@oneuptime/common 12.0.29 → 12.0.31

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 (664) hide show
  1. package/Models/AnalyticsModels/SecurityEvent.ts +48 -16
  2. package/Models/AnalyticsModels/ThreatIntelIndicator.ts +10 -5
  3. package/Models/DatabaseModels/AlertSeverity.ts +44 -0
  4. package/Models/DatabaseModels/DetectionRule.ts +16 -5
  5. package/Models/DatabaseModels/GoogleSecOpsConnection.ts +14 -5
  6. package/Models/DatabaseModels/IncidentSeverity.ts +44 -0
  7. package/Models/DatabaseModels/Index.ts +13 -0
  8. package/Models/DatabaseModels/NetworkDevice.ts +113 -3
  9. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +88 -0
  10. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +22 -0
  11. package/Models/DatabaseModels/NetworkDeviceOidTemplate.ts +499 -0
  12. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +43 -0
  13. package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +662 -0
  14. package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +584 -0
  15. package/Models/DatabaseModels/ThreatIntelFeed.ts +16 -5
  16. package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +546 -0
  17. package/Models/DatabaseModels/UserOnCallShiftReminder.ts +231 -0
  18. package/Models/DatabaseModels/UserOnCallShiftReminderLog.ts +331 -0
  19. package/Server/API/GlobalConfigAPI.ts +362 -183
  20. package/Server/API/OnCallCalendarAPI.ts +2194 -0
  21. package/Server/API/TelemetryAPI.ts +42 -4
  22. package/Server/EnvironmentConfig.ts +250 -0
  23. package/Server/Infrastructure/OnCallCalendarFeedCache.ts +1050 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.ts +253 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.ts +59 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.ts +25 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  28. package/Server/Middleware/MultipartFormData.ts +118 -32
  29. package/Server/Middleware/OnCallCalendarFeedRateLimit.ts +487 -0
  30. package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +9 -1
  31. package/Server/Services/AlertEpisodeOnCallRuleEngineService.ts +9 -1
  32. package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +9 -1
  33. package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +9 -1
  34. package/Server/Services/AlertGroupingEngineService.ts +9 -1
  35. package/Server/Services/AlertLabelRuleEngineService.ts +9 -1
  36. package/Server/Services/AlertOnCallRuleEngineService.ts +9 -1
  37. package/Server/Services/AlertOwnerRuleEngineService.ts +9 -1
  38. package/Server/Services/AlertPrivacyRuleEngineService.ts +9 -1
  39. package/Server/Services/AlertReminderRuleService.ts +9 -1
  40. package/Server/Services/AutoRemediationRuleEngineService.ts +9 -1
  41. package/Server/Services/CephClusterLabelRuleEngineService.ts +9 -1
  42. package/Server/Services/CephClusterOwnerRuleEngineService.ts +9 -1
  43. package/Server/Services/CloudResourceLabelRuleEngineService.ts +9 -1
  44. package/Server/Services/CloudResourceOwnerRuleEngineService.ts +9 -1
  45. package/Server/Services/DashboardLabelRuleEngineService.ts +9 -1
  46. package/Server/Services/DashboardOwnerRuleEngineService.ts +9 -1
  47. package/Server/Services/DockerHostLabelRuleEngineService.ts +9 -1
  48. package/Server/Services/DockerHostOwnerRuleEngineService.ts +9 -1
  49. package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +9 -1
  50. package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +9 -1
  51. package/Server/Services/HostLabelRuleEngineService.ts +9 -1
  52. package/Server/Services/HostOwnerRuleEngineService.ts +9 -1
  53. package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +9 -1
  54. package/Server/Services/IncidentEpisodeOnCallRuleEngineService.ts +9 -1
  55. package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +9 -1
  56. package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +9 -1
  57. package/Server/Services/IncidentGroupingEngineService.ts +9 -1
  58. package/Server/Services/IncidentLabelRuleEngineService.ts +9 -1
  59. package/Server/Services/IncidentOnCallRuleEngineService.ts +9 -1
  60. package/Server/Services/IncidentOwnerRuleEngineService.ts +9 -1
  61. package/Server/Services/IncidentPrivacyRuleEngineService.ts +9 -1
  62. package/Server/Services/IncidentReminderRuleService.ts +9 -1
  63. package/Server/Services/IncidentSlaRuleService.ts +9 -1
  64. package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +9 -1
  65. package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +9 -1
  66. package/Server/Services/Index.ts +14 -0
  67. package/Server/Services/IoTFleetLabelRuleEngineService.ts +9 -1
  68. package/Server/Services/IoTFleetOwnerRuleEngineService.ts +9 -1
  69. package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +9 -1
  70. package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +9 -1
  71. package/Server/Services/KubernetesResourceService.ts +5 -1
  72. package/Server/Services/MonitorLabelRuleEngineService.ts +9 -1
  73. package/Server/Services/MonitorOwnerRuleEngineService.ts +9 -1
  74. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +35 -0
  75. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +96 -0
  76. package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +9 -1
  77. package/Server/Services/NetworkDeviceOidTemplateService.ts +201 -0
  78. package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +9 -1
  79. package/Server/Services/NetworkDeviceService.ts +209 -1
  80. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +32 -0
  81. package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +9 -1
  82. package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +9 -1
  83. package/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.ts +260 -0
  84. package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +9 -1
  85. package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +70 -3
  86. package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +138 -3
  87. package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +9 -1
  88. package/Server/Services/OnCallDutyPolicyScheduleService.ts +1465 -134
  89. package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +167 -31
  90. package/Server/Services/PodmanHostLabelRuleEngineService.ts +9 -1
  91. package/Server/Services/PodmanHostOwnerRuleEngineService.ts +9 -1
  92. package/Server/Services/ProjectOnCallCalendarFeedService.ts +192 -0
  93. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +9 -1
  94. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +9 -1
  95. package/Server/Services/RumApplicationLabelRuleEngineService.ts +9 -1
  96. package/Server/Services/RumApplicationOwnerRuleEngineService.ts +9 -1
  97. package/Server/Services/RunbookLabelRuleEngineService.ts +9 -1
  98. package/Server/Services/RunbookOwnerRuleEngineService.ts +9 -1
  99. package/Server/Services/RunbookRuleEngineService.ts +9 -1
  100. package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +9 -1
  101. package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +9 -1
  102. package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +9 -1
  103. package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +9 -1
  104. package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +9 -1
  105. package/Server/Services/ServiceLabelRuleEngineService.ts +9 -1
  106. package/Server/Services/ServiceOwnerRuleEngineService.ts +9 -1
  107. package/Server/Services/StatusPageLabelRuleEngineService.ts +9 -1
  108. package/Server/Services/StatusPageMonitorRuleEngineService.ts +7 -0
  109. package/Server/Services/StatusPageOwnerRuleEngineService.ts +9 -1
  110. package/Server/Services/TeamMemberService.ts +489 -1
  111. package/Server/Services/TeamService.ts +50 -0
  112. package/Server/Services/TelemetrySourceMapService.ts +266 -23
  113. package/Server/Services/UserNotificationSettingService.ts +44 -1
  114. package/Server/Services/UserOnCallCalendarFeedService.ts +159 -0
  115. package/Server/Services/UserOnCallShiftReminderLogService.ts +151 -0
  116. package/Server/Services/UserOnCallShiftReminderService.ts +112 -0
  117. package/Server/Services/UserService.ts +27 -0
  118. package/Server/Services/WorkflowLabelRuleEngineService.ts +9 -1
  119. package/Server/Services/WorkflowOwnerRuleEngineService.ts +9 -1
  120. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +186 -0
  121. package/Server/Utils/Monitor/CapturedMetricAttributeUtil.ts +245 -0
  122. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +21 -2
  123. package/Server/Utils/Monitor/MonitorMetricUtil.ts +55 -21
  124. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +32 -0
  125. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +15 -2
  126. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +18 -1
  127. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +10 -0
  128. package/Server/Utils/Monitor/SeriesResourceLabels.ts +34 -0
  129. package/Server/Utils/OnCall/CalendarFeedToken.ts +241 -0
  130. package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1488 -0
  131. package/Server/Utils/OnCall/OnCallCalendarFeedUrls.ts +230 -0
  132. package/Server/Utils/OnCall/OnCallShiftChangeListeners.ts +227 -0
  133. package/Server/Utils/OnCall/OnCallShiftMaterializer.ts +1127 -0
  134. package/Server/Utils/OnCall/OnCallShiftReminderListener.ts +174 -0
  135. package/Server/Utils/OnCall/OnCallShiftReminderRunner.ts +2584 -0
  136. package/Server/Utils/Response.ts +134 -0
  137. package/Server/Utils/Rules/RuleEngineRuleRead.ts +48 -0
  138. package/Server/Utils/StartServer.ts +10 -0
  139. package/Server/Utils/Telemetry/AppMetrics.ts +51 -0
  140. package/Server/Utils/Telemetry/ExceptionSanitizer.ts +14 -1
  141. package/Server/Utils/Telemetry/LogExceptionExtractor.ts +14 -2
  142. package/Server/Utils/Telemetry/SourceMapResolver.ts +16 -5
  143. package/Server/Utils/Telemetry/StackTraceParser.ts +399 -0
  144. package/Tests/App/Dashboard/EventOverlayHook.test.tsx +125 -0
  145. package/Tests/App/Dashboard/HeaderImageAssets.test.tsx +93 -0
  146. package/Tests/App/Dashboard/OnCallCalendarFeedLinks.test.tsx +229 -0
  147. package/Tests/App/Dashboard/OnCallCalendarFeedPlanGate.test.tsx +489 -0
  148. package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +149 -0
  149. package/Tests/App/Dashboard/OnCallCalendarFeedUtil.test.ts +855 -0
  150. package/Tests/App/Dashboard/OnCallPersonalCalendarFeed.test.tsx +1209 -0
  151. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3 -3
  152. package/Tests/App/Dashboard/OnCallSharedCalendarFeedCard.test.tsx +1019 -0
  153. package/Tests/App/Dashboard/OnCallShiftRemindersAndUpcomingShifts.test.tsx +655 -0
  154. package/Tests/App/Dashboard/UserElementEmail.test.tsx +12 -4
  155. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +1 -1
  156. package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +73 -0
  157. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +14 -0
  158. package/Tests/Models/DatabaseModels/ModelRegistryInvariants.test.ts +469 -0
  159. package/Tests/Models/OnCallCalendarFeedModels.test.ts +642 -0
  160. package/Tests/Models/OnCallDutyPolicyScheduleCalendarFeed.test.ts +288 -0
  161. package/Tests/Models/OnCallDutyPolicyScheduleShiftConfigVersion.test.ts +88 -0
  162. package/Tests/Models/SecurityDomainAccessControl.test.ts +429 -0
  163. package/Tests/Models/UserOnCallShiftReminderModels.test.ts +368 -0
  164. package/Tests/Server/API/GlobalConfigLicense.test.ts +657 -0
  165. package/Tests/Server/API/Helpers.ts +8 -0
  166. package/Tests/Server/API/OnCallCalendarAPI.test.ts +4461 -0
  167. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +84 -6
  168. package/Tests/Server/API/TelemetryResolveStackTraceAPI.test.ts +805 -0
  169. package/Tests/Server/EnvironmentConfigOnCallCalendarFeed.test.ts +357 -0
  170. package/Tests/Server/Infrastructure/OnCallCalendarFeedCache.test.ts +1589 -0
  171. package/Tests/Server/Infrastructure/Postgres/AddOnCallCalendarFeedsMigration.test.ts +394 -0
  172. package/Tests/Server/Middleware/IdentityRateLimit.test.ts +1144 -0
  173. package/Tests/Server/Middleware/MultipartFormData.test.ts +618 -3
  174. package/Tests/Server/Middleware/OnCallCalendarFeedRateLimit.test.ts +1365 -0
  175. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +70 -0
  176. package/Tests/Server/Services/MonitorLabelRuleEngineScale.test.ts +520 -0
  177. package/Tests/Server/Services/NetworkDeviceOidTemplateService.test.ts +332 -0
  178. package/Tests/Server/Services/NetworkDeviceOidTemplateWriteGuards.test.ts +409 -0
  179. package/Tests/Server/Services/OnCallCalendarFeedServices.test.ts +1103 -0
  180. package/Tests/Server/Services/OnCallDutyPolicyScheduleResolver.test.ts +1037 -0
  181. package/Tests/Server/Services/OnCallShiftConfigPropagation.test.ts +1270 -0
  182. package/Tests/Server/Services/RuleEngineRuleFetchLimit.test.ts +239 -0
  183. package/Tests/Server/Services/TeamDeleteMemberCleanup.test.ts +156 -0
  184. package/Tests/Server/Services/TeamMemberOnCallCleanup.test.ts +755 -0
  185. package/Tests/Server/Services/TelemetrySourceMapService.test.ts +1210 -2
  186. package/Tests/Server/Services/UserNotificationSettingShiftReminderDefaults.test.ts +267 -0
  187. package/Tests/Server/Services/UserOnCallShiftReminderServices.test.ts +583 -0
  188. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +182 -0
  189. package/Tests/Server/Types/AnalyticsDatabase/SecurityEventModelPermission.test.ts +255 -0
  190. package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +254 -0
  191. package/Tests/Server/Types/Database/Permissions/ReadBlockPermission.test.ts +212 -0
  192. package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +413 -0
  193. package/Tests/Server/Utils/CodeRepository.test.ts +689 -0
  194. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +495 -0
  195. package/Tests/Server/Utils/ExceptionSanitizer.test.ts +77 -0
  196. package/Tests/Server/Utils/Monitor/CapturedMetricAttributeUtil.test.ts +284 -0
  197. package/Tests/Server/Utils/Monitor/MonitorCustomMetricAttributes.test.ts +503 -0
  198. package/Tests/Server/Utils/Monitor/MonitorTemplatePrototypePollution.test.ts +106 -0
  199. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkLogWritePath.test.ts +33 -4
  200. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +14 -4
  201. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +44 -0
  202. package/Tests/Server/Utils/OnCall/CalendarFeedToken.test.ts +467 -0
  203. package/Tests/Server/Utils/OnCall/OnCallCalendarFeedRenderer.test.ts +2142 -0
  204. package/Tests/Server/Utils/OnCall/OnCallCalendarFeedUrls.test.ts +278 -0
  205. package/Tests/Server/Utils/OnCall/OnCallResolverTestHarness.ts +440 -0
  206. package/Tests/Server/Utils/OnCall/OnCallShiftChangeListeners.test.ts +314 -0
  207. package/Tests/Server/Utils/OnCall/OnCallShiftMaterializer.test.ts +1502 -0
  208. package/Tests/Server/Utils/OnCall/OnCallShiftReminderListener.test.ts +491 -0
  209. package/Tests/Server/Utils/OnCall/OnCallShiftReminderRunner.test.ts +3088 -0
  210. package/Tests/Server/Utils/OnCall/OnCallShiftReminderTestHarness.ts +910 -0
  211. package/Tests/Server/Utils/OpenAPISpec.test.ts +536 -0
  212. package/Tests/Server/Utils/ResponseSendCalendarResponse.test.ts +561 -0
  213. package/Tests/Server/Utils/Rules/RuleEngineRuleRead.test.ts +115 -0
  214. package/Tests/Server/Utils/StackTraceParser.test.ts +610 -0
  215. package/Tests/Server/Utils/StartServerEncryptionSecretWarning.test.ts +64 -0
  216. package/Tests/Server/Utils/Telemetry/AppMetrics.test.ts +29 -0
  217. package/Tests/Server/Utils/Telemetry/LogExceptionExtractor.test.ts +0 -0
  218. package/Tests/Server/Utils/Telemetry/SourceMapLimits.test.ts +656 -0
  219. package/Tests/Server/Utils/Telemetry/SourceMapResolver.test.ts +100 -0
  220. package/Tests/Types/Calendar/ICalendar.test.ts +488 -0
  221. package/Tests/Types/Monitor/SnmpMonitor/SnmpOidListUtil.test.ts +454 -0
  222. package/Tests/Types/NotificationSetting/NotificationSettingEventType.test.ts +53 -0
  223. package/Tests/Types/OnCallDutyPolicy/CalendarFeedTestFixtures.ts +310 -0
  224. package/Tests/Types/OnCallDutyPolicy/CalendarFeedWindow.test.ts +205 -0
  225. package/Tests/Types/OnCallDutyPolicy/LayerUtilLayerMetaAndIterationCap.test.ts +458 -0
  226. package/Tests/Types/OnCallDutyPolicy/MaterializedShift.test.ts +197 -0
  227. package/Tests/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.test.ts +1986 -0
  228. package/Tests/Types/OnCallDutyPolicy/ScheduleShiftUtilGroupKey.test.ts +678 -0
  229. package/Tests/Types/OnCallDutyPolicy/ShiftSeamUtil.test.ts +417 -0
  230. package/Tests/Types/SecurityRolePermissions.test.ts +193 -0
  231. package/Tests/UI/Components/Charts/AnnotationLayout.test.ts +773 -0
  232. package/Tests/UI/Components/Charts/ChartAnnotationRail.test.tsx +789 -0
  233. package/Tests/UI/Components/Charts/ChartBucketIdentity.test.ts +254 -0
  234. package/Tests/UI/Components/Charts/TimeAnnotation.test.ts +471 -0
  235. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +405 -0
  236. package/Tests/UI/Components/ErrorMessageRefreshControl.test.tsx +83 -0
  237. package/Tests/UI/Components/MarkdownConverters.test.ts +686 -0
  238. package/Tests/UI/Components/ModelTable/BaseModelTableDeleteAndEmptyStates.test.tsx +341 -0
  239. package/Tests/UI/Components/OrderedStatesList.test.tsx +5 -5
  240. package/Tests/UI/Components/PendingProjectInvitations.test.tsx +1 -1
  241. package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +195 -0
  242. package/Tests/UI/Components/XAxis.test.ts +270 -5
  243. package/Tests/UI/Components/XAxisDaylightSaving.test.ts +113 -0
  244. package/Tests/UI/Styles/ChartFocusRing.test.ts +153 -0
  245. package/Tests/UI/Styles/ChartFocusRingCoverage.test.tsx +377 -0
  246. package/Tests/UI/Styles/ThemeStylesheet.ts +162 -0
  247. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  248. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  249. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +507 -0
  250. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +951 -1
  251. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +238 -0
  252. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +1056 -0
  253. package/Tests/Utils/NetworkDiscovery/ReverseDnsNameUtil.test.ts +882 -0
  254. package/Types/Calendar/ICalendar.ts +442 -0
  255. package/Types/Date.ts +39 -0
  256. package/Types/Email/EmailTemplateType.ts +2 -0
  257. package/Types/Monitor/SnmpMonitor/SnmpOidListUtil.ts +333 -0
  258. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  259. package/Types/OnCallDutyPolicy/CalendarFeedWindow.ts +140 -0
  260. package/Types/OnCallDutyPolicy/Layer.ts +190 -35
  261. package/Types/OnCallDutyPolicy/MaterializedShift.ts +274 -0
  262. package/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.ts +1415 -0
  263. package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +159 -4
  264. package/Types/OnCallDutyPolicy/ShiftSeamUtil.ts +106 -0
  265. package/Types/Permission.ts +96 -0
  266. package/Types/Rum/SessionReplay.ts +21 -0
  267. package/Types/Telemetry/SourceMap.ts +8 -0
  268. package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.tsx +176 -0
  269. package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.ts +745 -0
  270. package/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.tsx +576 -0
  271. package/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.tsx +204 -0
  272. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +491 -544
  273. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +324 -372
  274. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +487 -540
  275. package/UI/Components/Charts/ChartLibrary/Types/FormattedReferenceRegion.ts +7 -3
  276. package/UI/Components/Charts/ChartLibrary/Types/FormattedTimeReferenceLine.ts +14 -3
  277. package/UI/Components/Charts/Types/ChartEventKind.ts +13 -0
  278. package/UI/Components/Charts/Types/ReferenceRegionProps.ts +6 -0
  279. package/UI/Components/Charts/Types/TimeReferenceLineProps.ts +20 -3
  280. package/UI/Components/Charts/Utils/TimeAnnotation.ts +69 -35
  281. package/UI/Components/Charts/Utils/XAxis.ts +125 -18
  282. package/UI/Components/EditionLabel/EditionLabel.tsx +280 -26
  283. package/UI/Components/ErrorMessage/ErrorMessage.tsx +21 -10
  284. package/UI/Components/Feed/FeedItem.tsx +4 -5
  285. package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -2
  286. package/UI/Components/Header/UserProfile/UserProfile.tsx +1 -2
  287. package/UI/Components/Image/Image.tsx +20 -3
  288. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  289. package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +1 -2
  290. package/UI/Components/ModelTable/BaseModelTable.tsx +150 -24
  291. package/UI/Components/Table/TableHeader.tsx +64 -48
  292. package/UI/Components/Table/TableRow.tsx +13 -3
  293. package/UI/Styles/Theme.css +38 -0
  294. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +271 -0
  295. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +6 -0
  296. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +141 -10
  297. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +55 -3
  298. package/Utils/NetworkDiscovery/ReverseDnsNameUtil.ts +151 -0
  299. package/Utils/Rules/RuleEngineLimits.ts +32 -0
  300. package/build/dist/Models/AnalyticsModels/SecurityEvent.js +48 -16
  301. package/build/dist/Models/AnalyticsModels/SecurityEvent.js.map +1 -1
  302. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js +10 -5
  303. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js.map +1 -1
  304. package/build/dist/Models/DatabaseModels/AlertSeverity.js +46 -1
  305. package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
  306. package/build/dist/Models/DatabaseModels/DetectionRule.js +16 -5
  307. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  308. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +14 -5
  309. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
  310. package/build/dist/Models/DatabaseModels/IncidentSeverity.js +46 -1
  311. package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
  312. package/build/dist/Models/DatabaseModels/Index.js +13 -0
  313. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  314. package/build/dist/Models/DatabaseModels/NetworkDevice.js +115 -3
  315. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  316. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +88 -0
  317. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  318. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  319. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js +519 -0
  320. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js.map +1 -0
  321. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +44 -0
  322. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  323. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +699 -0
  324. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -0
  325. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +620 -0
  326. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -0
  327. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +16 -5
  328. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js.map +1 -1
  329. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +585 -0
  330. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -0
  331. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js +247 -0
  332. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js.map +1 -0
  333. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js +355 -0
  334. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js.map +1 -0
  335. package/build/dist/Server/API/GlobalConfigAPI.js +293 -176
  336. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  337. package/build/dist/Server/API/OnCallCalendarAPI.js +1371 -0
  338. package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -0
  339. package/build/dist/Server/API/TelemetryAPI.js +31 -3
  340. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  341. package/build/dist/Server/EnvironmentConfig.js +185 -0
  342. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  343. package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js +663 -0
  344. package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js.map +1 -0
  345. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js +103 -0
  346. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js.map +1 -0
  347. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js +26 -0
  348. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js.map +1 -0
  349. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js +14 -0
  350. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js.map +1 -0
  351. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  352. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  353. package/build/dist/Server/Middleware/MultipartFormData.js +93 -28
  354. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  355. package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js +342 -0
  356. package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js.map +1 -0
  357. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +8 -1
  358. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
  359. package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js +8 -1
  360. package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js.map +1 -1
  361. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +8 -1
  362. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
  363. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +8 -1
  364. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
  365. package/build/dist/Server/Services/AlertGroupingEngineService.js +8 -1
  366. package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
  367. package/build/dist/Server/Services/AlertLabelRuleEngineService.js +8 -1
  368. package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
  369. package/build/dist/Server/Services/AlertOnCallRuleEngineService.js +8 -1
  370. package/build/dist/Server/Services/AlertOnCallRuleEngineService.js.map +1 -1
  371. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +8 -1
  372. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
  373. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +8 -1
  374. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
  375. package/build/dist/Server/Services/AlertReminderRuleService.js +8 -1
  376. package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
  377. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +8 -1
  378. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  379. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +8 -1
  380. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
  381. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +8 -1
  382. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
  383. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +8 -1
  384. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
  385. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +8 -1
  386. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
  387. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +8 -1
  388. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
  389. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +8 -1
  390. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
  391. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +8 -1
  392. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
  393. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +8 -1
  394. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
  395. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +8 -1
  396. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
  397. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +8 -1
  398. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
  399. package/build/dist/Server/Services/HostLabelRuleEngineService.js +8 -1
  400. package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
  401. package/build/dist/Server/Services/HostOwnerRuleEngineService.js +8 -1
  402. package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
  403. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +8 -1
  404. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
  405. package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js +8 -1
  406. package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js.map +1 -1
  407. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +8 -1
  408. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
  409. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +8 -1
  410. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
  411. package/build/dist/Server/Services/IncidentGroupingEngineService.js +8 -1
  412. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  413. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +8 -1
  414. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
  415. package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js +8 -1
  416. package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js.map +1 -1
  417. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +8 -1
  418. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
  419. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +8 -1
  420. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
  421. package/build/dist/Server/Services/IncidentReminderRuleService.js +8 -1
  422. package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
  423. package/build/dist/Server/Services/IncidentSlaRuleService.js +8 -1
  424. package/build/dist/Server/Services/IncidentSlaRuleService.js.map +1 -1
  425. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +8 -1
  426. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
  427. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +8 -1
  428. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
  429. package/build/dist/Server/Services/Index.js +14 -0
  430. package/build/dist/Server/Services/Index.js.map +1 -1
  431. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +8 -1
  432. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
  433. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +8 -1
  434. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
  435. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +8 -1
  436. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
  437. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +8 -1
  438. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
  439. package/build/dist/Server/Services/KubernetesResourceService.js +5 -1
  440. package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -1
  441. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +8 -1
  442. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
  443. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +8 -1
  444. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
  445. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +30 -21
  446. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  447. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +64 -0
  448. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  449. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +8 -1
  450. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
  451. package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js +180 -0
  452. package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js.map +1 -0
  453. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +8 -1
  454. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
  455. package/build/dist/Server/Services/NetworkDeviceService.js +154 -1
  456. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  457. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +20 -0
  458. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  459. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +8 -1
  460. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
  461. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +8 -1
  462. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
  463. package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js +219 -0
  464. package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js.map +1 -0
  465. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +8 -1
  466. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
  467. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +47 -3
  468. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
  469. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +112 -3
  470. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
  471. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +8 -1
  472. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
  473. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +955 -9
  474. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  475. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +93 -6
  476. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
  477. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +8 -1
  478. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
  479. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +8 -1
  480. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
  481. package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js +157 -0
  482. package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js.map +1 -0
  483. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +8 -1
  484. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
  485. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +8 -1
  486. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
  487. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +8 -1
  488. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
  489. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +8 -1
  490. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
  491. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +8 -1
  492. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
  493. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +8 -1
  494. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
  495. package/build/dist/Server/Services/RunbookRuleEngineService.js +8 -1
  496. package/build/dist/Server/Services/RunbookRuleEngineService.js.map +1 -1
  497. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +8 -1
  498. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
  499. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +8 -1
  500. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
  501. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +8 -1
  502. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
  503. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +8 -1
  504. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
  505. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +8 -1
  506. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
  507. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +8 -1
  508. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
  509. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +8 -1
  510. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
  511. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +8 -1
  512. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
  513. package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +6 -0
  514. package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -1
  515. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +8 -1
  516. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
  517. package/build/dist/Server/Services/TeamMemberService.js +396 -1
  518. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  519. package/build/dist/Server/Services/TeamService.js +43 -0
  520. package/build/dist/Server/Services/TeamService.js.map +1 -1
  521. package/build/dist/Server/Services/TelemetrySourceMapService.js +213 -19
  522. package/build/dist/Server/Services/TelemetrySourceMapService.js.map +1 -1
  523. package/build/dist/Server/Services/UserNotificationSettingService.js +26 -1
  524. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  525. package/build/dist/Server/Services/UserOnCallCalendarFeedService.js +140 -0
  526. package/build/dist/Server/Services/UserOnCallCalendarFeedService.js.map +1 -0
  527. package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js +116 -0
  528. package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js.map +1 -0
  529. package/build/dist/Server/Services/UserOnCallShiftReminderService.js +92 -0
  530. package/build/dist/Server/Services/UserOnCallShiftReminderService.js.map +1 -0
  531. package/build/dist/Server/Services/UserService.js +25 -0
  532. package/build/dist/Server/Services/UserService.js.map +1 -1
  533. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +8 -1
  534. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
  535. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +8 -1
  536. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
  537. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +145 -0
  538. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +1 -0
  539. package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js +201 -0
  540. package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js.map +1 -0
  541. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +19 -2
  542. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  543. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +42 -23
  544. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  545. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +29 -0
  546. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  547. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +11 -2
  548. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  549. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +16 -1
  550. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  551. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +10 -0
  552. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  553. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +33 -0
  554. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  555. package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js +161 -0
  556. package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js.map +1 -0
  557. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js +983 -0
  558. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js.map +1 -0
  559. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js +155 -0
  560. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js.map +1 -0
  561. package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js +145 -0
  562. package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js.map +1 -0
  563. package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js +752 -0
  564. package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js.map +1 -0
  565. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js +92 -0
  566. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js.map +1 -0
  567. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js +1786 -0
  568. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js.map +1 -0
  569. package/build/dist/Server/Utils/Response.js +97 -0
  570. package/build/dist/Server/Utils/Response.js.map +1 -1
  571. package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js +37 -0
  572. package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js.map +1 -0
  573. package/build/dist/Server/Utils/StartServer.js +9 -1
  574. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  575. package/build/dist/Server/Utils/Telemetry/AppMetrics.js +41 -0
  576. package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
  577. package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js +12 -1
  578. package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js.map +1 -1
  579. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +14 -2
  580. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
  581. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js +15 -5
  582. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js.map +1 -1
  583. package/build/dist/Server/Utils/Telemetry/StackTraceParser.js +307 -0
  584. package/build/dist/Server/Utils/Telemetry/StackTraceParser.js.map +1 -1
  585. package/build/dist/Types/Calendar/ICalendar.js +290 -0
  586. package/build/dist/Types/Calendar/ICalendar.js.map +1 -0
  587. package/build/dist/Types/Date.js +27 -0
  588. package/build/dist/Types/Date.js.map +1 -1
  589. package/build/dist/Types/Email/EmailTemplateType.js +2 -0
  590. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  591. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js +253 -0
  592. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js.map +1 -0
  593. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  594. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  595. package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js +97 -0
  596. package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js.map +1 -0
  597. package/build/dist/Types/OnCallDutyPolicy/Layer.js +113 -19
  598. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  599. package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js +134 -0
  600. package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js.map +1 -0
  601. package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js +800 -0
  602. package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js.map +1 -0
  603. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +97 -3
  604. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
  605. package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js +77 -0
  606. package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js.map +1 -0
  607. package/build/dist/Types/Permission.js +86 -0
  608. package/build/dist/Types/Permission.js.map +1 -1
  609. package/build/dist/Types/Rum/SessionReplay.js +19 -0
  610. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  611. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js +83 -0
  612. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js.map +1 -0
  613. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js +531 -0
  614. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js.map +1 -0
  615. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js +264 -0
  616. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js.map +1 -0
  617. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js +122 -0
  618. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js.map +1 -0
  619. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +213 -233
  620. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  621. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +139 -152
  622. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  623. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +212 -232
  624. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  625. package/build/dist/UI/Components/Charts/Types/ChartEventKind.js +14 -0
  626. package/build/dist/UI/Components/Charts/Types/ChartEventKind.js.map +1 -0
  627. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +57 -28
  628. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -1
  629. package/build/dist/UI/Components/Charts/Utils/XAxis.js +103 -17
  630. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  631. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +198 -23
  632. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  633. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +15 -5
  634. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
  635. package/build/dist/UI/Components/Feed/FeedItem.js +4 -5
  636. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  637. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -2
  638. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  639. package/build/dist/UI/Components/Header/UserProfile/UserProfile.js.map +1 -1
  640. package/build/dist/UI/Components/Image/Image.js +6 -1
  641. package/build/dist/UI/Components/Image/Image.js.map +1 -1
  642. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  643. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  644. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +1 -2
  645. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
  646. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +104 -23
  647. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  648. package/build/dist/UI/Components/Table/TableHeader.js +20 -22
  649. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  650. package/build/dist/UI/Components/Table/TableRow.js +13 -4
  651. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  652. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +153 -0
  653. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -0
  654. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  655. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +127 -7
  656. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  657. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +50 -3
  658. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
  659. package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js +132 -0
  660. package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js.map +1 -0
  661. package/build/dist/Utils/Rules/RuleEngineLimits.js +31 -0
  662. package/build/dist/Utils/Rules/RuleEngineLimits.js.map +1 -0
  663. package/jest.config.json +1 -0
  664. package/package.json +2 -2
@@ -0,0 +1,1127 @@
1
+ import crypto from "crypto";
2
+ import OnCallDutyPolicyScheduleService, {
3
+ ResolvedShiftSegments,
4
+ } from "../../Services/OnCallDutyPolicyScheduleService";
5
+ import OnCallDutyPolicyScheduleLayerUserService from "../../Services/OnCallDutyPolicyScheduleLayerUserService";
6
+ import OnCallDutyPolicyUserOverrideService from "../../Services/OnCallDutyPolicyUserOverrideService";
7
+ import ProjectService from "../../Services/ProjectService";
8
+ import UserService from "../../Services/UserService";
9
+ import QueryHelper from "../../Types/Database/QueryHelper";
10
+ import CaptureSpan from "../Telemetry/CaptureSpan";
11
+ import OnCallDutyPolicySchedule from "../../../Models/DatabaseModels/OnCallDutyPolicySchedule";
12
+ import OnCallDutyPolicyScheduleLayerUser from "../../../Models/DatabaseModels/OnCallDutyPolicyScheduleLayerUser";
13
+ import OnCallDutyPolicyUserOverride from "../../../Models/DatabaseModels/OnCallDutyPolicyUserOverride";
14
+ import Project from "../../../Models/DatabaseModels/Project";
15
+ import User from "../../../Models/DatabaseModels/User";
16
+ import CalendarEvent from "../../../Types/Calendar/CalendarEvent";
17
+ import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
18
+ import OneUptimeDate from "../../../Types/Date";
19
+ import BadDataException from "../../../Types/Exception/BadDataException";
20
+ import ObjectID from "../../../Types/ObjectID";
21
+ import { FEED_SIMULATION_ITERATION_CAP } from "../../../Types/OnCallDutyPolicy/CalendarFeedWindow";
22
+ import { LayerProps } from "../../../Types/OnCallDutyPolicy/Layer";
23
+ import MaterializedShiftUtil, {
24
+ MaterializedShift,
25
+ MaterializedShiftOverride,
26
+ MaterializedShiftPolicy,
27
+ } from "../../../Types/OnCallDutyPolicy/MaterializedShift";
28
+ import OnCallCalendarFeedUtil from "../../../Types/OnCallDutyPolicy/OnCallCalendarFeedUtil";
29
+ import ScheduleShiftUtil, {
30
+ OnCallShift,
31
+ } from "../../../Types/OnCallDutyPolicy/ScheduleShiftUtil";
32
+ import ShiftSeamUtil from "../../../Types/OnCallDutyPolicy/ShiftSeamUtil";
33
+ import { UserOverrideRecord } from "../../../Types/OnCallDutyPolicy/UserOverrideUtil";
34
+
35
+ /*
36
+ * Turns the resolver's raw coverage segments into MaterializedShifts — the
37
+ * one shape the calendar feeds, /my-shifts and the shift reminders consume.
38
+ *
39
+ * Per schedule, in this order:
40
+ * 1. ScheduleShiftUtil.groupEventsIntoShifts with mergeAcrossGaps = false
41
+ * and a group key of user + override identity + layer, so a restricted
42
+ * layer yields one shift per active block, an override split yields
43
+ * A / B / A as three shifts, and a layer handover is a boundary.
44
+ * 2. ShiftSeamUtil.normalizeSeams: the engine's one-second seams become
45
+ * touching, minute-aligned boundaries. Every identity below (shiftKey,
46
+ * the calendar UID, the reminder idempotency key) is derived AFTER this
47
+ * step, which is what makes it stable across windows and edits.
48
+ * 3. Policy-variant diffing: for a schedule attached to several policies
49
+ * with a policy-scoped override, the per-policy resolution is compared
50
+ * with the base one and every interval where a DIFFERENT person is
51
+ * paged becomes an extra shift tagged policyVariantOf.
52
+ * 4. One user lookup for display names and timezones, one project lookup
53
+ * for project names.
54
+ *
55
+ * The public entry points differ only in how they choose schedules:
56
+ * - materializeForSchedule(s): everything on those schedules (shared feeds,
57
+ * the schedule-level cache, the reminder sweep);
58
+ * - materializeForUser: the schedules the user is rostered on, plus (when
59
+ * includeCoveringShifts) the schedules of people the user substitutes
60
+ * for, filtered down to the user's own shifts;
61
+ * - materializeForProject: every schedule in the project.
62
+ * Standing escalation targets (direct users, teams) have no start and end
63
+ * and are deliberately never emitted.
64
+ */
65
+
66
+ export interface MaterializedUserInfo {
67
+ userId: string;
68
+ userName: string;
69
+ email?: string;
70
+ timezone?: string;
71
+ }
72
+
73
+ export interface MaterializedScheduleInfo {
74
+ scheduleId: string;
75
+ scheduleName: string;
76
+ projectId: string;
77
+ projectName?: string;
78
+ scheduleTimezone?: string;
79
+ shiftConfigVersion: number;
80
+ lastModifiedAt: Date;
81
+ truncated: boolean;
82
+ attachedPolicies: Array<MaterializedShiftPolicy>;
83
+ // The engine input, for the coverage envelope (OnCallCalendarFeedUtil).
84
+ layerProps: Array<LayerProps>;
85
+ scheduleUserIds: Array<string>;
86
+ }
87
+
88
+ export interface MaterializeResult {
89
+ shifts: Array<MaterializedShift>;
90
+ // True when any schedule's expansion hit the iteration cap.
91
+ truncated: boolean;
92
+ schedules: Array<MaterializedScheduleInfo>;
93
+ users: Array<MaterializedUserInfo>;
94
+ generatedAt: Date;
95
+ }
96
+
97
+ interface MaterializeWindowOptions {
98
+ windowStart: Date;
99
+ windowEnd: Date;
100
+ // "now" for isPast; defaults to the clock.
101
+ now?: Date | undefined;
102
+ // Defaults to FEED_SIMULATION_ITERATION_CAP.
103
+ maxSimulationIterations?: number | undefined;
104
+ }
105
+
106
+ export interface MaterializeForScheduleOptions
107
+ extends MaterializeWindowOptions {
108
+ scheduleId: ObjectID;
109
+ }
110
+
111
+ export interface MaterializeForSchedulesOptions
112
+ extends MaterializeWindowOptions {
113
+ scheduleIds: Array<ObjectID>;
114
+ }
115
+
116
+ export interface MaterializeForUserOptions extends MaterializeWindowOptions {
117
+ userId: ObjectID;
118
+ // Restrict to these projects; every project the user is rostered in otherwise.
119
+ projectIds?: Array<ObjectID> | undefined;
120
+ // Restrict to one schedule (the `?schedule=` feed filter).
121
+ scheduleId?: ObjectID | undefined;
122
+ // Include shifts the user covers as a substitute on other people's schedules.
123
+ includeCoveringShifts: boolean;
124
+ }
125
+
126
+ export interface MaterializeForProjectOptions extends MaterializeWindowOptions {
127
+ projectId: ObjectID;
128
+ }
129
+
130
+ export interface MaterializeResolvedOptions {
131
+ now: Date;
132
+ users: Map<string, MaterializedUserInfo>;
133
+ projectName?: string | undefined;
134
+ }
135
+
136
+ export default class OnCallShiftMaterializer {
137
+ // -- Entry points -----------------------------------------------------
138
+
139
+ @CaptureSpan()
140
+ public static async materializeForSchedule(
141
+ options: MaterializeForScheduleOptions,
142
+ ): Promise<MaterializeResult> {
143
+ return await OnCallShiftMaterializer.materializeForSchedules({
144
+ scheduleIds: [options.scheduleId],
145
+ windowStart: options.windowStart,
146
+ windowEnd: options.windowEnd,
147
+ now: options.now,
148
+ maxSimulationIterations: options.maxSimulationIterations,
149
+ });
150
+ }
151
+
152
+ @CaptureSpan()
153
+ public static async materializeForSchedules(
154
+ options: MaterializeForSchedulesOptions,
155
+ ): Promise<MaterializeResult> {
156
+ OnCallShiftMaterializer.validateWindow(
157
+ options.windowStart,
158
+ options.windowEnd,
159
+ );
160
+
161
+ const now: Date = options.now || OneUptimeDate.getCurrentDate();
162
+ const scheduleIds: Array<ObjectID> = OnCallShiftMaterializer.dedupeIds(
163
+ options.scheduleIds,
164
+ );
165
+
166
+ if (scheduleIds.length === 0) {
167
+ return OnCallShiftMaterializer.emptyResult(now);
168
+ }
169
+
170
+ const resolved: Array<ResolvedShiftSegments> =
171
+ await OnCallDutyPolicyScheduleService.getResolvedShiftSegmentsForSchedules(
172
+ {
173
+ scheduleIds,
174
+ windowStart: options.windowStart,
175
+ windowEnd: options.windowEnd,
176
+ maxSimulationIterations:
177
+ options.maxSimulationIterations ?? FEED_SIMULATION_ITERATION_CAP,
178
+ },
179
+ );
180
+
181
+ if (resolved.length === 0) {
182
+ return OnCallShiftMaterializer.emptyResult(now);
183
+ }
184
+
185
+ const users: Map<string, MaterializedUserInfo> =
186
+ await OnCallShiftMaterializer.loadUsers(
187
+ OnCallShiftMaterializer.collectUserIds(resolved),
188
+ );
189
+
190
+ const projectNames: Map<string, string> =
191
+ await OnCallShiftMaterializer.loadProjectNames(
192
+ resolved.map((item: ResolvedShiftSegments) => {
193
+ return item.schedule.projectId;
194
+ }),
195
+ );
196
+
197
+ const shifts: Array<MaterializedShift> = [];
198
+ const schedules: Array<MaterializedScheduleInfo> = [];
199
+ let truncated: boolean = false;
200
+
201
+ for (const item of resolved) {
202
+ const projectName: string | undefined = projectNames.get(
203
+ item.schedule.projectId,
204
+ );
205
+
206
+ shifts.push(
207
+ ...OnCallShiftMaterializer.materializeResolved(item, {
208
+ now,
209
+ users,
210
+ projectName,
211
+ }),
212
+ );
213
+
214
+ const info: MaterializedScheduleInfo = {
215
+ scheduleId: item.schedule.id,
216
+ scheduleName: item.schedule.name,
217
+ projectId: item.schedule.projectId,
218
+ shiftConfigVersion: item.schedule.shiftConfigVersion,
219
+ lastModifiedAt: item.lastModifiedAt,
220
+ truncated: item.truncated,
221
+ attachedPolicies: item.attachedPolicies,
222
+ layerProps: item.layerProps,
223
+ scheduleUserIds: item.scheduleUserIds,
224
+ };
225
+
226
+ if (projectName !== undefined) {
227
+ info.projectName = projectName;
228
+ }
229
+
230
+ if (item.schedule.timezone !== undefined) {
231
+ info.scheduleTimezone = item.schedule.timezone;
232
+ }
233
+
234
+ schedules.push(info);
235
+ truncated = truncated || item.truncated;
236
+ }
237
+
238
+ return {
239
+ shifts: MaterializedShiftUtil.sortByStart(shifts),
240
+ truncated,
241
+ schedules,
242
+ users: Array.from(users.values()),
243
+ generatedAt: now,
244
+ };
245
+ }
246
+
247
+ @CaptureSpan()
248
+ public static async materializeForUser(
249
+ options: MaterializeForUserOptions,
250
+ ): Promise<MaterializeResult> {
251
+ OnCallShiftMaterializer.validateWindow(
252
+ options.windowStart,
253
+ options.windowEnd,
254
+ );
255
+
256
+ const now: Date = options.now || OneUptimeDate.getCurrentDate();
257
+
258
+ const candidateScheduleIds: Array<ObjectID> =
259
+ await OnCallShiftMaterializer.getCandidateScheduleIdsForUser({
260
+ userId: options.userId,
261
+ projectIds: options.projectIds,
262
+ scheduleId: options.scheduleId,
263
+ windowStart: options.windowStart,
264
+ windowEnd: options.windowEnd,
265
+ includeCoveringShifts: options.includeCoveringShifts,
266
+ });
267
+
268
+ if (candidateScheduleIds.length === 0) {
269
+ return OnCallShiftMaterializer.emptyResult(now);
270
+ }
271
+
272
+ const result: MaterializeResult =
273
+ await OnCallShiftMaterializer.materializeForSchedules({
274
+ scheduleIds: candidateScheduleIds,
275
+ windowStart: options.windowStart,
276
+ windowEnd: options.windowEnd,
277
+ now,
278
+ maxSimulationIterations: options.maxSimulationIterations,
279
+ });
280
+
281
+ return {
282
+ ...result,
283
+ shifts: OnCallShiftMaterializer.filterShiftsForUser(
284
+ result.shifts,
285
+ options.userId,
286
+ ),
287
+ };
288
+ }
289
+
290
+ @CaptureSpan()
291
+ public static async materializeForProject(
292
+ options: MaterializeForProjectOptions,
293
+ ): Promise<MaterializeResult> {
294
+ OnCallShiftMaterializer.validateWindow(
295
+ options.windowStart,
296
+ options.windowEnd,
297
+ );
298
+
299
+ const now: Date = options.now || OneUptimeDate.getCurrentDate();
300
+
301
+ const schedules: Array<OnCallDutyPolicySchedule> =
302
+ await OnCallDutyPolicyScheduleService.findBy({
303
+ query: {
304
+ projectId: options.projectId,
305
+ },
306
+ select: {
307
+ _id: true,
308
+ },
309
+ limit: LIMIT_PER_PROJECT,
310
+ skip: 0,
311
+ props: {
312
+ isRoot: true,
313
+ },
314
+ });
315
+
316
+ const scheduleIds: Array<ObjectID> = schedules
317
+ .map((schedule: OnCallDutyPolicySchedule) => {
318
+ return schedule.id;
319
+ })
320
+ .filter((id: ObjectID | null | undefined): id is ObjectID => {
321
+ return Boolean(id);
322
+ });
323
+
324
+ if (scheduleIds.length === 0) {
325
+ return OnCallShiftMaterializer.emptyResult(now);
326
+ }
327
+
328
+ return await OnCallShiftMaterializer.materializeForSchedules({
329
+ scheduleIds,
330
+ windowStart: options.windowStart,
331
+ windowEnd: options.windowEnd,
332
+ now,
333
+ maxSimulationIterations: options.maxSimulationIterations,
334
+ });
335
+ }
336
+
337
+ // -- Candidate schedules ----------------------------------------------
338
+
339
+ /**
340
+ * The schedules whose materialization can contain the user's shifts:
341
+ * distinct schedule ids from the user's layer-user rows (optionally within
342
+ * `projectIds`), plus — when includeCoveringShifts — the schedules of every
343
+ * user the caller substitutes for through an override overlapping the
344
+ * window. Optionally narrowed to one schedule. Root reads: the caller has
345
+ * already decided the user may see these.
346
+ *
347
+ * One user, 2-3 queries. Anything that needs this for a GROUP of users
348
+ * (the reminder sweep and its change pass walk every reminded user of a
349
+ * project on every tick) must call getCandidateScheduleIdsForUsers, which
350
+ * answers the whole group in the same 2-3 queries.
351
+ */
352
+ @CaptureSpan()
353
+ public static async getCandidateScheduleIdsForUser(data: {
354
+ userId: ObjectID;
355
+ projectIds?: Array<ObjectID> | undefined;
356
+ scheduleId?: ObjectID | undefined;
357
+ windowStart: Date;
358
+ windowEnd: Date;
359
+ includeCoveringShifts: boolean;
360
+ }): Promise<Array<ObjectID>> {
361
+ const byUser: Map<
362
+ string,
363
+ Array<ObjectID>
364
+ > = await OnCallShiftMaterializer.getCandidateScheduleIdsForUsers({
365
+ userIds: [data.userId],
366
+ projectIds: data.projectIds,
367
+ scheduleId: data.scheduleId,
368
+ windowStart: data.windowStart,
369
+ windowEnd: data.windowEnd,
370
+ includeCoveringShifts: data.includeCoveringShifts,
371
+ });
372
+
373
+ return byUser.get(data.userId.toString()) || [];
374
+ }
375
+
376
+ /**
377
+ * The batched form of getCandidateScheduleIdsForUser: the candidate
378
+ * schedules of MANY users in the same two or three queries it takes for
379
+ * one, keyed by user id (every requested user gets an entry, empty when
380
+ * they are on nothing). Semantics per user are identical — own layer-user
381
+ * rows, plus the schedules of the people that user substitutes for through
382
+ * an override overlapping the window, narrowed to `scheduleId` when given.
383
+ *
384
+ * The covering overrides are matched back to the SUBSTITUTE that each one
385
+ * routes to, so one user's coverage never leaks into another's list.
386
+ */
387
+ @CaptureSpan()
388
+ public static async getCandidateScheduleIdsForUsers(data: {
389
+ userIds: Array<ObjectID>;
390
+ projectIds?: Array<ObjectID> | undefined;
391
+ scheduleId?: ObjectID | undefined;
392
+ windowStart: Date;
393
+ windowEnd: Date;
394
+ includeCoveringShifts: boolean;
395
+ }): Promise<Map<string, Array<ObjectID>>> {
396
+ const userIds: Array<ObjectID> = OnCallShiftMaterializer.dedupeIds(
397
+ data.userIds,
398
+ );
399
+
400
+ const candidatesByUser: Map<string, Array<ObjectID>> = new Map<
401
+ string,
402
+ Array<ObjectID>
403
+ >();
404
+
405
+ for (const userId of userIds) {
406
+ candidatesByUser.set(userId.toString(), []);
407
+ }
408
+
409
+ if (userIds.length === 0) {
410
+ return candidatesByUser;
411
+ }
412
+
413
+ const projectFilter: Array<ObjectID> | undefined =
414
+ data.projectIds && data.projectIds.length > 0
415
+ ? OnCallShiftMaterializer.dedupeIds(data.projectIds)
416
+ : undefined;
417
+
418
+ const ownRows: Array<OnCallDutyPolicyScheduleLayerUser> =
419
+ await OnCallDutyPolicyScheduleLayerUserService.findBy({
420
+ query: projectFilter
421
+ ? {
422
+ userId: QueryHelper.any(userIds),
423
+ projectId: QueryHelper.any(projectFilter),
424
+ }
425
+ : {
426
+ userId: QueryHelper.any(userIds),
427
+ },
428
+ select: {
429
+ onCallDutyPolicyScheduleId: true,
430
+ projectId: true,
431
+ userId: true,
432
+ },
433
+ limit: LIMIT_PER_PROJECT,
434
+ skip: 0,
435
+ props: {
436
+ isRoot: true,
437
+ },
438
+ });
439
+
440
+ for (const row of ownRows) {
441
+ const userKey: string = row.userId?.toString() || "";
442
+ const candidates: Array<ObjectID> | undefined =
443
+ candidatesByUser.get(userKey);
444
+
445
+ if (!candidates || !row.onCallDutyPolicyScheduleId) {
446
+ continue;
447
+ }
448
+
449
+ candidates.push(row.onCallDutyPolicyScheduleId);
450
+ }
451
+
452
+ if (data.includeCoveringShifts) {
453
+ const coveringOverrides: Array<OnCallDutyPolicyUserOverride> =
454
+ await OnCallDutyPolicyUserOverrideService.findBy({
455
+ query: projectFilter
456
+ ? {
457
+ routeAlertsToUserId: QueryHelper.any(userIds),
458
+ projectId: QueryHelper.any(projectFilter),
459
+ startsAt: QueryHelper.lessThanEqualTo(data.windowEnd),
460
+ endsAt: QueryHelper.greaterThanEqualTo(data.windowStart),
461
+ }
462
+ : {
463
+ routeAlertsToUserId: QueryHelper.any(userIds),
464
+ startsAt: QueryHelper.lessThanEqualTo(data.windowEnd),
465
+ endsAt: QueryHelper.greaterThanEqualTo(data.windowStart),
466
+ },
467
+ select: {
468
+ projectId: true,
469
+ overrideUserId: true,
470
+ routeAlertsToUserId: true,
471
+ startsAt: true,
472
+ endsAt: true,
473
+ },
474
+ limit: LIMIT_PER_PROJECT,
475
+ skip: 0,
476
+ props: {
477
+ isRoot: true,
478
+ },
479
+ });
480
+
481
+ // substitute -> the (project, overridden user) pairs THEY cover.
482
+ const pairsByUser: Map<string, Set<string>> = new Map<
483
+ string,
484
+ Set<string>
485
+ >();
486
+ const overriddenUserIds: Array<ObjectID> = [];
487
+ const overrideProjectIds: Array<ObjectID> = [];
488
+
489
+ for (const override of coveringOverrides) {
490
+ const overriddenUserId: ObjectID | undefined = override.overrideUserId;
491
+ const projectId: ObjectID | undefined = override.projectId;
492
+ const substituteKey: string =
493
+ override.routeAlertsToUserId?.toString() || "";
494
+
495
+ if (
496
+ !overriddenUserId ||
497
+ !projectId ||
498
+ !candidatesByUser.has(substituteKey)
499
+ ) {
500
+ continue;
501
+ }
502
+
503
+ if (
504
+ override.startsAt &&
505
+ override.endsAt &&
506
+ (OneUptimeDate.isAfter(override.startsAt, data.windowEnd) ||
507
+ OneUptimeDate.isBefore(override.endsAt, data.windowStart))
508
+ ) {
509
+ continue;
510
+ }
511
+
512
+ let pairs: Set<string> | undefined = pairsByUser.get(substituteKey);
513
+
514
+ if (!pairs) {
515
+ pairs = new Set<string>();
516
+ pairsByUser.set(substituteKey, pairs);
517
+ }
518
+
519
+ pairs.add(`${projectId.toString()}:${overriddenUserId.toString()}`);
520
+ overriddenUserIds.push(overriddenUserId);
521
+ overrideProjectIds.push(projectId);
522
+ }
523
+
524
+ if (pairsByUser.size > 0) {
525
+ const coveredRows: Array<OnCallDutyPolicyScheduleLayerUser> =
526
+ await OnCallDutyPolicyScheduleLayerUserService.findBy({
527
+ query: {
528
+ userId: QueryHelper.any(
529
+ OnCallShiftMaterializer.dedupeIds(overriddenUserIds),
530
+ ),
531
+ projectId: QueryHelper.any(
532
+ OnCallShiftMaterializer.dedupeIds(overrideProjectIds),
533
+ ),
534
+ },
535
+ select: {
536
+ onCallDutyPolicyScheduleId: true,
537
+ projectId: true,
538
+ userId: true,
539
+ },
540
+ limit: LIMIT_PER_PROJECT,
541
+ skip: 0,
542
+ props: {
543
+ isRoot: true,
544
+ },
545
+ });
546
+
547
+ for (const row of coveredRows) {
548
+ const key: string = `${row.projectId?.toString() || ""}:${
549
+ row.userId?.toString() || ""
550
+ }`;
551
+
552
+ if (!row.onCallDutyPolicyScheduleId) {
553
+ continue;
554
+ }
555
+
556
+ for (const [substituteKey, pairs] of pairsByUser) {
557
+ if (pairs.has(key)) {
558
+ candidatesByUser
559
+ .get(substituteKey)
560
+ ?.push(row.onCallDutyPolicyScheduleId);
561
+ }
562
+ }
563
+ }
564
+ }
565
+ }
566
+
567
+ const wanted: string | undefined = data.scheduleId?.toString();
568
+
569
+ for (const [userKey, candidates] of candidatesByUser) {
570
+ let deduped: Array<ObjectID> =
571
+ OnCallShiftMaterializer.dedupeIds(candidates);
572
+
573
+ if (wanted) {
574
+ deduped = deduped.filter((id: ObjectID) => {
575
+ return id.toString() === wanted;
576
+ });
577
+ }
578
+
579
+ candidatesByUser.set(userKey, deduped);
580
+ }
581
+
582
+ return candidatesByUser;
583
+ }
584
+
585
+ // -- Pure materialization ---------------------------------------------
586
+
587
+ /**
588
+ * Materialize ONE resolved schedule: base shifts plus policy-variant
589
+ * shifts. Pure — every lookup has already happened.
590
+ */
591
+ public static materializeResolved(
592
+ resolved: ResolvedShiftSegments,
593
+ options: MaterializeResolvedOptions,
594
+ ): Array<MaterializedShift> {
595
+ const baseShifts: Array<OnCallShift> = OnCallShiftMaterializer.toShifts(
596
+ resolved.segments,
597
+ );
598
+
599
+ const shifts: Array<MaterializedShift> = baseShifts.map(
600
+ (shift: OnCallShift) => {
601
+ return OnCallShiftMaterializer.toMaterializedShift({
602
+ shift,
603
+ resolved,
604
+ options,
605
+ policyVariant: null,
606
+ });
607
+ },
608
+ );
609
+
610
+ for (const variant of resolved.policyVariants) {
611
+ const variantShifts: Array<OnCallShift> =
612
+ OnCallShiftMaterializer.toShifts(variant.segments);
613
+
614
+ const differing: Array<{ shift: OnCallShift; globalUserId: string }> =
615
+ OnCallShiftMaterializer.diffPolicyVariant(baseShifts, variantShifts);
616
+
617
+ for (const entry of differing) {
618
+ shifts.push(
619
+ OnCallShiftMaterializer.toMaterializedShift({
620
+ shift: entry.shift,
621
+ resolved,
622
+ options,
623
+ policyVariant: {
624
+ policyId: variant.policyId,
625
+ policyName: variant.policyName,
626
+ globalUserId: entry.globalUserId,
627
+ },
628
+ }),
629
+ );
630
+ }
631
+ }
632
+
633
+ return MaterializedShiftUtil.sortByStart(shifts);
634
+ }
635
+
636
+ /*
637
+ * Group + seam-normalise raw segments into shifts. Exposed so tests and
638
+ * the coverage-gap logic can reproduce exactly what the feed sees.
639
+ */
640
+ public static toShifts(segments: Array<CalendarEvent>): Array<OnCallShift> {
641
+ const grouped: Array<OnCallShift> = ScheduleShiftUtil.groupEventsIntoShifts(
642
+ segments,
643
+ {
644
+ mergeAcrossGaps: false,
645
+ groupKey: ScheduleShiftUtil.groupKeyByUserOverrideAndLayer,
646
+ },
647
+ );
648
+
649
+ /*
650
+ * Seam normalisation widens a shift by the engine's one-second seams;
651
+ * with mergeAcrossGaps = false every shift is one contiguous block, so
652
+ * its honest active time is exactly its span. Recompute rather than
653
+ * carry the pre-normalisation sum, which would read 28799 for an 8-hour
654
+ * block.
655
+ */
656
+ return ShiftSeamUtil.normalizeSeams(grouped)
657
+ .filter((shift: OnCallShift) => {
658
+ return shift.end.getTime() > shift.start.getTime();
659
+ })
660
+ .map((shift: OnCallShift) => {
661
+ return {
662
+ ...shift,
663
+ coverageSeconds: Math.round(
664
+ (shift.end.getTime() - shift.start.getTime()) / 1000,
665
+ ),
666
+ };
667
+ });
668
+ }
669
+
670
+ /*
671
+ * The variant shifts during which a DIFFERENT person is paged than in the
672
+ * base resolution. A variant shift whose whole span is covered by base
673
+ * shifts of the same user is identical for the subscriber and dropped; one
674
+ * that overlaps a base shift of another user (or no base shift at all) is
675
+ * kept, together with who the base resolution pages at its start.
676
+ */
677
+ public static diffPolicyVariant(
678
+ baseShifts: Array<OnCallShift>,
679
+ variantShifts: Array<OnCallShift>,
680
+ ): Array<{ shift: OnCallShift; globalUserId: string }> {
681
+ const result: Array<{ shift: OnCallShift; globalUserId: string }> = [];
682
+
683
+ for (const variant of variantShifts) {
684
+ const overlapping: Array<OnCallShift> = baseShifts.filter(
685
+ (base: OnCallShift) => {
686
+ return (
687
+ base.start.getTime() < variant.end.getTime() &&
688
+ base.end.getTime() > variant.start.getTime()
689
+ );
690
+ },
691
+ );
692
+
693
+ const differingBase: OnCallShift | undefined = overlapping.find(
694
+ (base: OnCallShift) => {
695
+ return base.userId !== variant.userId;
696
+ },
697
+ );
698
+
699
+ if (overlapping.length > 0 && !differingBase) {
700
+ continue; // same person throughout: nothing policy-specific here.
701
+ }
702
+
703
+ const globalUserId: string =
704
+ differingBase?.userId ||
705
+ variant.override?.originalUserId ||
706
+ variant.userId;
707
+
708
+ result.push({ shift: variant, globalUserId });
709
+ }
710
+
711
+ return result;
712
+ }
713
+
714
+ /** Keep only the shifts where `userId` is the person on call. */
715
+ public static filterShiftsForUser(
716
+ shifts: Array<MaterializedShift>,
717
+ userId: ObjectID | string,
718
+ ): Array<MaterializedShift> {
719
+ const wanted: string = userId.toString();
720
+ return shifts.filter((shift: MaterializedShift) => {
721
+ return shift.userId === wanted;
722
+ });
723
+ }
724
+
725
+ /*
726
+ * sha256 over every field that changes what a subscriber sees for this
727
+ * shift, excluding the identity (shiftKey), the version and the
728
+ * modification stamp, so two renders of an unchanged shift hash the same
729
+ * and any content change — the person, the end, the layer, the policies,
730
+ * the override provenance — changes the hash.
731
+ */
732
+ public static computeContentHash(
733
+ shift: Omit<
734
+ MaterializedShift,
735
+ "contentHash" | "shiftKey" | "lastModifiedAt" | "shiftConfigVersion"
736
+ >,
737
+ ): string {
738
+ const payload: Record<string, unknown> = {
739
+ scheduleId: shift.scheduleId,
740
+ scheduleName: shift.scheduleName,
741
+ scheduleTimezone: shift.scheduleTimezone ?? null,
742
+ projectName: shift.projectName ?? null,
743
+ userId: shift.userId,
744
+ userName: shift.userName,
745
+ start: shift.start.toISOString(),
746
+ end: shift.end.toISOString(),
747
+ coverageSeconds: shift.coverageSeconds,
748
+ layerId: shift.layerId ?? null,
749
+ layerName: shift.layerName ?? null,
750
+ override: shift.override
751
+ ? {
752
+ originalUserId: shift.override.originalUserId,
753
+ originalUserName: shift.override.originalUserName,
754
+ overrideStartsAt: shift.override.overrideStartsAt.toISOString(),
755
+ overrideEndsAt: shift.override.overrideEndsAt.toISOString(),
756
+ onCallDutyPolicyId: shift.override.onCallDutyPolicyId ?? null,
757
+ }
758
+ : null,
759
+ policyVariantOf: shift.policyVariantOf
760
+ ? {
761
+ policyId: shift.policyVariantOf.policyId,
762
+ policyName: shift.policyVariantOf.policyName,
763
+ globalUserId: shift.policyVariantOf.globalUserId,
764
+ }
765
+ : null,
766
+ policies: shift.policies.map((policy: MaterializedShiftPolicy) => {
767
+ return {
768
+ policyId: policy.policyId,
769
+ policyName: policy.policyName,
770
+ ruleId: policy.ruleId,
771
+ ruleName: policy.ruleName,
772
+ ruleOrder: policy.ruleOrder,
773
+ };
774
+ }),
775
+ };
776
+
777
+ return crypto
778
+ .createHash("sha256")
779
+ .update(JSON.stringify(payload), "utf8")
780
+ .digest("hex");
781
+ }
782
+
783
+ // -- Internals ---------------------------------------------------------
784
+
785
+ private static toMaterializedShift(data: {
786
+ shift: OnCallShift;
787
+ resolved: ResolvedShiftSegments;
788
+ options: MaterializeResolvedOptions;
789
+ policyVariant: {
790
+ policyId: string;
791
+ policyName: string;
792
+ globalUserId: string;
793
+ } | null;
794
+ }): MaterializedShift {
795
+ const { shift, resolved, options } = data;
796
+
797
+ const base: Omit<
798
+ MaterializedShift,
799
+ "contentHash" | "shiftKey" | "lastModifiedAt" | "shiftConfigVersion"
800
+ > = {
801
+ projectId: resolved.schedule.projectId,
802
+ scheduleId: resolved.schedule.id,
803
+ scheduleName: resolved.schedule.name,
804
+ userId: shift.userId,
805
+ userName: OnCallShiftMaterializer.displayName(
806
+ options.users,
807
+ shift.userId,
808
+ ),
809
+ start: shift.start,
810
+ end: shift.end,
811
+ coverageSeconds: shift.coverageSeconds,
812
+ policies: resolved.attachedPolicies.map(
813
+ (policy: MaterializedShiftPolicy) => {
814
+ return { ...policy };
815
+ },
816
+ ),
817
+ isPast: shift.start.getTime() < options.now.getTime(),
818
+ };
819
+
820
+ if (options.projectName !== undefined) {
821
+ base.projectName = options.projectName;
822
+ }
823
+
824
+ if (resolved.schedule.timezone !== undefined) {
825
+ base.scheduleTimezone = resolved.schedule.timezone;
826
+ }
827
+
828
+ if (shift.layerId !== undefined) {
829
+ base.layerId = shift.layerId;
830
+ }
831
+
832
+ if (shift.layerName !== undefined) {
833
+ base.layerName = shift.layerName;
834
+ }
835
+
836
+ if (shift.override) {
837
+ const override: MaterializedShiftOverride = {
838
+ originalUserId: shift.override.originalUserId,
839
+ originalUserName: OnCallShiftMaterializer.displayName(
840
+ options.users,
841
+ shift.override.originalUserId,
842
+ ),
843
+ overrideStartsAt: new Date(shift.override.overrideStartsAt.getTime()),
844
+ overrideEndsAt: new Date(shift.override.overrideEndsAt.getTime()),
845
+ };
846
+
847
+ const policyId: string | null =
848
+ OnCallShiftMaterializer.findOverridePolicyId(resolved.overrides, {
849
+ originalUserId: shift.override.originalUserId,
850
+ substituteUserId: shift.userId,
851
+ startsAt: shift.override.overrideStartsAt,
852
+ endsAt: shift.override.overrideEndsAt,
853
+ preferredPolicyId: data.policyVariant?.policyId,
854
+ });
855
+
856
+ if (policyId) {
857
+ override.onCallDutyPolicyId = policyId;
858
+ }
859
+
860
+ base.override = override;
861
+ }
862
+
863
+ if (data.policyVariant) {
864
+ base.policyVariantOf = {
865
+ policyId: data.policyVariant.policyId,
866
+ policyName: data.policyVariant.policyName,
867
+ globalUserId: data.policyVariant.globalUserId,
868
+ };
869
+ }
870
+
871
+ return {
872
+ ...base,
873
+ shiftKey: MaterializedShiftUtil.buildShiftKey({
874
+ scheduleId: resolved.schedule.id,
875
+ start: shift.start,
876
+ policyId: data.policyVariant?.policyId,
877
+ }),
878
+ contentHash: OnCallShiftMaterializer.computeContentHash(base),
879
+ lastModifiedAt: resolved.lastModifiedAt,
880
+ shiftConfigVersion: resolved.schedule.shiftConfigVersion,
881
+ };
882
+ }
883
+
884
+ /*
885
+ * Map a segment's override meta back to the override record that produced
886
+ * it, to learn its policy scope. Prefers a record scoped to
887
+ * `preferredPolicyId` (the variant being materialized); falls back to any
888
+ * record with the same users and window.
889
+ */
890
+ private static findOverridePolicyId(
891
+ overrides: Array<UserOverrideRecord>,
892
+ data: {
893
+ originalUserId: string;
894
+ substituteUserId: string;
895
+ startsAt: Date;
896
+ endsAt: Date;
897
+ preferredPolicyId?: string | undefined;
898
+ },
899
+ ): string | null {
900
+ const matches: Array<UserOverrideRecord> = overrides.filter(
901
+ (record: UserOverrideRecord) => {
902
+ return (
903
+ record.overrideUserId === data.originalUserId &&
904
+ record.routeAlertsToUserId === data.substituteUserId &&
905
+ record.startsAt.getTime() === data.startsAt.getTime() &&
906
+ record.endsAt.getTime() === data.endsAt.getTime()
907
+ );
908
+ },
909
+ );
910
+
911
+ if (matches.length === 0) {
912
+ return null;
913
+ }
914
+
915
+ if (data.preferredPolicyId) {
916
+ const preferred: UserOverrideRecord | undefined = matches.find(
917
+ (record: UserOverrideRecord) => {
918
+ return record.onCallDutyPolicyId === data.preferredPolicyId;
919
+ },
920
+ );
921
+ if (preferred) {
922
+ return preferred.onCallDutyPolicyId || null;
923
+ }
924
+ }
925
+
926
+ // A global match wins over a scoped one for the base resolution.
927
+ const global: UserOverrideRecord | undefined = matches.find(
928
+ (record: UserOverrideRecord) => {
929
+ return !record.onCallDutyPolicyId;
930
+ },
931
+ );
932
+
933
+ if (global) {
934
+ return null;
935
+ }
936
+
937
+ return matches[0]!.onCallDutyPolicyId || null;
938
+ }
939
+
940
+ private static displayName(
941
+ users: Map<string, MaterializedUserInfo>,
942
+ userId: string,
943
+ ): string {
944
+ return (
945
+ users.get(userId)?.userName || OnCallCalendarFeedUtil.FALLBACK_USER_NAME
946
+ );
947
+ }
948
+
949
+ private static collectUserIds(
950
+ resolved: Array<ResolvedShiftSegments>,
951
+ ): Array<string> {
952
+ const ids: Set<string> = new Set<string>();
953
+
954
+ for (const item of resolved) {
955
+ for (const segment of item.segments) {
956
+ if (segment.title) {
957
+ ids.add(segment.title);
958
+ }
959
+ }
960
+ for (const variant of item.policyVariants) {
961
+ for (const segment of variant.segments) {
962
+ if (segment.title) {
963
+ ids.add(segment.title);
964
+ }
965
+ }
966
+ }
967
+ for (const override of item.overrides) {
968
+ if (override.overrideUserId) {
969
+ ids.add(override.overrideUserId);
970
+ }
971
+ if (override.routeAlertsToUserId) {
972
+ ids.add(override.routeAlertsToUserId);
973
+ }
974
+ }
975
+ for (const userId of item.scheduleUserIds) {
976
+ ids.add(userId);
977
+ }
978
+ }
979
+
980
+ return Array.from(ids);
981
+ }
982
+
983
+ /*
984
+ * One root user lookup for names and timezones. Name falls back to email;
985
+ * the feed mapper masks emails where they must not appear (shared feeds).
986
+ */
987
+ private static async loadUsers(
988
+ userIds: Array<string>,
989
+ ): Promise<Map<string, MaterializedUserInfo>> {
990
+ const users: Map<string, MaterializedUserInfo> = new Map<
991
+ string,
992
+ MaterializedUserInfo
993
+ >();
994
+
995
+ if (userIds.length === 0) {
996
+ return users;
997
+ }
998
+
999
+ const rows: Array<User> = await UserService.findBy({
1000
+ query: {
1001
+ _id: QueryHelper.any(userIds),
1002
+ },
1003
+ select: {
1004
+ _id: true,
1005
+ name: true,
1006
+ email: true,
1007
+ timezone: true,
1008
+ },
1009
+ limit: LIMIT_PER_PROJECT,
1010
+ skip: 0,
1011
+ props: {
1012
+ isRoot: true,
1013
+ },
1014
+ });
1015
+
1016
+ for (const row of rows) {
1017
+ const userId: string | undefined = row.id?.toString();
1018
+ if (!userId) {
1019
+ continue;
1020
+ }
1021
+
1022
+ const name: string = row.name?.toString().trim() || "";
1023
+ const email: string = row.email?.toString().trim() || "";
1024
+ const timezone: string = row.timezone?.toString() || "";
1025
+
1026
+ const info: MaterializedUserInfo = {
1027
+ userId,
1028
+ userName: name || email || OnCallCalendarFeedUtil.FALLBACK_USER_NAME,
1029
+ };
1030
+
1031
+ if (email) {
1032
+ info.email = email;
1033
+ }
1034
+
1035
+ if (timezone) {
1036
+ info.timezone = timezone;
1037
+ }
1038
+
1039
+ users.set(userId, info);
1040
+ }
1041
+
1042
+ return users;
1043
+ }
1044
+
1045
+ private static async loadProjectNames(
1046
+ projectIds: Array<string>,
1047
+ ): Promise<Map<string, string>> {
1048
+ const names: Map<string, string> = new Map<string, string>();
1049
+ const distinct: Array<string> = Array.from(
1050
+ new Set<string>(
1051
+ projectIds.filter((id: string) => {
1052
+ return Boolean(id);
1053
+ }),
1054
+ ),
1055
+ );
1056
+
1057
+ if (distinct.length === 0) {
1058
+ return names;
1059
+ }
1060
+
1061
+ const projects: Array<Project> = await ProjectService.findBy({
1062
+ query: {
1063
+ _id: QueryHelper.any(distinct),
1064
+ },
1065
+ select: {
1066
+ _id: true,
1067
+ name: true,
1068
+ },
1069
+ limit: LIMIT_PER_PROJECT,
1070
+ skip: 0,
1071
+ props: {
1072
+ isRoot: true,
1073
+ },
1074
+ });
1075
+
1076
+ for (const project of projects) {
1077
+ const id: string | undefined = project.id?.toString();
1078
+ if (id && project.name) {
1079
+ names.set(id, project.name);
1080
+ }
1081
+ }
1082
+
1083
+ return names;
1084
+ }
1085
+
1086
+ private static validateWindow(windowStart: Date, windowEnd: Date): void {
1087
+ if (
1088
+ !(windowStart instanceof Date) ||
1089
+ !(windowEnd instanceof Date) ||
1090
+ Number.isNaN(windowStart.getTime()) ||
1091
+ Number.isNaN(windowEnd.getTime())
1092
+ ) {
1093
+ throw new BadDataException("windowStart and windowEnd must be dates");
1094
+ }
1095
+
1096
+ if (windowStart.getTime() >= windowEnd.getTime()) {
1097
+ throw new BadDataException("windowStart must be before windowEnd");
1098
+ }
1099
+ }
1100
+
1101
+ private static emptyResult(now: Date): MaterializeResult {
1102
+ return {
1103
+ shifts: [],
1104
+ truncated: false,
1105
+ schedules: [],
1106
+ users: [],
1107
+ generatedAt: now,
1108
+ };
1109
+ }
1110
+
1111
+ private static dedupeIds(ids: Array<ObjectID>): Array<ObjectID> {
1112
+ const seen: Set<string> = new Set<string>();
1113
+ const result: Array<ObjectID> = [];
1114
+ for (const id of ids) {
1115
+ if (!id) {
1116
+ continue;
1117
+ }
1118
+ const key: string = id.toString();
1119
+ if (!key || seen.has(key)) {
1120
+ continue;
1121
+ }
1122
+ seen.add(key);
1123
+ result.push(id);
1124
+ }
1125
+ return result;
1126
+ }
1127
+ }