@oneuptime/common 14.0.1 → 14.0.3

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 (1241) hide show
  1. package/Models/DatabaseModels/AlertEpisodeMember.ts +8 -1
  2. package/Models/DatabaseModels/AlertFeed.ts +2 -0
  3. package/Models/DatabaseModels/AutoRemediationSuggestion.ts +63 -0
  4. package/Models/DatabaseModels/IncidentAlert.ts +540 -0
  5. package/Models/DatabaseModels/IncidentEpisodeMember.ts +8 -1
  6. package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +9 -2
  7. package/Models/DatabaseModels/IncidentFeed.ts +2 -0
  8. package/Models/DatabaseModels/IncidentPublicNote.ts +9 -2
  9. package/Models/DatabaseModels/Index.ts +2 -0
  10. package/Models/DatabaseModels/KubernetesCluster.ts +429 -0
  11. package/Models/DatabaseModels/Monitor.ts +48 -0
  12. package/Models/DatabaseModels/Project.ts +60 -0
  13. package/Models/DatabaseModels/RumApplication.ts +52 -1
  14. package/Models/DatabaseModels/Runner.ts +5 -4
  15. package/Models/DatabaseModels/RunnerJob.ts +66 -0
  16. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +10 -2
  17. package/Models/DatabaseModels/WorkflowVariable.ts +479 -2
  18. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +79 -25
  19. package/Server/API/AIInvestigationAPI.ts +341 -0
  20. package/Server/API/AutoRemediationAPI.ts +184 -2
  21. package/Server/API/CommonAPI.ts +70 -0
  22. package/Server/API/KubernetesClusterAiAccessAPI.ts +793 -0
  23. package/Server/API/MicrosoftTeamsAPI.ts +770 -315
  24. package/Server/API/MonitorAPI.ts +140 -0
  25. package/Server/API/OnCallScheduleTimelineAPI.ts +5 -21
  26. package/Server/API/SlackAPI.ts +447 -99
  27. package/Server/API/StatusPageAPI.ts +146 -26
  28. package/Server/API/TelemetryAPI.ts +216 -5
  29. package/Server/API/UserTwoFactorBackupCodeAPI.ts +1 -0
  30. package/Server/API/WorkflowVariableAPI.ts +156 -0
  31. package/Server/Infrastructure/GlobalCache.ts +35 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1794300000000-AddOAuth2WorkflowVariables.ts +97 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/1794400000000-AddKubernetesClusterAiAccess.ts +129 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/1794500000000-AddIncomingEmailCustomAddressToMonitor.ts +25 -0
  35. package/Server/Infrastructure/Postgres/SchemaMigrations/1794600000000-AddAuthTokenExpiresAtToWorkspaceProjectAuthToken.ts +20 -0
  36. package/Server/Infrastructure/Postgres/SchemaMigrations/1794700000000-RemoveAppAccessTokenFromWorkspaceProjectAuthTokenMiscData.ts +38 -0
  37. package/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.ts +28 -0
  38. package/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.ts +89 -0
  39. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
  40. package/Server/Middleware/MasterAdminAuthorization.ts +28 -0
  41. package/Server/Middleware/TelemetryIngest.ts +47 -2
  42. package/Server/Middleware/UserAuthorization.ts +56 -2
  43. package/Server/Services/AIAgentService.ts +1 -0
  44. package/Server/Services/AccessTokenService.ts +121 -48
  45. package/Server/Services/AlertEpisodeMemberService.ts +9 -0
  46. package/Server/Services/AlertEpisodeService.ts +14 -1
  47. package/Server/Services/AlertService.ts +134 -22
  48. package/Server/Services/AutoRemediationRuleEngineService.ts +968 -39
  49. package/Server/Services/AutoRemediationRuleService.ts +118 -0
  50. package/Server/Services/BillingService.ts +1 -0
  51. package/Server/Services/InboundEmail/Providers/SendGridInboundProvider.ts +16 -22
  52. package/Server/Services/IncidentAlertService.ts +1811 -0
  53. package/Server/Services/IncidentEpisodeMemberService.ts +9 -0
  54. package/Server/Services/IncidentEpisodePublicNoteService.ts +66 -0
  55. package/Server/Services/IncidentEpisodeRoleMemberService.ts +27 -0
  56. package/Server/Services/IncidentEpisodeService.ts +14 -1
  57. package/Server/Services/IncidentGroupingEngineService.ts +11 -0
  58. package/Server/Services/IncidentMemberService.ts +21 -0
  59. package/Server/Services/IncidentPublicNoteService.ts +63 -0
  60. package/Server/Services/IncidentService.ts +330 -30
  61. package/Server/Services/IncidentStateTimelineService.ts +39 -0
  62. package/Server/Services/IncidentTemplateService.ts +83 -3
  63. package/Server/Services/Index.ts +2 -0
  64. package/Server/Services/KubernetesClusterAiAccessService.ts +1943 -0
  65. package/Server/Services/KubernetesClusterService.ts +1570 -1
  66. package/Server/Services/LogAggregationService.ts +14 -6
  67. package/Server/Services/MonitorService.ts +651 -52
  68. package/Server/Services/MonitorStatusTimelineService.ts +639 -2
  69. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +2 -0
  70. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +2 -0
  71. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +2 -0
  72. package/Server/Services/OnCallDutyPolicyScheduleService.ts +3 -0
  73. package/Server/Services/OnCallNotificationAlertingService.ts +36 -12
  74. package/Server/Services/OnCallSetupReminderService.ts +1 -0
  75. package/Server/Services/ProbeService.ts +7 -1
  76. package/Server/Services/ProjectService.ts +11 -1
  77. package/Server/Services/RunbookCredentialService.ts +26 -1
  78. package/Server/Services/RunbookSecretService.ts +36 -0
  79. package/Server/Services/RunnerJobService.ts +941 -23
  80. package/Server/Services/RunnerService.ts +439 -6
  81. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +66 -0
  82. package/Server/Services/ScheduledMaintenanceService.ts +124 -19
  83. package/Server/Services/ScheduledMaintenanceTemplateService.ts +82 -3
  84. package/Server/Services/ServiceLevelObjectiveService.ts +14 -1
  85. package/Server/Services/StatusPagePrivateUserService.ts +1 -0
  86. package/Server/Services/StatusPageService.ts +301 -74
  87. package/Server/Services/StatusPageSubscriberService.ts +4 -0
  88. package/Server/Services/TeamMemberService.ts +309 -7
  89. package/Server/Services/TraceAggregationService.ts +10 -6
  90. package/Server/Services/UserEmailService.ts +1 -0
  91. package/Server/Services/UserNotificationMethodAdminService.ts +1 -0
  92. package/Server/Services/UserNotificationRuleAdminService.ts +1 -0
  93. package/Server/Services/UserNotificationRuleService.ts +4 -0
  94. package/Server/Services/UserService.ts +122 -1
  95. package/Server/Services/WorkflowVariableService.ts +593 -8
  96. package/Server/Services/WorkspaceNotificationRuleService.ts +588 -8
  97. package/Server/Services/WorkspaceProjectAuthTokenService.ts +170 -1
  98. package/Server/Types/Database/QueryHelper.ts +22 -0
  99. package/Server/Types/Markdown.ts +502 -27
  100. package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +182 -0
  101. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +525 -0
  102. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +854 -0
  103. package/Server/Utils/AI/CodeFix/CodeFixAgentAuth.ts +22 -2
  104. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1916 -307
  105. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +1601 -74
  106. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +139 -7
  107. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +58 -1
  108. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +54 -1
  109. package/Server/Utils/AI/Toolbox/AIActionTools.ts +14 -6
  110. package/Server/Utils/AI/Toolbox/ResourceTools.ts +4 -2
  111. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +1341 -150
  112. package/Server/Utils/AutoRemediation/RemediationVerifier.ts +375 -4
  113. package/Server/Utils/Database/AffectedResourceRelations.ts +127 -0
  114. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +240 -1
  115. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +1 -0
  116. package/Server/Utils/Monitor/MonitorAlert.ts +83 -9
  117. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +5 -1
  118. package/Server/Utils/Monitor/MonitorIncident.ts +104 -9
  119. package/Server/Utils/Monitor/MonitorPayloadRedaction.ts +124 -7
  120. package/Server/Utils/Monitor/ProbeMonitorsNotification.ts +407 -0
  121. package/Server/Utils/OnCall/OnCallShiftReminderRunner.ts +1 -0
  122. package/Server/Utils/PushNotificationUtil.ts +45 -0
  123. package/Server/Utils/Rules/OwnerRuleAssignment.ts +40 -3
  124. package/Server/Utils/Runbook/RunbookExecutePermission.ts +56 -6
  125. package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +24 -2
  126. package/Server/Utils/SessionReplay/SessionReplayReadService.ts +223 -33
  127. package/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.ts +559 -0
  128. package/Server/Utils/StartServer.ts +4 -3
  129. package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +528 -0
  130. package/Server/Utils/TwoFactorBackupCodeNotification.ts +1 -0
  131. package/Server/Utils/UserPermission/UserPermission.ts +16 -0
  132. package/Server/Utils/Workflow/OAuth2TokenClient.ts +704 -0
  133. package/Server/Utils/Workflow/WorkflowVariableOAuthToken.ts +318 -0
  134. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +47 -7
  135. package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +57 -16
  136. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +193 -214
  137. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +57 -13
  138. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.ts +54 -17
  139. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +179 -161
  140. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +281 -167
  141. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsServiceUrl.ts +114 -0
  142. package/Server/Utils/Workspace/MicrosoftTeams/ReactionNoteSync.ts +895 -0
  143. package/Server/Utils/Workspace/Slack/Actions/ActionTypes.ts +7 -9
  144. package/Server/Utils/Workspace/Slack/Actions/Alert.ts +96 -227
  145. package/Server/Utils/Workspace/Slack/Actions/AlertEpisode.ts +93 -214
  146. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +30 -3
  147. package/Server/Utils/Workspace/Slack/Actions/Authorization.ts +99 -0
  148. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +117 -283
  149. package/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.ts +101 -196
  150. package/Server/Utils/Workspace/Slack/Actions/ReactionNote.ts +329 -0
  151. package/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.ts +111 -287
  152. package/Server/Utils/Workspace/Slack/Slack.ts +86 -17
  153. package/Server/Utils/Workspace/Slack/app-manifest.json +2 -0
  154. package/Server/Utils/Workspace/Workspace.ts +171 -54
  155. package/Server/Utils/Workspace/WorkspaceActionAuthorization.ts +252 -0
  156. package/Server/Utils/Workspace/WorkspaceBase.ts +39 -0
  157. package/Server/Utils/Workspace/WorkspaceOAuthState.ts +280 -0
  158. package/Server/Utils/Workspace/WorkspaceProjectReferenceValidator.ts +96 -0
  159. package/Server/Utils/Workspace/WorkspaceReactionNote.ts +620 -0
  160. package/Tests/App/Dashboard/AttributesJSONDashboardSurfaces.test.tsx +496 -0
  161. package/Tests/App/Dashboard/AutoRemediationRulesTableCommandRunners.test.tsx +152 -0
  162. package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +32 -0
  163. package/Tests/App/Dashboard/BulkIncidentLinkActions.test.tsx +869 -0
  164. package/Tests/App/Dashboard/CephMetricTooltips.test.tsx +1777 -0
  165. package/Tests/App/Dashboard/CloudFleetSummary.test.ts +8 -0
  166. package/Tests/App/Dashboard/CloudMetricTooltips.test.tsx +887 -0
  167. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +794 -0
  168. package/Tests/App/Dashboard/ContainerHostMetricTooltips.test.tsx +1309 -0
  169. package/Tests/App/Dashboard/CreateOAuthWorkflowVariableModal.test.tsx +840 -0
  170. package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +653 -0
  171. package/Tests/App/Dashboard/DatabaseMonitorStepForm.test.tsx +197 -0
  172. package/Tests/App/Dashboard/DatabaseMonitorView.test.tsx +376 -0
  173. package/Tests/App/Dashboard/DisabledWarningRobustness.test.tsx +262 -0
  174. package/Tests/App/Dashboard/DiscoveryScanLivePage.test.tsx +39 -0
  175. package/Tests/App/Dashboard/DockerSwarmClustersListTooltips.test.tsx +414 -0
  176. package/Tests/App/Dashboard/DockerSwarmMetricTooltips.test.ts +796 -0
  177. package/Tests/App/Dashboard/DockerSwarmOverviewTooltips.test.tsx +747 -0
  178. package/Tests/App/Dashboard/EventNotes.test.tsx +2080 -0
  179. package/Tests/App/Dashboard/EventNotesPages.test.tsx +486 -0
  180. package/Tests/App/Dashboard/EventNotesUtil.test.ts +933 -0
  181. package/Tests/App/Dashboard/ExceptionMonitorEnvironmentFilter.test.tsx +238 -0
  182. package/Tests/App/Dashboard/HostDetailViewTooltips.test.tsx +725 -0
  183. package/Tests/App/Dashboard/HostListColumnTooltips.test.tsx +472 -0
  184. package/Tests/App/Dashboard/HostMetricTooltips.test.ts +709 -0
  185. package/Tests/App/Dashboard/HostOverviewTooltips.test.tsx +698 -0
  186. package/Tests/App/Dashboard/HostTooltipHarness.ts +124 -0
  187. package/Tests/App/Dashboard/HostsListTooltips.test.tsx +395 -0
  188. package/Tests/App/Dashboard/IncidentAlertLinkDialog.test.tsx +691 -0
  189. package/Tests/App/Dashboard/IncidentAlertLinkHelpers.test.ts +458 -0
  190. package/Tests/App/Dashboard/IncidentAlertLinkPages.test.tsx +828 -0
  191. package/Tests/App/Dashboard/IncidentAlertLinkSideMenus.test.tsx +231 -0
  192. package/Tests/App/Dashboard/IncidentChangeStateNotifyDefault.test.tsx +665 -0
  193. package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +689 -0
  194. package/Tests/App/Dashboard/IncidentEpisodeFeedPublicNoteNotifyDefault.test.tsx +494 -0
  195. package/Tests/App/Dashboard/IncidentEpisodeOverviewNotifyDefault.test.tsx +706 -0
  196. package/Tests/App/Dashboard/IncidentFeedPublicNoteNotifyDefault.test.tsx +472 -0
  197. package/Tests/App/Dashboard/IncidentOverviewNotifyDefault.test.tsx +858 -0
  198. package/Tests/App/Dashboard/IncomingEmailAddressSettings.test.tsx +567 -0
  199. package/Tests/App/Dashboard/InvestigationClusterToolFormat.test.ts +241 -0
  200. package/Tests/App/Dashboard/InvestigationEvidenceKubectl.test.tsx +322 -0
  201. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +12 -0
  202. package/Tests/App/Dashboard/InvestigationPanelClusterAccess.test.tsx +476 -0
  203. package/Tests/App/Dashboard/InvestigationRunDetailsKubectl.test.tsx +383 -0
  204. package/Tests/App/Dashboard/IoTMetricTooltips.test.tsx +1123 -0
  205. package/Tests/App/Dashboard/KubectlActivitySummary.test.tsx +366 -0
  206. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +2886 -0
  207. package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +2688 -0
  208. package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +915 -0
  209. package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +837 -0
  210. package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +699 -0
  211. package/Tests/App/Dashboard/KubernetesContainersTabTooltips.test.tsx +320 -0
  212. package/Tests/App/Dashboard/KubernetesCostTooltips.test.tsx +502 -0
  213. package/Tests/App/Dashboard/KubernetesInsightsTooltips.test.tsx +222 -0
  214. package/Tests/App/Dashboard/KubernetesResourceMetricTooltips.test.ts +561 -0
  215. package/Tests/App/Dashboard/KubernetesResourcePagesTooltips.test.tsx +1168 -0
  216. package/Tests/App/Dashboard/LayerDateTimeFieldTimezoneName.test.tsx +66 -0
  217. package/Tests/App/Dashboard/LinkIncidentAlertModal.test.tsx +154 -0
  218. package/Tests/App/Dashboard/LogMonitorPreview.test.tsx +174 -0
  219. package/Tests/App/Dashboard/MetricDescriptionRules.ts +170 -0
  220. package/Tests/App/Dashboard/MetricDescriptionsCatalog.test.ts +206 -0
  221. package/Tests/App/Dashboard/MetricDescriptionsConsistency.test.ts +275 -0
  222. package/Tests/App/Dashboard/MonitorFeedRefresh.test.tsx +279 -0
  223. package/Tests/App/Dashboard/MonitorMetricQueryConfig.test.ts +244 -0
  224. package/Tests/App/Dashboard/MonitorOpenWorkCard.test.tsx +381 -0
  225. package/Tests/App/Dashboard/MonitorOpenWorkHook.test.tsx +784 -0
  226. package/Tests/App/Dashboard/MonitorOverviewData.test.tsx +2199 -0
  227. package/Tests/App/Dashboard/MonitorOverviewHero.test.tsx +1169 -0
  228. package/Tests/App/Dashboard/MonitorOverviewInput.test.ts +1127 -0
  229. package/Tests/App/Dashboard/MonitorOverviewPage.test.tsx +2136 -0
  230. package/Tests/App/Dashboard/MonitorOverviewSelectReadable.test.ts +368 -0
  231. package/Tests/App/Dashboard/MonitorOverviewStatBar.test.tsx +526 -0
  232. package/Tests/App/Dashboard/MonitorOverviewSupportingCards.test.tsx +542 -0
  233. package/Tests/App/Dashboard/MonitorOwnersCombine.test.ts +299 -0
  234. package/Tests/App/Dashboard/MonitorProbesCard.test.tsx +602 -0
  235. package/Tests/App/Dashboard/MonitorResponseTimeCard.test.tsx +386 -0
  236. package/Tests/App/Dashboard/MonitorSetupAndConnectionCards.test.tsx +612 -0
  237. package/Tests/App/Dashboard/MonitorStatusChangesCard.test.tsx +257 -0
  238. package/Tests/App/Dashboard/MonitorSummaryTestMonitorButton.test.tsx +360 -1
  239. package/Tests/App/Dashboard/MonitorUptimeHistoryCard.test.tsx +835 -0
  240. package/Tests/App/Dashboard/MonitorUptimeSummaryHook.test.tsx +971 -0
  241. package/Tests/App/Dashboard/MonitorViewLayout.test.tsx +580 -0
  242. package/Tests/App/Dashboard/NetworkDeviceTooltips.test.tsx +852 -0
  243. package/Tests/App/Dashboard/NetworkDiagnosticsTooltips.test.tsx +556 -0
  244. package/Tests/App/Dashboard/NetworkMetricTooltips.test.ts +1348 -0
  245. package/Tests/App/Dashboard/NetworkSiteTooltips.test.tsx +679 -0
  246. package/Tests/App/Dashboard/OnCallLayerRestrictionTimesPreserved.test.tsx +441 -0
  247. package/Tests/App/Dashboard/OnCallNavbar.test.tsx +214 -0
  248. package/Tests/App/Dashboard/OnCallSchedulePreviewCalendarDisplay.test.tsx +1389 -0
  249. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +205 -1
  250. package/Tests/App/Dashboard/OnCallScheduleTimeInputsSettingsZone.test.tsx +198 -0
  251. package/Tests/App/Dashboard/ProxmoxMetricTooltips.test.ts +592 -0
  252. package/Tests/App/Dashboard/ProxmoxOverviewTooltips.test.tsx +1002 -0
  253. package/Tests/App/Dashboard/ProxmoxResourcePageTooltips.test.tsx +923 -0
  254. package/Tests/App/Dashboard/PublicNotePagesNotifyDefault.test.tsx +524 -0
  255. package/Tests/App/Dashboard/RemediationSuggestionCardApproval.test.tsx +702 -0
  256. package/Tests/App/Dashboard/RemoveUserFromProject.test.tsx +427 -0
  257. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +4 -0
  258. package/Tests/App/Dashboard/ResourceOverviewTileTooltips.test.tsx +1066 -0
  259. package/Tests/App/Dashboard/RumOverviewPage.test.tsx +1195 -0
  260. package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +3 -1
  261. package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +166 -0
  262. package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +622 -0
  263. package/Tests/App/Dashboard/ScheduledMaintenanceChangeStateNotifyDefault.test.tsx +1491 -0
  264. package/Tests/App/Dashboard/ScheduledMaintenanceFeedPublicNoteNotifyDefault.test.tsx +489 -0
  265. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewNotifyDefault.test.tsx +909 -0
  266. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +14 -0
  267. package/Tests/App/Dashboard/ScheduledMaintenanceWindowStatsTranslation.test.tsx +307 -0
  268. package/Tests/App/Dashboard/SecurityEventAttributeColumnPicker.test.tsx +542 -0
  269. package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +174 -0
  270. package/Tests/App/Dashboard/SecurityEventConnectionsEmptyState.test.tsx +973 -212
  271. package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +491 -52
  272. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +301 -0
  273. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +158 -1
  274. package/Tests/App/Dashboard/SecurityEventProviderTile.test.tsx +869 -0
  275. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +959 -94
  276. package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +2 -0
  277. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +274 -1
  278. package/Tests/App/Dashboard/ServerlessMetricTooltips.test.tsx +474 -0
  279. package/Tests/App/Dashboard/ServiceMetricTooltips.test.tsx +772 -0
  280. package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +56 -1
  281. package/Tests/App/Dashboard/TeamMembershipRemoval.test.ts +900 -0
  282. package/Tests/App/Dashboard/TeamMembershipRemovalPages.test.tsx +460 -0
  283. package/Tests/App/Dashboard/TelemetryMetricsSignals.test.ts +1207 -0
  284. package/Tests/App/Dashboard/TelemetryResourceTabTooltips.test.tsx +437 -0
  285. package/Tests/App/Dashboard/TimezoneElements.test.tsx +321 -0
  286. package/Tests/App/Dashboard/TimezoneSelectButton.test.tsx +634 -0
  287. package/Tests/App/Dashboard/TraceExplorer.test.tsx +260 -0
  288. package/Tests/App/Dashboard/TraceMonitorPreview.test.tsx +182 -0
  289. package/Tests/App/Dashboard/UserTimezoneInit.test.tsx +544 -0
  290. package/Tests/App/Dashboard/VMwareMetricTooltips.test.ts +801 -0
  291. package/Tests/App/Dashboard/VMwareOverviewTooltips.test.tsx +601 -0
  292. package/Tests/App/Dashboard/VMwareResourcePagesTooltips.test.tsx +646 -0
  293. package/Tests/App/Dashboard/VMwareTooltipHarness.ts +145 -0
  294. package/Tests/App/Dashboard/WorkflowVariableModals.test.tsx +1630 -0
  295. package/Tests/App/Dashboard/WorkflowVariableRoutes.test.tsx +603 -0
  296. package/Tests/App/Dashboard/WorkflowVariableTokenStatus.test.tsx +589 -0
  297. package/Tests/App/Dashboard/WorkflowVariableUtil.test.ts +1543 -0
  298. package/Tests/App/Dashboard/WorkflowVariableView.test.tsx +3227 -0
  299. package/Tests/App/Dashboard/WorkflowVariablesTable.test.tsx +1277 -395
  300. package/Tests/App/StatusPage/StatusPageOverviewMonitorGroupUptime.test.tsx +714 -0
  301. package/Tests/App/StatusPage/StatusPageOverviewUptimeBars.NewYork.test.tsx +1009 -0
  302. package/Tests/App/StatusPage/StatusPageOverviewUptimeBars.test.tsx +1092 -0
  303. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +5 -0
  304. package/Tests/Models/DatabaseModels/IncidentAlertModel.test.ts +554 -0
  305. package/Tests/Models/DatabaseModels/KubernetesClusterAiAccessColumns.test.ts +520 -0
  306. package/Tests/Models/DatabaseModels/MonitorSecretKeyColumnAccessControl.test.ts +66 -2
  307. package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +117 -0
  308. package/Tests/Models/DatabaseModels/WorkspaceProjectAuthTokenAccessControl.test.ts +236 -0
  309. package/Tests/Models/IncidentEpisodePublicNoteNotifyColumnContract.test.ts +103 -0
  310. package/Tests/Models/IncidentPublicNoteNotifyColumnContract.test.ts +96 -0
  311. package/Tests/Models/ScheduledMaintenancePublicNoteNotifyColumnContract.test.ts +111 -0
  312. package/Tests/Server/API/AIInvestigationAPI.test.ts +976 -0
  313. package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +836 -0
  314. package/Tests/Server/API/CommonAPIAssertCanCreateTable.test.ts +565 -0
  315. package/Tests/Server/API/CommonAPIAssertCanReadTable.test.ts +282 -0
  316. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +1744 -0
  317. package/Tests/Server/API/LogHistogramAPI.test.ts +371 -0
  318. package/Tests/Server/API/MicrosoftTeamsLegacyWebhookRemoval.test.ts +125 -30
  319. package/Tests/Server/API/MicrosoftTeamsOAuthState.test.ts +1121 -0
  320. package/Tests/Server/API/MonitorUptimeSummaryAPI.test.ts +685 -0
  321. package/Tests/Server/API/SessionReplayAPI.test.ts +602 -1
  322. package/Tests/Server/API/SlackChannelCacheAPI.test.ts +358 -0
  323. package/Tests/Server/API/SlackOAuthState.test.ts +688 -0
  324. package/Tests/Server/API/StatusPageOverviewMonitorGroupUptime.test.ts +527 -0
  325. package/Tests/Server/API/StatusPageTestEmailReportAuth.test.ts +2 -0
  326. package/Tests/Server/API/StatusPageUptimeAPI.test.ts +427 -0
  327. package/Tests/Server/API/UserProjectsAPI.test.ts +4 -0
  328. package/Tests/Server/API/WorkflowVariableAPI.test.ts +404 -0
  329. package/Tests/Server/API/WorkspaceOAuthTestHelpers.ts +289 -0
  330. package/Tests/Server/API/WorkspaceSendTestNotificationRoutes.test.ts +2064 -0
  331. package/Tests/Server/Infrastructure/GlobalCache.test.ts +86 -0
  332. package/Tests/Server/Infrastructure/Postgres/AddIncidentAlertMigration.test.ts +341 -0
  333. package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +589 -0
  334. package/Tests/Server/Infrastructure/Postgres/AddOAuth2WorkflowVariablesMigration.test.ts +254 -0
  335. package/Tests/Server/Infrastructure/Postgres/AddSessionReplaySameOriginTracePropagationMigration.test.ts +247 -0
  336. package/Tests/Server/Middleware/BlockedUserMiddleware.test.ts +403 -0
  337. package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +13 -0
  338. package/Tests/Server/Middleware/PublicRouteUserMiddleware.test.ts +2 -0
  339. package/Tests/Server/Middleware/RemovedProjectMemberAuthorization.test.ts +469 -0
  340. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +77 -1
  341. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +211 -0
  342. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +358 -0
  343. package/Tests/Server/Middleware/UserAuthorization.test.ts +97 -0
  344. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +2 -0
  345. package/Tests/Server/Services/AccessTokenProjectUserGrant.test.ts +14 -2
  346. package/Tests/Server/Services/AccessTokenRemovedMemberAccess.test.ts +1044 -0
  347. package/Tests/Server/Services/AddOwnersIdempotency.test.ts +5 -0
  348. package/Tests/Server/Services/AlertEpisodeMemberCreatePermission.test.ts +139 -0
  349. package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +1361 -0
  350. package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +375 -0
  351. package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +2384 -0
  352. package/Tests/Server/Services/FindOwnersProjectMembership.test.ts +267 -0
  353. package/Tests/Server/Services/InboundEmail/SendGridInboundProviderAddress.test.ts +90 -0
  354. package/Tests/Server/Services/IncidentAlertPostgres.test.ts +903 -0
  355. package/Tests/Server/Services/IncidentAlertRegistration.test.ts +96 -0
  356. package/Tests/Server/Services/IncidentAlertService.test.ts +2225 -0
  357. package/Tests/Server/Services/IncidentAlertStateCascade.test.ts +970 -0
  358. package/Tests/Server/Services/IncidentCreateFromAlerts.test.ts +1284 -0
  359. package/Tests/Server/Services/IncidentEpisodeMemberCreatePermission.test.ts +143 -0
  360. package/Tests/Server/Services/IncidentEpisodePublicNoteNotifyDefault.test.ts +805 -0
  361. package/Tests/Server/Services/IncidentPublicNoteNotifyDefault.test.ts +724 -0
  362. package/Tests/Server/Services/IncidentRoleProjectMembership.test.ts +233 -0
  363. package/Tests/Server/Services/KubernetesClusterAiAccessAgentRunnerAssignments.test.ts +372 -0
  364. package/Tests/Server/Services/KubernetesClusterAiAccessBindingGuard.test.ts +1876 -0
  365. package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +620 -0
  366. package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +421 -0
  367. package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +3662 -0
  368. package/Tests/Server/Services/KubernetesClusterAiAccessSubjectClusters.test.ts +405 -0
  369. package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +975 -0
  370. package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +497 -0
  371. package/Tests/Server/Services/KubernetesClusterServiceDeleteSettlesRemediation.test.ts +328 -0
  372. package/Tests/Server/Services/LogAggregationService.test.ts +99 -0
  373. package/Tests/Server/Services/MonitorServiceIncomingEmailCustomAddress.test.ts +447 -0
  374. package/Tests/Server/Services/MonitorServiceProbeFlagSync.test.ts +1334 -0
  375. package/Tests/Server/Services/MonitorServiceProbeStatusGrouping.test.ts +1640 -0
  376. package/Tests/Server/Services/MonitorServiceRefreshCurrentStatus.test.ts +225 -0
  377. package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +8 -8
  378. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +264 -1
  379. package/Tests/Server/Services/MonitorStatusTimelineMergedDowntime.test.ts +284 -0
  380. package/Tests/Server/Services/MonitorUptimeSummaryService.test.ts +1043 -0
  381. package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +5 -0
  382. package/Tests/Server/Services/OnCallUndeliverablePageOwnerMembership.test.ts +359 -0
  383. package/Tests/Server/Services/ProbeServiceDashboardLink.test.ts +191 -0
  384. package/Tests/Server/Services/ProjectOwnersProjectMembership.test.ts +221 -0
  385. package/Tests/Server/Services/RuleRun/IncidentAlertMaintenanceRuleEnginesRun.test.ts +5 -0
  386. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupARun.test.ts +28 -0
  387. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +9 -1
  388. package/Tests/Server/Services/RunnerJobEnqueueAiCommandAgentRunner.test.ts +230 -0
  389. package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +978 -0
  390. package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +866 -0
  391. package/Tests/Server/Services/RunnerJobSubmitResultRedaction.test.ts +322 -0
  392. package/Tests/Server/Services/RunnerJobSubmitResultUnstorableText.test.ts +357 -0
  393. package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +227 -0
  394. package/Tests/Server/Services/RunnerServiceAgentName.test.ts +581 -0
  395. package/Tests/Server/Services/ScheduledMaintenancePublicNoteNotifyDefault.test.ts +802 -0
  396. package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +53 -0
  397. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +5 -0
  398. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +12 -0
  399. package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +1176 -1
  400. package/Tests/Server/Services/TeamMemberBillingSeatSync.test.ts +9 -0
  401. package/Tests/Server/Services/TeamMemberOnCallCleanup.test.ts +18 -0
  402. package/Tests/Server/Services/TeamMemberProjectMembership.test.ts +255 -0
  403. package/Tests/Server/Services/TeamMemberRemovalRevokesProjectAccess.test.ts +600 -0
  404. package/Tests/Server/Services/TeamMemberResourceCleanup.test.ts +731 -0
  405. package/Tests/Server/Services/TeamMemberWorkspaceAccountCleanup.test.ts +164 -0
  406. package/Tests/Server/Services/TraceAggregationService.test.ts +64 -0
  407. package/Tests/Server/Services/UserServiceBlockedUser.test.ts +293 -0
  408. package/Tests/Server/Services/WorkflowVariableOAuthHooks.test.ts +1016 -0
  409. package/Tests/Server/Services/WorkflowVariableOAuthPostgres.test.ts +543 -0
  410. package/Tests/Server/Services/WorkflowVariableRenameUniqueness.test.ts +16 -5
  411. package/Tests/Server/Services/WorkspaceNotificationRuleNoteDelivery.test.ts +473 -0
  412. package/Tests/Server/Services/WorkspaceNotificationRuleSendTestNotification.test.ts +3690 -0
  413. package/Tests/Server/Services/WorkspaceProjectAuthTokenMiscDataSecrets.test.ts +374 -0
  414. package/Tests/Server/Services/WorkspaceProjectAuthTokenSlackChannelCache.test.ts +143 -0
  415. package/Tests/Server/Types/Database/Permissions/WorkflowVariableOAuthColumnPermission.test.ts +250 -0
  416. package/Tests/Server/Types/Database/QueryHelperJsonContains.test.ts +96 -0
  417. package/Tests/Server/Types/Markdown.test.ts +1033 -0
  418. package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +285 -0
  419. package/Tests/Server/Utils/AI/CodeFix/CodeFixAgentAuth.test.ts +159 -1
  420. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +752 -0
  421. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +1840 -0
  422. package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +1067 -0
  423. package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +355 -0
  424. package/Tests/Server/Utils/AI/PostIncidentStatusUpdateTool.test.ts +496 -0
  425. package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +305 -0
  426. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +1365 -0
  427. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +639 -0
  428. package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +1585 -0
  429. package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +1065 -0
  430. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +2138 -1
  431. package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +1035 -0
  432. package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +517 -0
  433. package/Tests/Server/Utils/AI/ResourceTools.test.ts +27 -1
  434. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +1371 -24
  435. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorRollbackRace.test.ts +962 -0
  436. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +518 -0
  437. package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +939 -2
  438. package/Tests/Server/Utils/Database/ProjectScopedRelationReferences.test.ts +371 -0
  439. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +64 -0
  440. package/Tests/Server/Utils/Monitor/DatabaseMetricObservationRemediation.test.ts +102 -0
  441. package/Tests/Server/Utils/Monitor/MonitorAlertCriteriaReferences.test.ts +362 -0
  442. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +55 -0
  443. package/Tests/Server/Utils/Monitor/MonitorEmailAddressRedaction.test.ts +255 -0
  444. package/Tests/Server/Utils/Monitor/MonitorIncidentCriteriaReferences.test.ts +347 -0
  445. package/Tests/Server/Utils/Monitor/MonitorIncidentMemberRoleMembership.test.ts +203 -0
  446. package/Tests/Server/Utils/Monitor/ProbeMonitorsNotification.test.ts +1147 -0
  447. package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +79 -0
  448. package/Tests/Server/Utils/ResourceFeed/ResourceFeedUtil.test.ts +21 -1
  449. package/Tests/Server/Utils/Rules/OwnerRuleAssignment.test.ts +155 -1
  450. package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +103 -0
  451. package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +288 -0
  452. package/Tests/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.test.ts +304 -0
  453. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +40 -3
  454. package/Tests/Server/Utils/Workflow/OAuth2TokenClient.test.ts +702 -0
  455. package/Tests/Server/Utils/Workflow/OAuth2TokenClientHttpIntegration.test.ts +507 -0
  456. package/Tests/Server/Utils/Workflow/WorkflowVariableOAuthToken.test.ts +831 -0
  457. package/Tests/Server/Utils/Workspace/MicrosoftTeamsActionAuthorization.test.ts +63 -1
  458. package/Tests/Server/Utils/Workspace/MicrosoftTeamsAppAccessToken.test.ts +256 -0
  459. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +60 -0
  460. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChatActionAuthorization.test.ts +442 -0
  461. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +44 -2
  462. package/Tests/Server/Utils/Workspace/MicrosoftTeamsDirectMessage.test.ts +55 -0
  463. package/Tests/Server/Utils/Workspace/MicrosoftTeamsReactionNoteSync.test.ts +1522 -0
  464. package/Tests/Server/Utils/Workspace/MicrosoftTeamsServiceUrl.test.ts +130 -0
  465. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +4 -4
  466. package/Tests/Server/Utils/Workspace/Slack/SlackActionAuthorization.test.ts +691 -0
  467. package/Tests/Server/Utils/Workspace/Slack/SlackMessageByTimestamp.test.ts +253 -0
  468. package/Tests/Server/Utils/Workspace/Slack/SlackReactionNote.test.ts +574 -0
  469. package/Tests/Server/Utils/Workspace/WorkspaceActionAuthorization.test.ts +488 -0
  470. package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +861 -0
  471. package/Tests/Server/Utils/Workspace/WorkspaceMessageAuthor.test.ts +635 -0
  472. package/Tests/Server/Utils/Workspace/WorkspaceOAuthState.test.ts +548 -0
  473. package/Tests/Server/Utils/Workspace/WorkspaceReactionNote.test.ts +839 -0
  474. package/Tests/Server/Utils/Workspace/WorkspaceSendErrorMessage.test.ts +725 -0
  475. package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +283 -9
  476. package/Tests/Types/DateBrowserLocalWallClock.test.ts +280 -0
  477. package/Tests/Types/DateLocalShortMonthNameFallback.test.ts +389 -0
  478. package/Tests/Types/DateUserTimezone.test.ts +177 -4
  479. package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +306 -0
  480. package/Tests/Types/Kubernetes/KubernetesClusterAiAccess.test.ts +283 -0
  481. package/Tests/Types/Kubernetes/KubernetesRunnerPostureWriteScope.test.ts +68 -0
  482. package/Tests/Types/Monitor/DatabaseMonitor/SqlServerPlatform.test.ts +144 -0
  483. package/Tests/Types/Monitor/MonitorStepExceptionMonitor.test.ts +160 -0
  484. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +53 -0
  485. package/Tests/Types/Rum/WebVitals.test.ts +173 -0
  486. package/Tests/Types/Runbook/RunbookStepType.test.ts +91 -16
  487. package/Tests/Types/Runner/RunnerLiveStatus.test.ts +14 -3
  488. package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +15 -0
  489. package/Tests/Types/StatusPage/PublicNoteSubscriberNotificationDefault.test.ts +1868 -0
  490. package/Tests/Types/Timezone.test.ts +5 -0
  491. package/Tests/Types/TimezoneAlias.test.ts +1034 -0
  492. package/Tests/Types/Workflow/JiraTemplateFixtures.ts +833 -0
  493. package/Tests/Types/Workflow/JiraTemplateScripts.test.ts +5414 -0
  494. package/Tests/Types/Workflow/JiraTemplateSimulation.test.ts +4803 -0
  495. package/Tests/Types/Workflow/JiraTemplates.test.ts +5429 -0
  496. package/Tests/Types/Workflow/Templates.test.ts +79 -4
  497. package/Tests/Types/Workflow/WorkflowVariableOAuth.test.ts +520 -0
  498. package/Tests/Types/Workspace/WorkspaceNoteReaction.test.ts +177 -0
  499. package/Tests/UI/Components/AttributesJSON/AttributesJSONView.test.tsx +390 -0
  500. package/Tests/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.test.tsx +566 -0
  501. package/Tests/UI/Components/AttributesJSON/JSONHighlight.test.ts +131 -0
  502. package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +276 -1
  503. package/Tests/UI/Components/Calendar/Calendar.test.tsx +1611 -0
  504. package/Tests/UI/Components/Calendar/CalendarDayLayout.test.ts +1486 -0
  505. package/Tests/UI/Components/Calendar/CalendarDayLayoutDst.test.ts +632 -0
  506. package/Tests/UI/Components/Calendar/CalendarDst.test.tsx +388 -0
  507. package/Tests/UI/Components/Charts/ChartGroupPlotFloor.test.tsx +170 -0
  508. package/Tests/UI/Components/Charts/HistogramSelection.test.ts +282 -0
  509. package/Tests/UI/Components/CustomTimeRangeModal.test.tsx +6 -0
  510. package/Tests/UI/Components/CustomTimeRangeModalTimezoneTranslation.test.tsx +285 -0
  511. package/Tests/UI/Components/Dropdown.test.tsx +999 -2
  512. package/Tests/UI/Components/FieldLabelInfoCardTooltip.test.tsx +413 -0
  513. package/Tests/UI/Components/Forms/FormFieldCheckboxTranslation.test.tsx +216 -0
  514. package/Tests/UI/Components/Forms/FormFieldTimezoneDescriptionTranslation.test.tsx +461 -0
  515. package/Tests/UI/Components/Forms/IncidentEpisodePublicNoteNotifyPayload.test.tsx +641 -0
  516. package/Tests/UI/Components/Forms/IncidentPublicNoteNotifyPayload.test.tsx +346 -0
  517. package/Tests/UI/Components/Forms/ScheduledMaintenancePublicNoteNotifyPayload.test.tsx +493 -0
  518. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +911 -2
  519. package/Tests/UI/Components/Graphs/DayUptimeGraphTimezone.NewYork.test.tsx +730 -0
  520. package/Tests/UI/Components/Graphs/DayUptimeGraphTimezone.Tokyo.test.tsx +506 -0
  521. package/Tests/UI/Components/HistogramClickToZoom.test.tsx +619 -0
  522. package/Tests/UI/Components/InfoTooltip.test.tsx +242 -0
  523. package/Tests/UI/Components/LogDetailsPanelAttributesJSON.test.tsx +248 -0
  524. package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +47 -1
  525. package/Tests/UI/Components/LogsViewerSmallScreens.test.tsx +620 -0
  526. package/Tests/UI/Components/ModelPageModelChange.test.tsx +242 -3
  527. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +207 -3
  528. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDeleteVerb.test.tsx +367 -0
  529. package/Tests/UI/Components/ModelTable/BaseModelTableCreateButtonTitle.test.tsx +275 -0
  530. package/Tests/UI/Components/ModelTable/BaseModelTableDeleteConfirmation.test.tsx +521 -0
  531. package/Tests/UI/Components/MonitorGraphs/Uptime.test.tsx +406 -2
  532. package/Tests/UI/Components/MonitorGraphs/UptimeBarDayModal.test.tsx +169 -2
  533. package/Tests/UI/Components/TableHeaderTooltip.test.tsx +662 -0
  534. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +266 -0
  535. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerSmallScreens.test.tsx +439 -0
  536. package/Tests/UI/Components/TimezoneDropdownLegacyValues.test.tsx +704 -0
  537. package/Tests/UI/Components/UseHistogramZoom.test.tsx +89 -1
  538. package/Tests/UI/Components/UseLogsHistogram.test.tsx +175 -0
  539. package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +5 -5
  540. package/Tests/UI/Rum/PrivacySummaryCard.test.tsx +166 -9
  541. package/Tests/UI/Rum/RecordingHealthTooltips.test.tsx +447 -0
  542. package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +164 -0
  543. package/Tests/UI/Rum/ReplayFrameCapture.test.ts +6750 -0
  544. package/Tests/UI/Rum/ReplayRail.test.tsx +723 -12
  545. package/Tests/UI/Rum/ReplayRailDetail.test.tsx +86 -0
  546. package/Tests/UI/Rum/ReplayScreenshot.test.ts +2124 -0
  547. package/Tests/UI/Rum/ReplayScreenshotActions.test.tsx +3288 -0
  548. package/Tests/UI/Rum/ReplayStage.test.tsx +62 -0
  549. package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +983 -2
  550. package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +149 -0
  551. package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +107 -6
  552. package/Tests/UI/Rum/SessionReplayUsersTableTooltips.test.tsx +330 -0
  553. package/Tests/UI/Rum/UserFlowTooltips.test.tsx +886 -0
  554. package/Tests/UI/Telemetry/TelemetryDetailPanel.test.tsx +28 -0
  555. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  556. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  557. package/Tests/UI/Utils/PermissionGate.test.ts +76 -0
  558. package/Tests/UI/Utils/ProjectUsersModelAPI.test.ts +51 -0
  559. package/Tests/UI/Utils/Timezone.test.ts +747 -33
  560. package/Tests/UI/Workspace/SendTestNotificationButton.test.tsx +1854 -0
  561. package/Tests/UI/Workspace/WorkspaceCardsSendTestNotification.test.tsx +1864 -0
  562. package/Tests/Utils/AI/InvestigationReport.test.ts +435 -7
  563. package/Tests/Utils/AiRemediation/KubectlAllowlistValidatorParity.test.ts +1084 -0
  564. package/Tests/Utils/AiRemediation/KubectlOutputRedactor.test.ts +2531 -0
  565. package/Tests/Utils/AiRemediation/KubectlPolicy.test.ts +1895 -0
  566. package/Tests/Utils/AiRemediation/KubectlPolicyAllowlist.test.ts +428 -0
  567. package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +828 -0
  568. package/Tests/Utils/AiRemediation/KubectlPolicyCustomResourceScope.test.ts +573 -0
  569. package/Tests/Utils/AiRemediation/KubectlPolicyDenials.test.ts +1525 -0
  570. package/Tests/Utils/AiRemediation/KubectlPolicyExposeOverrides.test.ts +275 -0
  571. package/Tests/Utils/AiRemediation/KubectlPolicyNodePatch.test.ts +428 -0
  572. package/Tests/Utils/AiRemediation/KubectlPolicyObjectWords.test.ts +195 -0
  573. package/Tests/Utils/AiRemediation/KubectlPolicyPatchParents.test.ts +637 -0
  574. package/Tests/Utils/AiRemediation/KubectlPolicyPodSecurityBaseline.test.ts +322 -0
  575. package/Tests/Utils/AiRemediation/KubectlPolicySafeWriteScope.test.ts +1026 -0
  576. package/Tests/Utils/AiRemediation/KubectlWaitBudget.test.ts +267 -0
  577. package/Tests/Utils/AiRemediation/KubectlWriteScope.test.ts +390 -0
  578. package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +777 -0
  579. package/Tests/Utils/AiRemediation/KubectlWriteScopeClusterScoped.test.ts +613 -0
  580. package/Tests/Utils/AiRemediation/KubectlWriteScopeEntryPoint.test.ts +576 -0
  581. package/Tests/Utils/AiRemediation/KubectlWriteScopeKubectlSpellings.test.ts +752 -0
  582. package/Tests/Utils/AiRemediation/KubectlWriteScopeObjectWords.test.ts +358 -0
  583. package/Tests/Utils/AiRemediation/KubectlWriteScopeOverrides.test.ts +293 -0
  584. package/Tests/Utils/AiRemediation/KubectlWriteScopeParityCases.ts +598 -0
  585. package/Tests/Utils/AiRemediation/KubectlWriteScopePolicyParity.test.ts +403 -0
  586. package/Tests/Utils/Dashboard/DashboardClockComponent.test.ts +154 -5
  587. package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +696 -0
  588. package/Tests/Utils/Monitor/IncomingEmailMonitorAddress.test.ts +478 -0
  589. package/Tests/Utils/Monitor/MonitorCheckScheduleUtil.test.ts +646 -0
  590. package/Tests/Utils/Monitor/MonitorOverviewCriteriaUtil.test.ts +292 -0
  591. package/Tests/Utils/Monitor/MonitorOverviewFamily.test.ts +274 -0
  592. package/Tests/Utils/Monitor/MonitorOverviewPresentationUtil.test.ts +3100 -0
  593. package/Tests/Utils/Monitor/MonitorOverviewProbeUtil.test.ts +1412 -0
  594. package/Tests/Utils/Monitor/MonitorOverviewTargetUtil.test.ts +374 -0
  595. package/Tests/Utils/Monitor/MonitorStatusHistoryUtil.test.ts +332 -0
  596. package/Tests/Utils/Monitor/MonitorUptimeSummaryUtil.test.ts +946 -0
  597. package/Tests/Utils/Rum/SessionIdentity.test.ts +94 -0
  598. package/Tests/Utils/Rum/SessionReplayWafCompatibility.test.ts +840 -0
  599. package/Tests/Utils/Rum/SessionReplayWireEncoding.test.ts +208 -0
  600. package/Tests/Utils/Rum/SessionTraceState.test.ts +239 -0
  601. package/Tests/Utils/Rum/UserFlow.test.ts +1010 -0
  602. package/Tests/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.test.ts +217 -0
  603. package/Tests/Utils/StatusPage/ResourceUptime.test.ts +1272 -1
  604. package/Tests/Utils/StatusPage/UptimeDailyAggregateTotals.test.ts +298 -0
  605. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +649 -1
  606. package/Tests/Utils/StatusPage/UptimeDailyAggregateWindow.test.ts +314 -0
  607. package/Tests/Utils/Telemetry/AttributesJSON.test.ts +454 -0
  608. package/Tests/Utils/Uptime/DayUptimeGraphUtil.test.ts +418 -2
  609. package/Tests/Utils/Uptime/DayUptimeGraphUtilMidnightDst.test.ts +160 -0
  610. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.Auckland.test.ts +45 -0
  611. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.Kolkata.test.ts +40 -0
  612. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.London.test.ts +147 -0
  613. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.NewYork.test.ts +48 -0
  614. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.Tokyo.test.ts +39 -0
  615. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezoneCases.ts +1015 -0
  616. package/Tests/Utils/Uptime/UptimeUtil.test.ts +75 -0
  617. package/Tests/Utils/Uptime/UptimeUtilChronologicalOrder.test.ts +1279 -0
  618. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +203 -5
  619. package/Types/Date.ts +121 -7
  620. package/Types/Email/EmailMessage.ts +8 -0
  621. package/Types/Email/EmailTemplateType.ts +1 -0
  622. package/Types/Exception/ExceptionMessages.ts +1 -0
  623. package/Types/Incident/IncidentAlertLink.ts +38 -0
  624. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +488 -0
  625. package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +54 -0
  626. package/Types/Kubernetes/KubernetesClusterAiAccessToolNames.ts +17 -0
  627. package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +9 -0
  628. package/Types/Monitor/DatabaseMonitor/SqlServerPlatform.ts +117 -0
  629. package/Types/Monitor/KubernetesAlertTemplates.ts +6 -5
  630. package/Types/Monitor/MonitorStepExceptionMonitor.ts +56 -0
  631. package/Types/Monitor/MonitorUptimeSummary.ts +113 -0
  632. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +11 -0
  633. package/Types/Permission.ts +48 -0
  634. package/Types/Rum/SessionReplay.ts +80 -8
  635. package/Types/Rum/SessionReplayApi.ts +44 -1
  636. package/Types/Rum/UserFlow.ts +187 -0
  637. package/Types/Rum/WebVitals.ts +52 -0
  638. package/Types/Runbook/RunbookStepType.ts +10 -0
  639. package/Types/Runbook/RunnerJobOrigin.ts +15 -0
  640. package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +6 -2
  641. package/Types/StatusPage/MergedDowntimeTotals.ts +17 -0
  642. package/Types/StatusPage/PublicNoteSubscriberNotificationDefault.ts +148 -0
  643. package/Types/StatusPage/UptimeDailyAggregate.ts +15 -0
  644. package/Types/Telemetry/TelemetryIngestSurface.ts +9 -0
  645. package/Types/Timezone.ts +5 -0
  646. package/Types/TimezoneAlias.ts +385 -0
  647. package/Types/Workflow/Templates.ts +3041 -2
  648. package/Types/Workflow/WorkflowVariableOAuth.ts +476 -0
  649. package/Types/Workspace/WorkspaceNoteReaction.ts +132 -0
  650. package/Typings/Index.d.ts +24 -0
  651. package/UI/Components/AttributesJSON/AttributesJSONPreferences.ts +175 -0
  652. package/UI/Components/AttributesJSON/AttributesJSONView.tsx +138 -0
  653. package/UI/Components/AttributesJSON/AttributesViewToggle.tsx +79 -0
  654. package/UI/Components/AttributesJSON/BracesGlyph.tsx +30 -0
  655. package/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.tsx +491 -0
  656. package/UI/Components/AttributesJSON/JSONHighlight.ts +77 -0
  657. package/UI/Components/Calendar/Calendar.css +83 -0
  658. package/UI/Components/Calendar/Calendar.tsx +136 -7
  659. package/UI/Components/Calendar/CalendarDayLayout.ts +236 -0
  660. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +23 -1
  661. package/UI/Components/Charts/Utils/HistogramSelection.ts +117 -0
  662. package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +269 -0
  663. package/UI/Components/Charts/Utils/useHistogramZoom.ts +26 -2
  664. package/UI/Components/Date/CustomTimeRangeModal.tsx +26 -3
  665. package/UI/Components/Detail/FieldLabel.tsx +8 -0
  666. package/UI/Components/Dropdown/Dropdown.tsx +58 -9
  667. package/UI/Components/Forms/Fields/FormField.tsx +49 -14
  668. package/UI/Components/Graphs/DayUptimeGraph.tsx +166 -25
  669. package/UI/Components/Graphs/UptimeBarTooltip.tsx +10 -2
  670. package/UI/Components/Graphs/UptimeDaySummary.tsx +8 -0
  671. package/UI/Components/InfoCard/InfoCard.tsx +47 -1
  672. package/UI/Components/LogsViewer/LogsViewer.tsx +52 -5
  673. package/UI/Components/LogsViewer/components/ColumnSelector.tsx +13 -2
  674. package/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.tsx +13 -1
  675. package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +91 -76
  676. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +15 -1
  677. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +28 -106
  678. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +54 -6
  679. package/UI/Components/LogsViewer/components/SavedViewsDropdown.tsx +8 -2
  680. package/UI/Components/LogsViewer/useLogsHistogram.ts +39 -6
  681. package/UI/Components/ModelTable/BaseModelTable.tsx +161 -31
  682. package/UI/Components/ModelTable/Column.ts +5 -0
  683. package/UI/Components/MonitorGraphs/Uptime.tsx +12 -0
  684. package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +10 -2
  685. package/UI/Components/Page/ModelPage.tsx +59 -3
  686. package/UI/Components/Table/TableHeader.tsx +47 -2
  687. package/UI/Components/Table/Types/Column.ts +7 -0
  688. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +69 -5
  689. package/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.tsx +12 -1
  690. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +15 -1
  691. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +36 -104
  692. package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +9 -1
  693. package/UI/Components/Tooltip/InfoTooltip.tsx +78 -0
  694. package/UI/Utils/ModelAPI/ProjectUsersModelAPI.ts +19 -1
  695. package/UI/Utils/PermissionGate.ts +11 -2
  696. package/UI/Utils/Timezone.ts +69 -28
  697. package/Utils/AI/InvestigationReport.ts +195 -25
  698. package/Utils/AiRemediation/KubectlOutputRedactor.ts +1724 -0
  699. package/Utils/AiRemediation/KubectlPolicy.ts +4136 -0
  700. package/Utils/AiRemediation/KubectlWaitBudget.ts +156 -0
  701. package/Utils/AiRemediation/KubectlWriteScope.ts +1964 -0
  702. package/Utils/Dashboard/Components/DashboardClockComponent.ts +7 -6
  703. package/Utils/Incident/IncidentFromAlerts.ts +516 -0
  704. package/Utils/Monitor/IncomingEmailMonitorAddress.ts +292 -0
  705. package/Utils/Monitor/MonitorCheckScheduleUtil.ts +654 -0
  706. package/Utils/Monitor/MonitorOverviewCriteriaUtil.ts +188 -0
  707. package/Utils/Monitor/MonitorOverviewFamily.ts +263 -0
  708. package/Utils/Monitor/MonitorOverviewPresentationUtil.ts +1958 -0
  709. package/Utils/Monitor/MonitorOverviewProbeUtil.ts +979 -0
  710. package/Utils/Monitor/MonitorOverviewTargetUtil.ts +299 -0
  711. package/Utils/Monitor/MonitorStatusHistoryUtil.ts +201 -0
  712. package/Utils/Monitor/MonitorUptimeSummaryUtil.ts +638 -0
  713. package/Utils/Rum/SessionIdentity.ts +44 -0
  714. package/Utils/Rum/SessionReplayWireEncoding.ts +137 -0
  715. package/Utils/Rum/SessionTraceState.ts +212 -0
  716. package/Utils/Rum/UserFlow.ts +1527 -0
  717. package/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.ts +107 -0
  718. package/Utils/StatusPage/ResourceUptime.ts +99 -0
  719. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +197 -0
  720. package/Utils/Telemetry/AttributesJSON.ts +367 -0
  721. package/Utils/Uptime/DayUptimeGraphUtil.ts +165 -0
  722. package/Utils/Uptime/UptimeUtil.ts +122 -38
  723. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +8 -1
  724. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
  725. package/build/dist/Models/DatabaseModels/AlertFeed.js +2 -0
  726. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  727. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
  728. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
  729. package/build/dist/Models/DatabaseModels/IncidentAlert.js +553 -0
  730. package/build/dist/Models/DatabaseModels/IncidentAlert.js.map +1 -0
  731. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +8 -1
  732. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
  733. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +10 -3
  734. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
  735. package/build/dist/Models/DatabaseModels/IncidentFeed.js +2 -0
  736. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
  737. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +10 -3
  738. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  739. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  740. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  741. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +434 -0
  742. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  743. package/build/dist/Models/DatabaseModels/Monitor.js +49 -0
  744. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  745. package/build/dist/Models/DatabaseModels/Project.js +62 -0
  746. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  747. package/build/dist/Models/DatabaseModels/RumApplication.js +53 -1
  748. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  749. package/build/dist/Models/DatabaseModels/Runner.js +4 -4
  750. package/build/dist/Models/DatabaseModels/Runner.js.map +1 -1
  751. package/build/dist/Models/DatabaseModels/RunnerJob.js +66 -0
  752. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
  753. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +11 -3
  754. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  755. package/build/dist/Models/DatabaseModels/WorkflowVariable.js +487 -3
  756. package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
  757. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js +64 -16
  758. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  759. package/build/dist/Server/API/AIInvestigationAPI.js +205 -0
  760. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  761. package/build/dist/Server/API/AutoRemediationAPI.js +115 -2
  762. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  763. package/build/dist/Server/API/CommonAPI.js +49 -0
  764. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  765. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +564 -0
  766. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -0
  767. package/build/dist/Server/API/MicrosoftTeamsAPI.js +465 -176
  768. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  769. package/build/dist/Server/API/MonitorAPI.js +107 -1
  770. package/build/dist/Server/API/MonitorAPI.js.map +1 -1
  771. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js +5 -16
  772. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js.map +1 -1
  773. package/build/dist/Server/API/SlackAPI.js +322 -78
  774. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  775. package/build/dist/Server/API/StatusPageAPI.js +123 -17
  776. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  777. package/build/dist/Server/API/TelemetryAPI.js +144 -5
  778. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  779. package/build/dist/Server/API/UserTwoFactorBackupCodeAPI.js +1 -0
  780. package/build/dist/Server/API/UserTwoFactorBackupCodeAPI.js.map +1 -1
  781. package/build/dist/Server/API/WorkflowVariableAPI.js +109 -0
  782. package/build/dist/Server/API/WorkflowVariableAPI.js.map +1 -0
  783. package/build/dist/Server/Infrastructure/GlobalCache.js +29 -0
  784. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  785. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794300000000-AddOAuth2WorkflowVariables.js +38 -0
  786. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794300000000-AddOAuth2WorkflowVariables.js.map +1 -0
  787. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794400000000-AddKubernetesClusterAiAccess.js +54 -0
  788. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794400000000-AddKubernetesClusterAiAccess.js.map +1 -0
  789. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794500000000-AddIncomingEmailCustomAddressToMonitor.js +14 -0
  790. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794500000000-AddIncomingEmailCustomAddressToMonitor.js.map +1 -0
  791. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794600000000-AddAuthTokenExpiresAtToWorkspaceProjectAuthToken.js +12 -0
  792. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794600000000-AddAuthTokenExpiresAtToWorkspaceProjectAuthToken.js.map +1 -0
  793. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794700000000-RemoveAppAccessTokenFromWorkspaceProjectAuthTokenMiscData.js +32 -0
  794. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794700000000-RemoveAppAccessTokenFromWorkspaceProjectAuthTokenMiscData.js.map +1 -0
  795. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js +20 -0
  796. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js.map +1 -0
  797. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js +42 -0
  798. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js.map +1 -0
  799. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
  800. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  801. package/build/dist/Server/Middleware/MasterAdminAuthorization.js +21 -0
  802. package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
  803. package/build/dist/Server/Middleware/TelemetryIngest.js +32 -2
  804. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  805. package/build/dist/Server/Middleware/UserAuthorization.js +39 -6
  806. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  807. package/build/dist/Server/Services/AIAgentService.js +1 -0
  808. package/build/dist/Server/Services/AIAgentService.js.map +1 -1
  809. package/build/dist/Server/Services/AccessTokenService.js +87 -42
  810. package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
  811. package/build/dist/Server/Services/AlertEpisodeMemberService.js +4 -0
  812. package/build/dist/Server/Services/AlertEpisodeMemberService.js.map +1 -1
  813. package/build/dist/Server/Services/AlertEpisodeService.js +12 -1
  814. package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
  815. package/build/dist/Server/Services/AlertService.js +110 -23
  816. package/build/dist/Server/Services/AlertService.js.map +1 -1
  817. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +716 -30
  818. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  819. package/build/dist/Server/Services/AutoRemediationRuleService.js +100 -0
  820. package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
  821. package/build/dist/Server/Services/BillingService.js +1 -0
  822. package/build/dist/Server/Services/BillingService.js.map +1 -1
  823. package/build/dist/Server/Services/InboundEmail/Providers/SendGridInboundProvider.js +11 -16
  824. package/build/dist/Server/Services/InboundEmail/Providers/SendGridInboundProvider.js.map +1 -1
  825. package/build/dist/Server/Services/IncidentAlertService.js +1370 -0
  826. package/build/dist/Server/Services/IncidentAlertService.js.map +1 -0
  827. package/build/dist/Server/Services/IncidentEpisodeMemberService.js +4 -0
  828. package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
  829. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +48 -0
  830. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  831. package/build/dist/Server/Services/IncidentEpisodeRoleMemberService.js +21 -0
  832. package/build/dist/Server/Services/IncidentEpisodeRoleMemberService.js.map +1 -1
  833. package/build/dist/Server/Services/IncidentEpisodeService.js +12 -1
  834. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  835. package/build/dist/Server/Services/IncidentGroupingEngineService.js +8 -0
  836. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  837. package/build/dist/Server/Services/IncidentMemberService.js +14 -0
  838. package/build/dist/Server/Services/IncidentMemberService.js.map +1 -1
  839. package/build/dist/Server/Services/IncidentPublicNoteService.js +48 -0
  840. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  841. package/build/dist/Server/Services/IncidentService.js +263 -33
  842. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  843. package/build/dist/Server/Services/IncidentStateTimelineService.js +33 -0
  844. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  845. package/build/dist/Server/Services/IncidentTemplateService.js +68 -4
  846. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  847. package/build/dist/Server/Services/Index.js +2 -0
  848. package/build/dist/Server/Services/Index.js.map +1 -1
  849. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +1470 -0
  850. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -0
  851. package/build/dist/Server/Services/KubernetesClusterService.js +1097 -0
  852. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  853. package/build/dist/Server/Services/LogAggregationService.js +14 -6
  854. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  855. package/build/dist/Server/Services/MonitorService.js +487 -48
  856. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  857. package/build/dist/Server/Services/MonitorStatusTimelineService.js +540 -3
  858. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  859. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +2 -0
  860. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  861. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +2 -0
  862. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  863. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +2 -0
  864. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  865. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +3 -0
  866. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  867. package/build/dist/Server/Services/OnCallNotificationAlertingService.js +29 -7
  868. package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -1
  869. package/build/dist/Server/Services/OnCallSetupReminderService.js +1 -0
  870. package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -1
  871. package/build/dist/Server/Services/ProbeService.js +7 -1
  872. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  873. package/build/dist/Server/Services/ProjectService.js +11 -1
  874. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  875. package/build/dist/Server/Services/RunbookCredentialService.js +24 -0
  876. package/build/dist/Server/Services/RunbookCredentialService.js.map +1 -1
  877. package/build/dist/Server/Services/RunbookSecretService.js +44 -0
  878. package/build/dist/Server/Services/RunbookSecretService.js.map +1 -1
  879. package/build/dist/Server/Services/RunnerJobService.js +641 -21
  880. package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
  881. package/build/dist/Server/Services/RunnerService.js +344 -5
  882. package/build/dist/Server/Services/RunnerService.js.map +1 -1
  883. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +48 -0
  884. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  885. package/build/dist/Server/Services/ScheduledMaintenanceService.js +102 -20
  886. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  887. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +67 -4
  888. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
  889. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +12 -1
  890. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  891. package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -0
  892. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  893. package/build/dist/Server/Services/StatusPageService.js +230 -32
  894. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  895. package/build/dist/Server/Services/StatusPageSubscriberService.js +4 -0
  896. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  897. package/build/dist/Server/Services/TeamMemberService.js +270 -11
  898. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  899. package/build/dist/Server/Services/TraceAggregationService.js +10 -6
  900. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  901. package/build/dist/Server/Services/UserEmailService.js +1 -0
  902. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  903. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1 -0
  904. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -1
  905. package/build/dist/Server/Services/UserNotificationRuleAdminService.js +1 -0
  906. package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -1
  907. package/build/dist/Server/Services/UserNotificationRuleService.js +4 -0
  908. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  909. package/build/dist/Server/Services/UserService.js +107 -1
  910. package/build/dist/Server/Services/UserService.js.map +1 -1
  911. package/build/dist/Server/Services/WorkflowVariableService.js +396 -7
  912. package/build/dist/Server/Services/WorkflowVariableService.js.map +1 -1
  913. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +463 -7
  914. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  915. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +144 -2
  916. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
  917. package/build/dist/Server/Types/Database/QueryHelper.js +20 -0
  918. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  919. package/build/dist/Server/Types/Markdown.js +394 -27
  920. package/build/dist/Server/Types/Markdown.js.map +1 -1
  921. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +123 -0
  922. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -0
  923. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +344 -0
  924. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -0
  925. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +587 -0
  926. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -0
  927. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js +18 -2
  928. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js.map +1 -1
  929. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1380 -239
  930. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  931. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +1099 -68
  932. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  933. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +88 -6
  934. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  935. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +45 -11
  936. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  937. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +41 -11
  938. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  939. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js +11 -4
  940. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -1
  941. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +4 -2
  942. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -1
  943. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +997 -141
  944. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
  945. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +299 -4
  946. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
  947. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js +120 -0
  948. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js.map +1 -0
  949. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +160 -1
  950. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
  951. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +1 -0
  952. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
  953. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +59 -12
  954. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  955. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +5 -1
  956. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  957. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +84 -22
  958. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  959. package/build/dist/Server/Utils/Monitor/MonitorPayloadRedaction.js +70 -5
  960. package/build/dist/Server/Utils/Monitor/MonitorPayloadRedaction.js.map +1 -1
  961. package/build/dist/Server/Utils/Monitor/ProbeMonitorsNotification.js +249 -0
  962. package/build/dist/Server/Utils/Monitor/ProbeMonitorsNotification.js.map +1 -0
  963. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js +1 -0
  964. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js.map +1 -1
  965. package/build/dist/Server/Utils/PushNotificationUtil.js +27 -0
  966. package/build/dist/Server/Utils/PushNotificationUtil.js.map +1 -1
  967. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +26 -3
  968. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -1
  969. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js +38 -3
  970. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js.map +1 -1
  971. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +8 -0
  972. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
  973. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +143 -23
  974. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
  975. package/build/dist/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.js +406 -0
  976. package/build/dist/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.js.map +1 -0
  977. package/build/dist/Server/Utils/StartServer.js +4 -3
  978. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  979. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +382 -0
  980. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -0
  981. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js +1 -0
  982. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js.map +1 -1
  983. package/build/dist/Server/Utils/UserPermission/UserPermission.js +10 -0
  984. package/build/dist/Server/Utils/UserPermission/UserPermission.js.map +1 -1
  985. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js +447 -0
  986. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js.map +1 -0
  987. package/build/dist/Server/Utils/Workflow/WorkflowVariableOAuthToken.js +202 -0
  988. package/build/dist/Server/Utils/Workflow/WorkflowVariableOAuthToken.js.map +1 -0
  989. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +39 -1
  990. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
  991. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +44 -4
  992. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
  993. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +150 -191
  994. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  995. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +44 -4
  996. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  997. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js +39 -17
  998. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js.map +1 -1
  999. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +151 -145
  1000. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
  1001. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +221 -127
  1002. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  1003. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsServiceUrl.js +91 -0
  1004. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsServiceUrl.js.map +1 -0
  1005. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/ReactionNoteSync.js +673 -0
  1006. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/ReactionNoteSync.js.map +1 -0
  1007. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js +3 -9
  1008. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js.map +1 -1
  1009. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +65 -166
  1010. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js.map +1 -1
  1011. package/build/dist/Server/Utils/Workspace/Slack/Actions/AlertEpisode.js +63 -157
  1012. package/build/dist/Server/Utils/Workspace/Slack/Actions/AlertEpisode.js.map +1 -1
  1013. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +23 -3
  1014. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -1
  1015. package/build/dist/Server/Utils/Workspace/Slack/Actions/Authorization.js +92 -0
  1016. package/build/dist/Server/Utils/Workspace/Slack/Actions/Authorization.js.map +1 -0
  1017. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +81 -210
  1018. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js.map +1 -1
  1019. package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js +68 -138
  1020. package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js.map +1 -1
  1021. package/build/dist/Server/Utils/Workspace/Slack/Actions/ReactionNote.js +240 -0
  1022. package/build/dist/Server/Utils/Workspace/Slack/Actions/ReactionNote.js.map +1 -0
  1023. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js +85 -212
  1024. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js.map +1 -1
  1025. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +60 -17
  1026. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  1027. package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +2 -0
  1028. package/build/dist/Server/Utils/Workspace/Workspace.js +134 -41
  1029. package/build/dist/Server/Utils/Workspace/Workspace.js.map +1 -1
  1030. package/build/dist/Server/Utils/Workspace/WorkspaceActionAuthorization.js +197 -0
  1031. package/build/dist/Server/Utils/Workspace/WorkspaceActionAuthorization.js.map +1 -0
  1032. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js +32 -0
  1033. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  1034. package/build/dist/Server/Utils/Workspace/WorkspaceOAuthState.js +199 -0
  1035. package/build/dist/Server/Utils/Workspace/WorkspaceOAuthState.js.map +1 -0
  1036. package/build/dist/Server/Utils/Workspace/WorkspaceProjectReferenceValidator.js +91 -0
  1037. package/build/dist/Server/Utils/Workspace/WorkspaceProjectReferenceValidator.js.map +1 -0
  1038. package/build/dist/Server/Utils/Workspace/WorkspaceReactionNote.js +450 -0
  1039. package/build/dist/Server/Utils/Workspace/WorkspaceReactionNote.js.map +1 -0
  1040. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +103 -5
  1041. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
  1042. package/build/dist/Types/Date.js +97 -7
  1043. package/build/dist/Types/Date.js.map +1 -1
  1044. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  1045. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  1046. package/build/dist/Types/Exception/ExceptionMessages.js +1 -0
  1047. package/build/dist/Types/Exception/ExceptionMessages.js.map +1 -1
  1048. package/build/dist/Types/Incident/IncidentAlertLink.js +34 -0
  1049. package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -0
  1050. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +245 -0
  1051. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -0
  1052. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +49 -0
  1053. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -0
  1054. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessToolNames.js +16 -0
  1055. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessToolNames.js.map +1 -0
  1056. package/build/dist/Types/Monitor/DatabaseMonitor/SqlServerPlatform.js +104 -0
  1057. package/build/dist/Types/Monitor/DatabaseMonitor/SqlServerPlatform.js.map +1 -0
  1058. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +6 -5
  1059. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  1060. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js +32 -0
  1061. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js.map +1 -1
  1062. package/build/dist/Types/Monitor/MonitorUptimeSummary.js +52 -0
  1063. package/build/dist/Types/Monitor/MonitorUptimeSummary.js.map +1 -0
  1064. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +9 -1
  1065. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
  1066. package/build/dist/Types/Permission.js +42 -0
  1067. package/build/dist/Types/Permission.js.map +1 -1
  1068. package/build/dist/Types/Rum/SessionReplay.js +52 -2
  1069. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  1070. package/build/dist/Types/Rum/SessionReplayApi.js +11 -0
  1071. package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
  1072. package/build/dist/Types/Rum/UserFlow.js +115 -0
  1073. package/build/dist/Types/Rum/UserFlow.js.map +1 -0
  1074. package/build/dist/Types/Rum/WebVitals.js +25 -0
  1075. package/build/dist/Types/Rum/WebVitals.js.map +1 -1
  1076. package/build/dist/Types/Runbook/RunbookStepType.js +10 -0
  1077. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  1078. package/build/dist/Types/Runbook/RunnerJobOrigin.js +14 -0
  1079. package/build/dist/Types/Runbook/RunnerJobOrigin.js.map +1 -1
  1080. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +2 -2
  1081. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -1
  1082. package/build/dist/Types/StatusPage/MergedDowntimeTotals.js +2 -0
  1083. package/build/dist/Types/StatusPage/MergedDowntimeTotals.js.map +1 -0
  1084. package/build/dist/Types/StatusPage/PublicNoteSubscriberNotificationDefault.js +65 -0
  1085. package/build/dist/Types/StatusPage/PublicNoteSubscriberNotificationDefault.js.map +1 -0
  1086. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +8 -0
  1087. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
  1088. package/build/dist/Types/Timezone.js +5 -0
  1089. package/build/dist/Types/Timezone.js.map +1 -1
  1090. package/build/dist/Types/TimezoneAlias.js +340 -0
  1091. package/build/dist/Types/TimezoneAlias.js.map +1 -0
  1092. package/build/dist/Types/Workflow/Templates.js +2694 -2
  1093. package/build/dist/Types/Workflow/Templates.js.map +1 -1
  1094. package/build/dist/Types/Workflow/WorkflowVariableOAuth.js +314 -0
  1095. package/build/dist/Types/Workflow/WorkflowVariableOAuth.js.map +1 -0
  1096. package/build/dist/Types/Workspace/WorkspaceNoteReaction.js +98 -0
  1097. package/build/dist/Types/Workspace/WorkspaceNoteReaction.js.map +1 -0
  1098. package/build/dist/UI/Components/AttributesJSON/AttributesJSONPreferences.js +95 -0
  1099. package/build/dist/UI/Components/AttributesJSON/AttributesJSONPreferences.js.map +1 -0
  1100. package/build/dist/UI/Components/AttributesJSON/AttributesJSONView.js +44 -0
  1101. package/build/dist/UI/Components/AttributesJSON/AttributesJSONView.js.map +1 -0
  1102. package/build/dist/UI/Components/AttributesJSON/AttributesViewToggle.js +27 -0
  1103. package/build/dist/UI/Components/AttributesJSON/AttributesViewToggle.js.map +1 -0
  1104. package/build/dist/UI/Components/AttributesJSON/BracesGlyph.js +9 -0
  1105. package/build/dist/UI/Components/AttributesJSON/BracesGlyph.js.map +1 -0
  1106. package/build/dist/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.js +260 -0
  1107. package/build/dist/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.js.map +1 -0
  1108. package/build/dist/UI/Components/AttributesJSON/JSONHighlight.js +56 -0
  1109. package/build/dist/UI/Components/AttributesJSON/JSONHighlight.js.map +1 -0
  1110. package/build/dist/UI/Components/Calendar/Calendar.js +94 -7
  1111. package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
  1112. package/build/dist/UI/Components/Calendar/CalendarDayLayout.js +136 -0
  1113. package/build/dist/UI/Components/Calendar/CalendarDayLayout.js.map +1 -0
  1114. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +1 -1
  1115. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  1116. package/build/dist/UI/Components/Charts/Utils/HistogramSelection.js +72 -0
  1117. package/build/dist/UI/Components/Charts/Utils/HistogramSelection.js.map +1 -0
  1118. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +178 -0
  1119. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -0
  1120. package/build/dist/UI/Components/Charts/Utils/useHistogramZoom.js +13 -1
  1121. package/build/dist/UI/Components/Charts/Utils/useHistogramZoom.js.map +1 -1
  1122. package/build/dist/UI/Components/Date/CustomTimeRangeModal.js +20 -4
  1123. package/build/dist/UI/Components/Date/CustomTimeRangeModal.js.map +1 -1
  1124. package/build/dist/UI/Components/Detail/FieldLabel.js +2 -0
  1125. package/build/dist/UI/Components/Detail/FieldLabel.js.map +1 -1
  1126. package/build/dist/UI/Components/Dropdown/Dropdown.js +33 -9
  1127. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  1128. package/build/dist/UI/Components/Forms/Fields/FormField.js +36 -13
  1129. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  1130. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +117 -11
  1131. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  1132. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +5 -1
  1133. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
  1134. package/build/dist/UI/Components/Graphs/UptimeDaySummary.js.map +1 -1
  1135. package/build/dist/UI/Components/InfoCard/InfoCard.js +22 -1
  1136. package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
  1137. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +36 -8
  1138. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  1139. package/build/dist/UI/Components/LogsViewer/components/ColumnSelector.js +10 -2
  1140. package/build/dist/UI/Components/LogsViewer/components/ColumnSelector.js.map +1 -1
  1141. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js +9 -1
  1142. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js.map +1 -1
  1143. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +16 -15
  1144. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
  1145. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +1 -1
  1146. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  1147. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +14 -74
  1148. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  1149. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +22 -5
  1150. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  1151. package/build/dist/UI/Components/LogsViewer/components/SavedViewsDropdown.js +9 -2
  1152. package/build/dist/UI/Components/LogsViewer/components/SavedViewsDropdown.js.map +1 -1
  1153. package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js +16 -5
  1154. package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js.map +1 -1
  1155. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +89 -22
  1156. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  1157. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +7 -1
  1158. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  1159. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +5 -1
  1160. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
  1161. package/build/dist/UI/Components/Page/ModelPage.js +37 -3
  1162. package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
  1163. package/build/dist/UI/Components/Table/TableHeader.js +18 -2
  1164. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  1165. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +27 -6
  1166. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  1167. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js +7 -1
  1168. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js.map +1 -1
  1169. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +1 -1
  1170. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  1171. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +17 -77
  1172. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  1173. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +10 -1
  1174. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
  1175. package/build/dist/UI/Components/Tooltip/InfoTooltip.js +28 -0
  1176. package/build/dist/UI/Components/Tooltip/InfoTooltip.js.map +1 -0
  1177. package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js +15 -1
  1178. package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js.map +1 -1
  1179. package/build/dist/UI/Utils/PermissionGate.js +4 -2
  1180. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  1181. package/build/dist/UI/Utils/Timezone.js +52 -17
  1182. package/build/dist/UI/Utils/Timezone.js.map +1 -1
  1183. package/build/dist/Utils/AI/InvestigationReport.js +116 -21
  1184. package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
  1185. package/build/dist/Utils/AiRemediation/KubectlOutputRedactor.js +1209 -0
  1186. package/build/dist/Utils/AiRemediation/KubectlOutputRedactor.js.map +1 -0
  1187. package/build/dist/Utils/AiRemediation/KubectlPolicy.js +2973 -0
  1188. package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -0
  1189. package/build/dist/Utils/AiRemediation/KubectlWaitBudget.js +99 -0
  1190. package/build/dist/Utils/AiRemediation/KubectlWaitBudget.js.map +1 -0
  1191. package/build/dist/Utils/AiRemediation/KubectlWriteScope.js +1429 -0
  1192. package/build/dist/Utils/AiRemediation/KubectlWriteScope.js.map +1 -0
  1193. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js +7 -6
  1194. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js.map +1 -1
  1195. package/build/dist/Utils/Incident/IncidentFromAlerts.js +306 -0
  1196. package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -0
  1197. package/build/dist/Utils/Monitor/IncomingEmailMonitorAddress.js +214 -0
  1198. package/build/dist/Utils/Monitor/IncomingEmailMonitorAddress.js.map +1 -0
  1199. package/build/dist/Utils/Monitor/MonitorCheckScheduleUtil.js +471 -0
  1200. package/build/dist/Utils/Monitor/MonitorCheckScheduleUtil.js.map +1 -0
  1201. package/build/dist/Utils/Monitor/MonitorOverviewCriteriaUtil.js +107 -0
  1202. package/build/dist/Utils/Monitor/MonitorOverviewCriteriaUtil.js.map +1 -0
  1203. package/build/dist/Utils/Monitor/MonitorOverviewFamily.js +191 -0
  1204. package/build/dist/Utils/Monitor/MonitorOverviewFamily.js.map +1 -0
  1205. package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js +1259 -0
  1206. package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js.map +1 -0
  1207. package/build/dist/Utils/Monitor/MonitorOverviewProbeUtil.js +593 -0
  1208. package/build/dist/Utils/Monitor/MonitorOverviewProbeUtil.js.map +1 -0
  1209. package/build/dist/Utils/Monitor/MonitorOverviewTargetUtil.js +195 -0
  1210. package/build/dist/Utils/Monitor/MonitorOverviewTargetUtil.js.map +1 -0
  1211. package/build/dist/Utils/Monitor/MonitorStatusHistoryUtil.js +127 -0
  1212. package/build/dist/Utils/Monitor/MonitorStatusHistoryUtil.js.map +1 -0
  1213. package/build/dist/Utils/Monitor/MonitorUptimeSummaryUtil.js +464 -0
  1214. package/build/dist/Utils/Monitor/MonitorUptimeSummaryUtil.js.map +1 -0
  1215. package/build/dist/Utils/Rum/SessionIdentity.js +31 -1
  1216. package/build/dist/Utils/Rum/SessionIdentity.js.map +1 -1
  1217. package/build/dist/Utils/Rum/SessionReplayWireEncoding.js +128 -0
  1218. package/build/dist/Utils/Rum/SessionReplayWireEncoding.js.map +1 -0
  1219. package/build/dist/Utils/Rum/SessionTraceState.js +154 -0
  1220. package/build/dist/Utils/Rum/SessionTraceState.js.map +1 -0
  1221. package/build/dist/Utils/Rum/UserFlow.js +941 -0
  1222. package/build/dist/Utils/Rum/UserFlow.js.map +1 -0
  1223. package/build/dist/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.js +82 -0
  1224. package/build/dist/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.js.map +1 -0
  1225. package/build/dist/Utils/StatusPage/ResourceUptime.js +46 -0
  1226. package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
  1227. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  1228. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -1
  1229. package/build/dist/Utils/Telemetry/AttributesJSON.js +245 -0
  1230. package/build/dist/Utils/Telemetry/AttributesJSON.js.map +1 -0
  1231. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js +103 -0
  1232. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js.map +1 -1
  1233. package/build/dist/Utils/Uptime/UptimeUtil.js +91 -27
  1234. package/build/dist/Utils/Uptime/UptimeUtil.js.map +1 -1
  1235. package/jest.config.json +2 -1
  1236. package/package.json +2 -1
  1237. package/tsconfig.tests.json +36 -0
  1238. package/Tests/UI/Components/EmptyState/EmptyStateGuideLinks.test.tsx +0 -337
  1239. package/UI/Components/EmptyState/EmptyStateGuideLinks.tsx +0 -124
  1240. package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js +0 -47
  1241. package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js.map +0 -1
@@ -0,0 +1,1811 @@
1
+ import CountBy from "../Types/Database/CountBy";
2
+ import CreateBy from "../Types/Database/CreateBy";
3
+ import DeleteBy from "../Types/Database/DeleteBy";
4
+ import FindBy from "../Types/Database/FindBy";
5
+ import { OnCreate, OnDelete, OnFind, OnUpdate } from "../Types/Database/Hooks";
6
+ import Query from "../Types/Database/Query";
7
+ import QueryHelper from "../Types/Database/QueryHelper";
8
+ import UpdateBy from "../Types/Database/UpdateBy";
9
+ import ModelPermission from "../Types/Database/Permissions/Index";
10
+ import DatabaseService from "./DatabaseService";
11
+ import AlertFeedService from "./AlertFeedService";
12
+ import AlertOwnerTeamService from "./AlertOwnerTeamService";
13
+ import AlertOwnerUserService from "./AlertOwnerUserService";
14
+ import AlertService from "./AlertService";
15
+ import AlertStateService from "./AlertStateService";
16
+ import IncidentFeedService from "./IncidentFeedService";
17
+ import IncidentService from "./IncidentService";
18
+ import IncidentStateService from "./IncidentStateService";
19
+ import ProjectService from "./ProjectService";
20
+ import { IsBillingEnabled } from "../EnvironmentConfig";
21
+ import { applyAlertRelatedRecordPrivacyFilter } from "../Utils/Alert/AlertPrivacyFilter";
22
+ import { applyIncidentRelatedRecordPrivacyFilter } from "../Utils/Incident/IncidentPrivacyFilter";
23
+ import PostgresErrorTranslator from "../Utils/Database/PostgresErrorTranslator";
24
+ import ProjectScopedReferenceValidator from "../Utils/Database/ProjectScopedReferenceValidator";
25
+ import RelationIdUtil from "../Utils/Database/RelationIdUtil";
26
+ import logger, { LogAttributes } from "../Utils/Logger";
27
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
28
+ import Model from "../../Models/DatabaseModels/IncidentAlert";
29
+ import Alert from "../../Models/DatabaseModels/Alert";
30
+ import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
31
+ import AlertOwnerTeam from "../../Models/DatabaseModels/AlertOwnerTeam";
32
+ import AlertOwnerUser from "../../Models/DatabaseModels/AlertOwnerUser";
33
+ import AlertState from "../../Models/DatabaseModels/AlertState";
34
+ import Incident from "../../Models/DatabaseModels/Incident";
35
+ import { IncidentFeedEventType } from "../../Models/DatabaseModels/IncidentFeed";
36
+ import IncidentState from "../../Models/DatabaseModels/IncidentState";
37
+ import Project from "../../Models/DatabaseModels/Project";
38
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
39
+ import { Gray500, Yellow500 } from "../../Types/BrandColors";
40
+ import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
41
+ import BadDataException from "../../Types/Exception/BadDataException";
42
+ import Exception from "../../Types/Exception/Exception";
43
+ import ForbiddenException from "../../Types/Exception/ForbiddenException";
44
+ import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
45
+ import NotFoundException from "../../Types/Exception/NotFoundException";
46
+ import {
47
+ INCIDENT_ALERT_ALREADY_LINKED_MESSAGE,
48
+ INCIDENT_ALERT_IDS_TO_LINK_KEY,
49
+ MAX_ALERTS_PER_INCIDENT_LINK_ACTION,
50
+ } from "../../Types/Incident/IncidentAlertLink";
51
+ import ObjectID from "../../Types/ObjectID";
52
+ import PositiveNumber from "../../Types/PositiveNumber";
53
+
54
+ /*
55
+ * Which of the two opt-in project switches apply to an incident's state.
56
+ * Only the switches the incident's state has reached are true: an incident
57
+ * that is merely acknowledged never resolves its alerts, whatever the
58
+ * resolve switch says.
59
+ */
60
+ export interface LinkedAlertStateTargets {
61
+ acknowledge: boolean;
62
+ resolve: boolean;
63
+ // The incident has reached (or passed) its project's Resolved state.
64
+ incidentReachedResolved: boolean;
65
+ }
66
+
67
+ /*
68
+ * The decision half of the linked-alert state sync, shared by the cascade
69
+ * (an incident changes state) and the link-time sync (an alert is linked to
70
+ * an incident that is already acknowledged or resolved).
71
+ *
72
+ * States are compared by `order`, never by the isAcknowledgedState /
73
+ * isResolvedState flags: projects add custom states (say "Monitoring") between
74
+ * Acknowledged and Resolved, and an incident sitting in one of those has
75
+ * still been acknowledged. An incident project without an Acknowledged (or
76
+ * Resolved) state simply never triggers that half.
77
+ */
78
+ export function getLinkedAlertStateTargets(data: {
79
+ incidentStateOrder: number;
80
+ acknowledgedIncidentStateOrder: number | undefined;
81
+ resolvedIncidentStateOrder: number | undefined;
82
+ acknowledgeSwitch: boolean;
83
+ resolveSwitch: boolean;
84
+ }): LinkedAlertStateTargets {
85
+ const reachedAcknowledged: boolean =
86
+ data.acknowledgedIncidentStateOrder !== undefined &&
87
+ data.incidentStateOrder >= data.acknowledgedIncidentStateOrder;
88
+
89
+ const reachedResolved: boolean =
90
+ data.resolvedIncidentStateOrder !== undefined &&
91
+ data.incidentStateOrder >= data.resolvedIncidentStateOrder;
92
+
93
+ return {
94
+ acknowledge: data.acknowledgeSwitch && reachedAcknowledged,
95
+ resolve: data.resolveSwitch && reachedResolved,
96
+ incidentReachedResolved: reachedResolved,
97
+ };
98
+ }
99
+
100
+ /*
101
+ * The alert state one linked alert should move to, or null to leave it alone.
102
+ *
103
+ * Resolve wins when it applies and the alert is not held back by another
104
+ * linked incident that is still open; acknowledge is the fallback, so an
105
+ * alert that cannot be resolved yet is at least acknowledged (which is what
106
+ * stops its paging). An alert is never moved backwards and never "moved" to
107
+ * where it already is: anything at or past the target is left untouched.
108
+ */
109
+ export function chooseLinkedAlertTargetState<
110
+ TState extends { order?: number | undefined },
111
+ >(data: {
112
+ alertStateOrder: number;
113
+ acknowledgedAlertState: TState | undefined;
114
+ resolvedAlertState: TState | undefined;
115
+ isBlockedFromResolve: boolean;
116
+ }): TState | null {
117
+ const resolvedOrder: number | undefined = data.resolvedAlertState?.order;
118
+
119
+ if (
120
+ data.resolvedAlertState &&
121
+ resolvedOrder !== undefined &&
122
+ !data.isBlockedFromResolve &&
123
+ data.alertStateOrder < resolvedOrder
124
+ ) {
125
+ return data.resolvedAlertState;
126
+ }
127
+
128
+ const acknowledgedOrder: number | undefined =
129
+ data.acknowledgedAlertState?.order;
130
+
131
+ if (
132
+ data.acknowledgedAlertState &&
133
+ acknowledgedOrder !== undefined &&
134
+ data.alertStateOrder < acknowledgedOrder
135
+ ) {
136
+ return data.acknowledgedAlertState;
137
+ }
138
+
139
+ return null;
140
+ }
141
+
142
+ export interface LinkAlertsToIncidentResult {
143
+ linkedAlertIds: Array<ObjectID>;
144
+ alreadyLinkedAlertIds: Array<ObjectID>;
145
+ failed: Array<{ alertId: ObjectID; message: string }>;
146
+ }
147
+
148
+ /*
149
+ * miscDataProps key on an IncidentAlert create: the link is one of the links
150
+ * written while an incident is being declared from alerts. The incident then
151
+ * gets one "Declared from N alerts" entry (see
152
+ * createDeclaredFromAlertsFeedItem) instead of an "Alert Linked" entry - and
153
+ * a Slack / Microsoft Teams post - per alert. Honoured for root callers only:
154
+ * miscDataProps is part of the public create API, and an API client must not
155
+ * be able to link an alert without the incident's audit entry.
156
+ */
157
+ export const INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY: string =
158
+ "declaredWithIncident";
159
+
160
+ // One alert, as the incident-side entries describe it.
161
+ export interface LinkedAlertMention {
162
+ // "Alert ALT-3" / "Alert #3".
163
+ label: string;
164
+ // The alert's page in the dashboard.
165
+ link: string;
166
+ title: string | undefined;
167
+ isPrivate: boolean;
168
+ }
169
+
170
+ /*
171
+ * "**[Alert #3](link)**: <title>", or "**[Alert #3](link)** (private alert)"
172
+ * for a private alert: its number and link are kept so the entry still says
173
+ * what happened, but its title is never written where people who cannot see
174
+ * the alert read it (the incident's feed and Slack / Microsoft Teams posts).
175
+ */
176
+ function describeLinkedRecord(data: {
177
+ label: string;
178
+ link: string;
179
+ title: string | undefined;
180
+ isPrivate: boolean;
181
+ privateNoun: string;
182
+ }): { subject: string; titleSuffix: string } {
183
+ const subject: string = `**[${data.label}](${data.link})**`;
184
+
185
+ if (data.isPrivate) {
186
+ return {
187
+ subject: `${subject} (private ${data.privateNoun})`,
188
+ titleSuffix: "",
189
+ };
190
+ }
191
+
192
+ return { subject: subject, titleSuffix: `: ${data.title || "No title"}` };
193
+ }
194
+
195
+ /*
196
+ * The one incident feed entry for an incident declared from alerts, listing
197
+ * the alerts in the order given. Private alerts are listed without their
198
+ * titles.
199
+ */
200
+ export function getDeclaredFromAlertsMarkdown(
201
+ alerts: Array<LinkedAlertMention>,
202
+ ): string {
203
+ const lines: Array<string> = alerts.map(
204
+ (alert: LinkedAlertMention): string => {
205
+ const described: { subject: string; titleSuffix: string } =
206
+ describeLinkedRecord({
207
+ label: alert.label,
208
+ link: alert.link,
209
+ title: alert.title,
210
+ isPrivate: alert.isPrivate,
211
+ privateNoun: "alert",
212
+ });
213
+
214
+ return `- ${described.subject}${described.titleSuffix}`;
215
+ },
216
+ );
217
+
218
+ const noun: string = alerts.length === 1 ? "alert" : "alerts";
219
+
220
+ return `🔗 Declared from ${alerts.length} ${noun}:\n\n${lines.join("\n")}`;
221
+ }
222
+
223
+ interface LinkedAlertSwitches {
224
+ acknowledge: boolean;
225
+ resolve: boolean;
226
+ }
227
+
228
+ /*
229
+ * Everything the per-alert decision needs, read once per incident state
230
+ * change rather than once per alert.
231
+ */
232
+ interface LinkedAlertStatePlan {
233
+ acknowledgedAlertState: AlertState | undefined;
234
+ resolvedAlertState: AlertState | undefined;
235
+ incidentReachedResolved: boolean;
236
+ resolvedIncidentStateOrder: number | undefined;
237
+ alertStateOrderById: Map<string, number>;
238
+ incidentStateOrderById: Map<string, number>;
239
+ }
240
+
241
+ // A link row as the delete hooks carry it from before to after the delete.
242
+ interface CarriedLink {
243
+ id: string;
244
+ incidentId: ObjectID;
245
+ alertId: ObjectID;
246
+ projectId: ObjectID;
247
+ }
248
+
249
+ function normalizeId(id: ObjectID | string): string {
250
+ return id.toString().trim().toLowerCase();
251
+ }
252
+
253
+ // Distinct ids, in order, with the missing ones left out.
254
+ function uniqueIds(ids: Array<ObjectID | undefined | null>): Array<ObjectID> {
255
+ const seen: Set<string> = new Set();
256
+ const result: Array<ObjectID> = [];
257
+
258
+ for (const id of ids) {
259
+ if (!id) {
260
+ continue;
261
+ }
262
+
263
+ const key: string = normalizeId(id);
264
+
265
+ if (!key || seen.has(key)) {
266
+ continue;
267
+ }
268
+
269
+ seen.add(key);
270
+ result.push(new ObjectID(key));
271
+ }
272
+
273
+ return result;
274
+ }
275
+
276
+ function formatNumber(
277
+ numberWithPrefix: string | undefined | null,
278
+ number: number | undefined | null,
279
+ ): string {
280
+ if (numberWithPrefix) {
281
+ return numberWithPrefix;
282
+ }
283
+
284
+ if (number !== undefined && number !== null) {
285
+ return `#${number}`;
286
+ }
287
+
288
+ return "";
289
+ }
290
+
291
+ function withNumber(label: string, number: string): string {
292
+ return number ? `${label} ${number}` : label;
293
+ }
294
+
295
+ const NOT_VISIBLE_ALERTS_MESSAGE: string =
296
+ "One or more of the selected alerts do not exist in this project, or you do not have access to them.";
297
+
298
+ export class Service extends DatabaseService<Model> {
299
+ public constructor() {
300
+ super(Model);
301
+ if (IsBillingEnabled) {
302
+ this.hardDeleteItemsOlderThanInDays("createdAt", 3 * 365); // 3 years
303
+ }
304
+ }
305
+
306
+ /*
307
+ * A link row reveals both of its ends, so it is only visible to a user who
308
+ * can see the private incident AND the private alert. The two filters write
309
+ * different keys (incidentId / alertId) and compose. Relation joins
310
+ * (`select: { alert: { title } }`) do not run AlertService.onBeforeFind,
311
+ * so these are the only thing keeping a private alert's title out of an
312
+ * incident's "Linked Alerts" list, and the other way round.
313
+ */
314
+ private applyPrivacyFilters<T>(
315
+ query: T,
316
+ props: DatabaseCommonInteractionProps,
317
+ ): T {
318
+ return applyAlertRelatedRecordPrivacyFilter(
319
+ applyIncidentRelatedRecordPrivacyFilter(query, props),
320
+ props,
321
+ );
322
+ }
323
+
324
+ @CaptureSpan()
325
+ protected override async onBeforeFind(
326
+ findBy: FindBy<Model>,
327
+ ): Promise<OnFind<Model>> {
328
+ findBy.query = this.applyPrivacyFilters(findBy.query, findBy.props);
329
+ return { findBy, carryForward: null };
330
+ }
331
+
332
+ /*
333
+ * A pair that is already linked answers with the same message however the
334
+ * duplicate is caught. @UniqueColumnsTogether catches it before the insert
335
+ * with INCIDENT_ALERT_ALREADY_LINKED_MESSAGE; when two requests race past
336
+ * that check, the unique index rejects the second insert, and the generic
337
+ * translation ("A Incident Alert with the same Incident Id, Alert Id,
338
+ * Project Id already exists...") would reach the dashboard, which counts a
339
+ * link as done only by this message. The exception stays tagged as a unique
340
+ * violation, so linkAlertsToIncident still counts it as already linked.
341
+ *
342
+ * IncidentAlert has no other unique index. A unique violation reported
343
+ * against another table (nothing on the create path writes one today) keeps
344
+ * the generic translation. Synchronous and `never`-returning, like the
345
+ * method it overrides.
346
+ */
347
+ protected override getException(error: Exception): never {
348
+ if (
349
+ PostgresErrorTranslator.isUniqueViolation(error) &&
350
+ this.isOwnTableOrUnknown(error)
351
+ ) {
352
+ throw PostgresErrorTranslator.createUniqueViolationException(
353
+ INCIDENT_ALERT_ALREADY_LINKED_MESSAGE,
354
+ );
355
+ }
356
+
357
+ return super.getException(error);
358
+ }
359
+
360
+ /*
361
+ * True when a Postgres error names this table, or names none (an exception
362
+ * that was already translated carries no driver details).
363
+ */
364
+ private isOwnTableOrUnknown(error: unknown): boolean {
365
+ const direct: { table?: unknown } = error as { table?: unknown };
366
+ const driverError: { table?: unknown } | undefined = (
367
+ error as { driverError?: { table?: unknown } }
368
+ ).driverError;
369
+
370
+ const table: unknown =
371
+ typeof direct.table === "string" ? direct.table : driverError?.table;
372
+
373
+ if (typeof table !== "string" || table.length === 0) {
374
+ return true;
375
+ }
376
+
377
+ return table === this.getModel().tableName;
378
+ }
379
+
380
+ @CaptureSpan()
381
+ public override async countBy(
382
+ countBy: CountBy<Model>,
383
+ ): Promise<PositiveNumber> {
384
+ countBy.query = this.applyPrivacyFilters(countBy.query, countBy.props);
385
+ return super.countBy(countBy);
386
+ }
387
+
388
+ @CaptureSpan()
389
+ protected override async onBeforeUpdate(
390
+ updateBy: UpdateBy<Model>,
391
+ ): Promise<OnUpdate<Model>> {
392
+ updateBy.query = this.applyPrivacyFilters(updateBy.query, updateBy.props);
393
+ return { updateBy, carryForward: null };
394
+ }
395
+
396
+ /*
397
+ * Both ends must exist in the link's project, and a user may only link what
398
+ * they can see. The foreign keys only require the rows to exist somewhere,
399
+ * and @CanAccessIfCanReadOn is not applied on create, so without this a
400
+ * member could link another project's alert, or a private incident they
401
+ * cannot open. The duplicate check is left to @UniqueColumnsTogether and the
402
+ * unique index, which are race free.
403
+ *
404
+ * This hook runs before DatabaseService checks the caller's create
405
+ * permission, so every refusal is worded so it reveals nothing about
406
+ * records the caller cannot see.
407
+ */
408
+ @CaptureSpan()
409
+ protected override async onBeforeCreate(
410
+ createBy: CreateBy<Model>,
411
+ ): Promise<OnCreate<Model>> {
412
+ const data: Record<string, unknown> = createBy.data as unknown as Record<
413
+ string,
414
+ unknown
415
+ >;
416
+
417
+ // A reference arrives as `incidentId` or as `incident: { _id }`.
418
+ const incidentId: ObjectID | null = RelationIdUtil.readConsistent(
419
+ data,
420
+ ["incidentId", "incident"],
421
+ "incident",
422
+ );
423
+
424
+ const alertId: ObjectID | null = RelationIdUtil.readConsistent(
425
+ data,
426
+ ["alertId", "alert"],
427
+ "alert",
428
+ );
429
+
430
+ if (!incidentId) {
431
+ throw new BadDataException(
432
+ "Please select the incident to link the alert to.",
433
+ );
434
+ }
435
+
436
+ if (!alertId) {
437
+ throw new BadDataException("Please select the alert to link.");
438
+ }
439
+
440
+ const projectId: ObjectID | null =
441
+ createBy.props.tenantId ||
442
+ RelationIdUtil.readConsistent(data, ["projectId", "project"], "project");
443
+
444
+ if (!projectId) {
445
+ throw new BadDataException(
446
+ "projectId is required to link an alert to an incident.",
447
+ );
448
+ }
449
+
450
+ createBy.data.projectId = projectId;
451
+ createBy.data.incidentId = incidentId;
452
+ createBy.data.alertId = alertId;
453
+
454
+ if (!createBy.props.isRoot) {
455
+ /*
456
+ * Read both ends as the caller, so privacy, label and owner scoping
457
+ * apply exactly as they do on the incident and alert pages. A caller
458
+ * without read access at all gets the same answer as one asking for
459
+ * a record that does not exist.
460
+ */
461
+ const incident: Incident | null = await this.findVisible(() => {
462
+ return IncidentService.findOneById({
463
+ id: incidentId,
464
+ select: { _id: true, projectId: true },
465
+ props: createBy.props,
466
+ });
467
+ });
468
+
469
+ if (
470
+ !incident ||
471
+ normalizeId(incident.projectId || "") !== normalizeId(projectId)
472
+ ) {
473
+ throw new BadDataException(
474
+ "The incident to link does not exist in this project, or you do not have access to it.",
475
+ );
476
+ }
477
+
478
+ const alert: Alert | null = await this.findVisible(() => {
479
+ return AlertService.findOneById({
480
+ id: alertId,
481
+ select: { _id: true, projectId: true },
482
+ props: createBy.props,
483
+ });
484
+ });
485
+
486
+ if (
487
+ !alert ||
488
+ normalizeId(alert.projectId || "") !== normalizeId(projectId)
489
+ ) {
490
+ throw new BadDataException(
491
+ "The alert to link does not exist in this project, or you do not have access to it.",
492
+ );
493
+ }
494
+
495
+ /*
496
+ * "Linked by" is whoever made the request. sanitizeCreateOrUpdate
497
+ * stamps it for a user; an API key has no user, and must not be able
498
+ * to name somebody else as the one who linked the alert.
499
+ */
500
+ if (createBy.props.userId) {
501
+ createBy.data.createdByUserId = createBy.props.userId;
502
+ } else {
503
+ delete createBy.data.createdByUserId;
504
+ }
505
+
506
+ delete createBy.data.createdByUser;
507
+ }
508
+
509
+ await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
510
+ projectId: projectId,
511
+ subject: "incident alert link",
512
+ references: [
513
+ {
514
+ modelName: "Incident",
515
+ id: incidentId,
516
+ service: IncidentService,
517
+ },
518
+ {
519
+ modelName: "Alert",
520
+ id: alertId,
521
+ service: AlertService,
522
+ },
523
+ ],
524
+ });
525
+
526
+ return { createBy, carryForward: null };
527
+ }
528
+
529
+ /*
530
+ * Runs a read made with the caller's props. A refusal from the permission
531
+ * layer (no read access to the table, a label the caller cannot see) is
532
+ * reported exactly like a record that does not exist, so the answer never
533
+ * reveals which it was. Anything else - a lapsed session, an unpaid
534
+ * project, the database being unavailable - is not about the record and is
535
+ * passed on as it is.
536
+ */
537
+ @CaptureSpan()
538
+ private async findVisible<T>(
539
+ read: () => Promise<T | null>,
540
+ ): Promise<T | null> {
541
+ try {
542
+ return await read();
543
+ } catch (error) {
544
+ if (
545
+ error instanceof NotAuthorizedException ||
546
+ error instanceof ForbiddenException ||
547
+ error instanceof NotFoundException ||
548
+ error instanceof BadDataException
549
+ ) {
550
+ logger.debug(
551
+ `IncidentAlertService: a record to link is not readable by the caller: ${error.message}`,
552
+ );
553
+ return null;
554
+ }
555
+
556
+ throw error;
557
+ }
558
+ }
559
+
560
+ @CaptureSpan()
561
+ public override async onCreateSuccess(
562
+ onCreate: OnCreate<Model>,
563
+ createdItem: Model,
564
+ ): Promise<Model> {
565
+ const projectId: ObjectID | undefined = createdItem.projectId;
566
+ const incidentId: ObjectID | undefined = createdItem.incidentId;
567
+ const alertId: ObjectID | undefined = createdItem.alertId;
568
+
569
+ if (!projectId || !incidentId || !alertId) {
570
+ return createdItem;
571
+ }
572
+
573
+ const actorUserId: ObjectID | undefined =
574
+ createdItem.createdByUserId || onCreate.createBy.props.userId;
575
+
576
+ /*
577
+ * A link written while its incident is being declared from alerts leaves
578
+ * the incident's side to that incident's single "Declared from N alerts"
579
+ * entry. Root only - see INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY.
580
+ */
581
+ const isDeclaredWithIncident: boolean =
582
+ onCreate.createBy.props.isRoot === true &&
583
+ onCreate.createBy.miscDataProps?.[
584
+ INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY
585
+ ] === true;
586
+
587
+ try {
588
+ await this.createLinkFeedItems({
589
+ link: {
590
+ id: createdItem.id?.toString() || "",
591
+ projectId: projectId,
592
+ incidentId: incidentId,
593
+ alertId: alertId,
594
+ },
595
+ isLinked: true,
596
+ actorUserId: actorUserId,
597
+ writeIncidentEntry: !isDeclaredWithIncident,
598
+ });
599
+ } catch (error) {
600
+ logger.error(
601
+ `IncidentAlertService.onCreateSuccess could not write the link feed items: ${error}`,
602
+ {
603
+ projectId: projectId.toString(),
604
+ incidentId: incidentId.toString(),
605
+ alertId: alertId.toString(),
606
+ } as LogAttributes,
607
+ );
608
+ }
609
+
610
+ /*
611
+ * Linking an alert to an incident that is already acknowledged or
612
+ * resolved brings the alert along, when the project asks for it.
613
+ * Fire-and-forget: it never fails, or slows down, the link.
614
+ */
615
+ this.syncAlertWithLinkedIncidentState({
616
+ projectId: projectId,
617
+ incidentId: incidentId,
618
+ alertId: alertId,
619
+ }).catch((error: Error) => {
620
+ logger.error(
621
+ `IncidentAlertService could not sync a newly linked alert with its incident: ${error}`,
622
+ {
623
+ projectId: projectId.toString(),
624
+ incidentId: incidentId.toString(),
625
+ alertId: alertId.toString(),
626
+ } as LogAttributes,
627
+ );
628
+ });
629
+
630
+ return createdItem;
631
+ }
632
+
633
+ /*
634
+ * Carries the rows about to be deleted to onDeleteSuccess, which reports
635
+ * only the ones that were actually deleted: the permission check that runs
636
+ * after this hook can still narrow the delete. The read is not capped at
637
+ * the delete's own limit because that limit applies to the narrowed query,
638
+ * whose rows need not be among the first rows of this one.
639
+ */
640
+ @CaptureSpan()
641
+ protected override async onBeforeDelete(
642
+ deleteBy: DeleteBy<Model>,
643
+ ): Promise<OnDelete<Model>> {
644
+ deleteBy.query = this.applyPrivacyFilters(deleteBy.query, deleteBy.props);
645
+
646
+ const carriedQuery: Query<Model> = { ...deleteBy.query };
647
+
648
+ if (deleteBy.props.tenantId && !carriedQuery.projectId) {
649
+ carriedQuery.projectId = deleteBy.props.tenantId;
650
+ }
651
+
652
+ const linksToDelete: Array<Model> = await this.findBy({
653
+ query: carriedQuery,
654
+ select: {
655
+ _id: true,
656
+ incidentId: true,
657
+ alertId: true,
658
+ projectId: true,
659
+ },
660
+ limit: LIMIT_PER_PROJECT,
661
+ skip: 0,
662
+ props: {
663
+ isRoot: true,
664
+ },
665
+ });
666
+
667
+ const carried: Array<CarriedLink> = [];
668
+
669
+ for (const link of linksToDelete) {
670
+ if (!link._id || !link.incidentId || !link.alertId || !link.projectId) {
671
+ continue;
672
+ }
673
+
674
+ carried.push({
675
+ id: link._id.toString(),
676
+ incidentId: link.incidentId,
677
+ alertId: link.alertId,
678
+ projectId: link.projectId,
679
+ });
680
+ }
681
+
682
+ return { deleteBy, carryForward: carried };
683
+ }
684
+
685
+ @CaptureSpan()
686
+ public override async onDeleteSuccess(
687
+ onDelete: OnDelete<Model>,
688
+ itemIdsBeforeDelete: Array<ObjectID>,
689
+ ): Promise<OnDelete<Model>> {
690
+ const carried: Array<CarriedLink> = Array.isArray(onDelete.carryForward)
691
+ ? (onDelete.carryForward as Array<CarriedLink>)
692
+ : [];
693
+
694
+ const deletedIds: Set<string> = new Set(
695
+ (itemIdsBeforeDelete || []).map((id: ObjectID) => {
696
+ return normalizeId(id);
697
+ }),
698
+ );
699
+
700
+ const actorUserId: ObjectID | undefined =
701
+ onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
702
+
703
+ for (const link of carried) {
704
+ if (!deletedIds.has(normalizeId(link.id))) {
705
+ continue;
706
+ }
707
+
708
+ try {
709
+ await this.createLinkFeedItems({
710
+ link: link,
711
+ isLinked: false,
712
+ actorUserId: actorUserId,
713
+ writeIncidentEntry: true,
714
+ });
715
+ } catch (error) {
716
+ logger.error(
717
+ `IncidentAlertService.onDeleteSuccess could not write the unlink feed items: ${error}`,
718
+ {
719
+ projectId: link.projectId.toString(),
720
+ incidentId: link.incidentId.toString(),
721
+ alertId: link.alertId.toString(),
722
+ } as LogAttributes,
723
+ );
724
+ }
725
+ }
726
+
727
+ return onDelete;
728
+ }
729
+
730
+ /*
731
+ * One entry on each side. Only the incident's entry is posted to Slack /
732
+ * Microsoft Teams: the incident's channels are where responders follow the
733
+ * incident, and posting the alert's entry as well would announce every link
734
+ * twice.
735
+ *
736
+ * Each entry is read by its own side's audience: the incident's feed and
737
+ * channels by whoever can see the incident, the alert's feed by whoever
738
+ * can see the alert. So a private end's title never goes into the other
739
+ * side's entry - not even when both ends are private, because two private
740
+ * records can have different owners. Its number and link are kept (opening
741
+ * the link is subject to the record's own privacy), which is what
742
+ * applyPrivacyFilters promises for the link rows themselves.
743
+ */
744
+ @CaptureSpan()
745
+ private async createLinkFeedItems(data: {
746
+ link: CarriedLink;
747
+ isLinked: boolean;
748
+ actorUserId: ObjectID | undefined;
749
+ // False for a link written while its incident is declared from alerts.
750
+ writeIncidentEntry: boolean;
751
+ }): Promise<void> {
752
+ const { link, isLinked, actorUserId } = data;
753
+
754
+ const incident: Incident | null = await IncidentService.findOneById({
755
+ id: link.incidentId,
756
+ select: {
757
+ incidentNumber: true,
758
+ incidentNumberWithPrefix: true,
759
+ title: true,
760
+ isPrivate: true,
761
+ },
762
+ props: {
763
+ isRoot: true,
764
+ },
765
+ });
766
+
767
+ const alert: Alert | null = await AlertService.findOneById({
768
+ id: link.alertId,
769
+ select: {
770
+ alertNumber: true,
771
+ alertNumberWithPrefix: true,
772
+ title: true,
773
+ isPrivate: true,
774
+ },
775
+ props: {
776
+ isRoot: true,
777
+ },
778
+ });
779
+
780
+ const incidentLabel: string = withNumber(
781
+ "Incident",
782
+ formatNumber(
783
+ incident?.incidentNumberWithPrefix,
784
+ incident?.incidentNumber,
785
+ ),
786
+ );
787
+ const alertLabel: string = withNumber(
788
+ "Alert",
789
+ formatNumber(alert?.alertNumberWithPrefix, alert?.alertNumber),
790
+ );
791
+
792
+ const incidentLink: string = (
793
+ await IncidentService.getIncidentLinkInDashboard(
794
+ link.projectId,
795
+ link.incidentId,
796
+ )
797
+ ).toString();
798
+ const alertLink: string = (
799
+ await AlertService.getAlertLinkInDashboard(link.projectId, link.alertId)
800
+ ).toString();
801
+
802
+ const alertMention: { subject: string; titleSuffix: string } =
803
+ describeLinkedRecord({
804
+ label: alertLabel,
805
+ link: alertLink,
806
+ title: alert?.title,
807
+ isPrivate: alert?.isPrivate === true,
808
+ privateNoun: "alert",
809
+ });
810
+
811
+ const incidentMention: { subject: string; titleSuffix: string } =
812
+ describeLinkedRecord({
813
+ label: incidentLabel,
814
+ link: incidentLink,
815
+ title: incident?.title,
816
+ isPrivate: incident?.isPrivate === true,
817
+ privateNoun: "incident",
818
+ });
819
+
820
+ const incidentSubject: string = `**[${incidentLabel}](${incidentLink})**`;
821
+
822
+ if (data.writeIncidentEntry) {
823
+ await IncidentFeedService.createIncidentFeedItem({
824
+ incidentId: link.incidentId,
825
+ projectId: link.projectId,
826
+ incidentFeedEventType: isLinked
827
+ ? IncidentFeedEventType.AlertLinked
828
+ : IncidentFeedEventType.AlertUnlinked,
829
+ displayColor: isLinked ? Yellow500 : Gray500,
830
+ feedInfoInMarkdown: isLinked
831
+ ? `🔗 Linked ${alertMention.subject} to ${incidentSubject}${alertMention.titleSuffix}`
832
+ : `Unlinked ${alertMention.subject} from ${incidentSubject}${alertMention.titleSuffix}`,
833
+ userId: actorUserId,
834
+ workspaceNotification: {
835
+ sendWorkspaceNotification: true,
836
+ notifyUserId: actorUserId,
837
+ },
838
+ });
839
+ }
840
+
841
+ await AlertFeedService.createAlertFeedItem({
842
+ alertId: link.alertId,
843
+ projectId: link.projectId,
844
+ alertFeedEventType: isLinked
845
+ ? AlertFeedEventType.LinkedToIncident
846
+ : AlertFeedEventType.UnlinkedFromIncident,
847
+ displayColor: isLinked ? Yellow500 : Gray500,
848
+ feedInfoInMarkdown: isLinked
849
+ ? `🔗 Linked to ${incidentMention.subject}${incidentMention.titleSuffix}`
850
+ : `Unlinked from ${incidentMention.subject}${incidentMention.titleSuffix}`,
851
+ userId: actorUserId,
852
+ });
853
+ }
854
+
855
+ /*
856
+ * The single incident feed entry for an incident declared from alerts,
857
+ * posted to its Slack / Microsoft Teams channels. The links themselves are
858
+ * written without incident-side entries (INCIDENT_ALERT_DECLARED_WITH_
859
+ * INCIDENT_KEY), so the incident's channels get one message instead of one
860
+ * per alert. IncidentService calls this from its create chain once the
861
+ * "Incident Created" entry is out, which is also when the incident's own
862
+ * channels exist. Nothing is written when none of the alerts can be found.
863
+ */
864
+ @CaptureSpan()
865
+ public async createDeclaredFromAlertsFeedItem(data: {
866
+ projectId: ObjectID;
867
+ incidentId: ObjectID;
868
+ alertIds: Array<ObjectID>;
869
+ actorUserId: ObjectID | undefined;
870
+ }): Promise<void> {
871
+ const markdown: string | null = await this.buildDeclaredFromAlertsMarkdown({
872
+ projectId: data.projectId,
873
+ alertIds: data.alertIds,
874
+ });
875
+
876
+ if (!markdown) {
877
+ return;
878
+ }
879
+
880
+ await IncidentFeedService.createIncidentFeedItem({
881
+ incidentId: data.incidentId,
882
+ projectId: data.projectId,
883
+ incidentFeedEventType: IncidentFeedEventType.AlertLinked,
884
+ displayColor: Yellow500,
885
+ feedInfoInMarkdown: markdown,
886
+ userId: data.actorUserId,
887
+ workspaceNotification: {
888
+ sendWorkspaceNotification: true,
889
+ notifyUserId: data.actorUserId,
890
+ },
891
+ });
892
+ }
893
+
894
+ /*
895
+ * The markdown for createDeclaredFromAlertsFeedItem: the project's alerts
896
+ * among `alertIds`, in that order, each with its number and dashboard
897
+ * link, and its title unless it is private. Read as root; null when none of
898
+ * the alerts exists (any more).
899
+ */
900
+ @CaptureSpan()
901
+ public async buildDeclaredFromAlertsMarkdown(data: {
902
+ projectId: ObjectID;
903
+ alertIds: Array<ObjectID>;
904
+ }): Promise<string | null> {
905
+ if (data.alertIds.length === 0) {
906
+ return null;
907
+ }
908
+
909
+ const alerts: Array<Alert> = await AlertService.findBy({
910
+ query: {
911
+ _id: QueryHelper.any(data.alertIds),
912
+ projectId: data.projectId,
913
+ },
914
+ select: {
915
+ _id: true,
916
+ alertNumber: true,
917
+ alertNumberWithPrefix: true,
918
+ title: true,
919
+ isPrivate: true,
920
+ },
921
+ limit: LIMIT_PER_PROJECT,
922
+ skip: 0,
923
+ props: {
924
+ isRoot: true,
925
+ },
926
+ });
927
+
928
+ const alertById: Map<string, Alert> = new Map();
929
+
930
+ for (const alert of alerts) {
931
+ if (alert._id) {
932
+ alertById.set(normalizeId(alert._id), alert);
933
+ }
934
+ }
935
+
936
+ const mentions: Array<LinkedAlertMention> = [];
937
+ const seen: Set<string> = new Set();
938
+
939
+ for (const alertId of data.alertIds) {
940
+ const key: string = normalizeId(alertId);
941
+ const alert: Alert | undefined = alertById.get(key);
942
+
943
+ if (!alert || seen.has(key)) {
944
+ continue;
945
+ }
946
+
947
+ seen.add(key);
948
+
949
+ mentions.push({
950
+ label: withNumber(
951
+ "Alert",
952
+ formatNumber(alert.alertNumberWithPrefix, alert.alertNumber),
953
+ ),
954
+ link: (
955
+ await AlertService.getAlertLinkInDashboard(
956
+ data.projectId,
957
+ new ObjectID(key),
958
+ )
959
+ ).toString(),
960
+ title: alert.title,
961
+ isPrivate: alert.isPrivate === true,
962
+ });
963
+ }
964
+
965
+ if (mentions.length === 0) {
966
+ return null;
967
+ }
968
+
969
+ return getDeclaredFromAlertsMarkdown(mentions);
970
+ }
971
+
972
+ /*
973
+ * Declaring a PRIVATE incident from alerts: the people who work those
974
+ * alerts become its owners too. A private incident is visible only to its
975
+ * owners (and project admins), and a private alert only to its owners, so
976
+ * without this the owners of the private alert an incident was declared
977
+ * from - the only non-admins who could see that alert - could not see the
978
+ * incident. The declaring user is already made an owner by
979
+ * DatabaseService.autoOwnerOnCreate. Owners are added as root, without
980
+ * notifying them (they were notified about their alerts), and owners the
981
+ * incident already has are skipped.
982
+ */
983
+ @CaptureSpan()
984
+ public async copyAlertOwnersToIncident(data: {
985
+ projectId: ObjectID;
986
+ incidentId: ObjectID;
987
+ alertIds: Array<ObjectID>;
988
+ }): Promise<{ userIds: Array<ObjectID>; teamIds: Array<ObjectID> }> {
989
+ if (data.alertIds.length === 0) {
990
+ return { userIds: [], teamIds: [] };
991
+ }
992
+
993
+ const ownerUsers: Array<AlertOwnerUser> =
994
+ await AlertOwnerUserService.findBy({
995
+ query: {
996
+ alertId: QueryHelper.any(data.alertIds),
997
+ projectId: data.projectId,
998
+ },
999
+ select: {
1000
+ userId: true,
1001
+ },
1002
+ limit: LIMIT_PER_PROJECT,
1003
+ skip: 0,
1004
+ props: {
1005
+ isRoot: true,
1006
+ },
1007
+ });
1008
+
1009
+ const ownerTeams: Array<AlertOwnerTeam> =
1010
+ await AlertOwnerTeamService.findBy({
1011
+ query: {
1012
+ alertId: QueryHelper.any(data.alertIds),
1013
+ projectId: data.projectId,
1014
+ },
1015
+ select: {
1016
+ teamId: true,
1017
+ },
1018
+ limit: LIMIT_PER_PROJECT,
1019
+ skip: 0,
1020
+ props: {
1021
+ isRoot: true,
1022
+ },
1023
+ });
1024
+
1025
+ const userIds: Array<ObjectID> = uniqueIds(
1026
+ ownerUsers.map((owner: AlertOwnerUser): ObjectID | undefined => {
1027
+ return owner.userId;
1028
+ }),
1029
+ );
1030
+
1031
+ const teamIds: Array<ObjectID> = uniqueIds(
1032
+ ownerTeams.map((owner: AlertOwnerTeam): ObjectID | undefined => {
1033
+ return owner.teamId;
1034
+ }),
1035
+ );
1036
+
1037
+ if (userIds.length === 0 && teamIds.length === 0) {
1038
+ return { userIds, teamIds };
1039
+ }
1040
+
1041
+ await IncidentService.addOwners(
1042
+ data.projectId,
1043
+ data.incidentId,
1044
+ userIds,
1045
+ teamIds,
1046
+ false,
1047
+ {
1048
+ isRoot: true,
1049
+ },
1050
+ );
1051
+
1052
+ return { userIds, teamIds };
1053
+ }
1054
+
1055
+ /*
1056
+ * Declaring an incident from alerts (miscDataProps.alertIdsToLink on an
1057
+ * Incident create). Runs in IncidentService.onBeforeCreate, BEFORE the
1058
+ * incident number is taken and before anything is written, so a bad id
1059
+ * neither burns an incident number nor leaves an incident behind with
1060
+ * half of its alerts. Returns the ids deduplicated and normalised, ready
1061
+ * for linkAlertsToIncident once the incident exists.
1062
+ */
1063
+ @CaptureSpan()
1064
+ public async validateAlertIdsForNewIncident(data: {
1065
+ projectId: ObjectID | undefined;
1066
+ alertIds: unknown;
1067
+ props: DatabaseCommonInteractionProps;
1068
+ }): Promise<Array<ObjectID>> {
1069
+ if (!Array.isArray(data.alertIds)) {
1070
+ throw new BadDataException(
1071
+ `${INCIDENT_ALERT_IDS_TO_LINK_KEY} must be an array of alert ids.`,
1072
+ );
1073
+ }
1074
+
1075
+ const alertIds: Array<ObjectID> = [];
1076
+ const seen: Set<string> = new Set();
1077
+
1078
+ for (const value of data.alertIds as Array<unknown>) {
1079
+ let id: string | null = null;
1080
+
1081
+ if (typeof value === "string") {
1082
+ id = value.trim();
1083
+ } else if (value instanceof ObjectID) {
1084
+ id = value.toString().trim();
1085
+ }
1086
+
1087
+ if (!id || !ObjectID.isValidUUID(id)) {
1088
+ throw new BadDataException(
1089
+ `${INCIDENT_ALERT_IDS_TO_LINK_KEY} must only contain alert ids.`,
1090
+ );
1091
+ }
1092
+
1093
+ const key: string = normalizeId(id);
1094
+
1095
+ if (seen.has(key)) {
1096
+ continue;
1097
+ }
1098
+
1099
+ seen.add(key);
1100
+ alertIds.push(new ObjectID(key));
1101
+ }
1102
+
1103
+ if (alertIds.length === 0) {
1104
+ throw new BadDataException(
1105
+ "Please select at least one alert to link to the incident.",
1106
+ );
1107
+ }
1108
+
1109
+ if (alertIds.length > MAX_ALERTS_PER_INCIDENT_LINK_ACTION) {
1110
+ throw new BadDataException(
1111
+ `You can link at most ${MAX_ALERTS_PER_INCIDENT_LINK_ACTION} alerts to an incident at a time. ${alertIds.length} were selected.`,
1112
+ );
1113
+ }
1114
+
1115
+ if (!data.projectId) {
1116
+ throw new BadDataException(
1117
+ "projectId is required to link alerts to an incident.",
1118
+ );
1119
+ }
1120
+
1121
+ const projectId: ObjectID = data.projectId;
1122
+
1123
+ if (!data.props.isRoot) {
1124
+ /*
1125
+ * The links are written as root once the incident exists (see
1126
+ * IncidentService.onCreateSuccess), so this is where the caller's own
1127
+ * right to link alerts is checked.
1128
+ */
1129
+ const probe: Model = new Model();
1130
+ probe.projectId = projectId;
1131
+ probe.incidentId = ObjectID.generate();
1132
+ probe.alertId = alertIds[0]!;
1133
+
1134
+ try {
1135
+ ModelPermission.checkCreatePermissions(Model, probe, data.props);
1136
+ } catch (error) {
1137
+ // A lapsed session or an unpaid project keeps its own answer.
1138
+ if (
1139
+ error instanceof NotAuthorizedException ||
1140
+ error instanceof BadDataException
1141
+ ) {
1142
+ throw new BadDataException(
1143
+ "You do not have permission to link alerts to incidents in this project.",
1144
+ );
1145
+ }
1146
+
1147
+ throw error;
1148
+ }
1149
+ }
1150
+
1151
+ /*
1152
+ * A user reads the alerts as themselves, so an alert they cannot open
1153
+ * (a private alert, a label they are not allowed to see) cannot be
1154
+ * pulled into their incident.
1155
+ */
1156
+ const alerts: Array<Alert> | null = await this.findVisible(() => {
1157
+ return AlertService.findBy({
1158
+ query: {
1159
+ _id: QueryHelper.any(alertIds),
1160
+ projectId: projectId,
1161
+ },
1162
+ select: {
1163
+ _id: true,
1164
+ },
1165
+ limit: LIMIT_PER_PROJECT,
1166
+ skip: 0,
1167
+ props: data.props.isRoot ? { isRoot: true } : data.props,
1168
+ });
1169
+ });
1170
+
1171
+ const foundIds: Set<string> = new Set(
1172
+ (alerts || []).map((alert: Alert) => {
1173
+ return normalizeId(alert._id || "");
1174
+ }),
1175
+ );
1176
+
1177
+ const missing: Array<ObjectID> = alertIds.filter((id: ObjectID) => {
1178
+ return !foundIds.has(normalizeId(id));
1179
+ });
1180
+
1181
+ if (missing.length > 0) {
1182
+ throw new BadDataException(NOT_VISIBLE_ALERTS_MESSAGE);
1183
+ }
1184
+
1185
+ return alertIds;
1186
+ }
1187
+
1188
+ /*
1189
+ * Links each alert to the incident, one at a time. An alert that is already
1190
+ * linked counts as done, not as a failure; any other failure is reported per
1191
+ * alert and never stops the rest.
1192
+ *
1193
+ * `declaredWithIncident` marks links written while the incident is being
1194
+ * declared from these alerts: they get no incident-side feed entry of their
1195
+ * own (see INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY, root callers only).
1196
+ */
1197
+ @CaptureSpan()
1198
+ public async linkAlertsToIncident(data: {
1199
+ projectId: ObjectID;
1200
+ incidentId: ObjectID;
1201
+ alertIds: Array<ObjectID>;
1202
+ createdByUserId?: ObjectID | undefined;
1203
+ declaredWithIncident?: boolean | undefined;
1204
+ props: DatabaseCommonInteractionProps;
1205
+ }): Promise<LinkAlertsToIncidentResult> {
1206
+ const result: LinkAlertsToIncidentResult = {
1207
+ linkedAlertIds: [],
1208
+ alreadyLinkedAlertIds: [],
1209
+ failed: [],
1210
+ };
1211
+
1212
+ for (const alertId of data.alertIds) {
1213
+ const link: Model = new Model();
1214
+ link.projectId = data.projectId;
1215
+ link.incidentId = data.incidentId;
1216
+ link.alertId = alertId;
1217
+
1218
+ if (data.createdByUserId) {
1219
+ link.createdByUserId = data.createdByUserId;
1220
+ }
1221
+
1222
+ try {
1223
+ await this.create({
1224
+ data: link,
1225
+ props: data.props,
1226
+ ...(data.declaredWithIncident
1227
+ ? {
1228
+ miscDataProps: {
1229
+ [INCIDENT_ALERT_DECLARED_WITH_INCIDENT_KEY]: true,
1230
+ },
1231
+ }
1232
+ : {}),
1233
+ });
1234
+ result.linkedAlertIds.push(alertId);
1235
+ } catch (error) {
1236
+ if (PostgresErrorTranslator.isUniqueViolation(error)) {
1237
+ result.alreadyLinkedAlertIds.push(alertId);
1238
+ continue;
1239
+ }
1240
+
1241
+ const message: string =
1242
+ error instanceof Error ? error.message : String(error);
1243
+
1244
+ result.failed.push({ alertId: alertId, message: message });
1245
+
1246
+ logger.error(
1247
+ `IncidentAlertService could not link alert ${alertId.toString()} to incident ${data.incidentId.toString()}: ${message}`,
1248
+ {
1249
+ projectId: data.projectId.toString(),
1250
+ incidentId: data.incidentId.toString(),
1251
+ alertId: alertId.toString(),
1252
+ } as LogAttributes,
1253
+ );
1254
+ }
1255
+ }
1256
+
1257
+ return result;
1258
+ }
1259
+
1260
+ /*
1261
+ * An incident changed state: bring its linked alerts along, when the
1262
+ * project has opted in. Called fire-and-forget from
1263
+ * IncidentStateTimelineService.onCreateSuccess for the incident's CURRENT
1264
+ * state only. Never throws; every failure is logged, and one alert failing
1265
+ * does not stop the others.
1266
+ */
1267
+ @CaptureSpan()
1268
+ public async cascadeIncidentStateToLinkedAlerts(data: {
1269
+ projectId: ObjectID;
1270
+ incidentId: ObjectID;
1271
+ incidentStateId: ObjectID;
1272
+ }): Promise<void> {
1273
+ try {
1274
+ const switches: LinkedAlertSwitches | null =
1275
+ await this.getLinkedAlertSwitches(data.projectId);
1276
+
1277
+ if (!switches) {
1278
+ return;
1279
+ }
1280
+
1281
+ const plan: LinkedAlertStatePlan | null =
1282
+ await this.buildLinkedAlertStatePlan({
1283
+ projectId: data.projectId,
1284
+ incidentStateId: data.incidentStateId,
1285
+ switches: switches,
1286
+ });
1287
+
1288
+ if (!plan) {
1289
+ return;
1290
+ }
1291
+
1292
+ const links: Array<Model> = await this.findBy({
1293
+ query: {
1294
+ incidentId: data.incidentId,
1295
+ projectId: data.projectId,
1296
+ },
1297
+ select: {
1298
+ alertId: true,
1299
+ },
1300
+ limit: LIMIT_PER_PROJECT,
1301
+ skip: 0,
1302
+ props: {
1303
+ isRoot: true,
1304
+ },
1305
+ });
1306
+
1307
+ const alertIds: Array<ObjectID> = [];
1308
+
1309
+ for (const link of links) {
1310
+ if (link.alertId) {
1311
+ alertIds.push(link.alertId);
1312
+ }
1313
+ }
1314
+
1315
+ if (alertIds.length === 0) {
1316
+ return;
1317
+ }
1318
+
1319
+ const incident: Incident | null = await IncidentService.findOneById({
1320
+ id: data.incidentId,
1321
+ select: {
1322
+ incidentNumber: true,
1323
+ incidentNumberWithPrefix: true,
1324
+ },
1325
+ props: {
1326
+ isRoot: true,
1327
+ },
1328
+ });
1329
+
1330
+ if (!incident) {
1331
+ return;
1332
+ }
1333
+
1334
+ await this.applyLinkedAlertStatePlan({
1335
+ plan: plan,
1336
+ projectId: data.projectId,
1337
+ incidentId: data.incidentId,
1338
+ incidentNumber: formatNumber(
1339
+ incident.incidentNumberWithPrefix,
1340
+ incident.incidentNumber,
1341
+ ),
1342
+ alertIds: alertIds,
1343
+ });
1344
+ } catch (error) {
1345
+ logger.error(
1346
+ `IncidentAlertService could not carry an incident state change over to its linked alerts: ${error}`,
1347
+ {
1348
+ projectId: data.projectId.toString(),
1349
+ incidentId: data.incidentId.toString(),
1350
+ } as LogAttributes,
1351
+ );
1352
+ }
1353
+ }
1354
+
1355
+ /*
1356
+ * The link-time half: an alert was just linked to an incident that may
1357
+ * already be acknowledged or resolved. Same rules as the cascade, applied to
1358
+ * the one alert. A newly declared incident is in its created state, so
1359
+ * this is a no-op for "declare incident from alerts". Never throws.
1360
+ */
1361
+ @CaptureSpan()
1362
+ public async syncAlertWithLinkedIncidentState(data: {
1363
+ projectId: ObjectID;
1364
+ incidentId: ObjectID;
1365
+ alertId: ObjectID;
1366
+ }): Promise<void> {
1367
+ try {
1368
+ const switches: LinkedAlertSwitches | null =
1369
+ await this.getLinkedAlertSwitches(data.projectId);
1370
+
1371
+ if (!switches) {
1372
+ return;
1373
+ }
1374
+
1375
+ const incident: Incident | null = await IncidentService.findOneById({
1376
+ id: data.incidentId,
1377
+ select: {
1378
+ currentIncidentStateId: true,
1379
+ incidentNumber: true,
1380
+ incidentNumberWithPrefix: true,
1381
+ },
1382
+ props: {
1383
+ isRoot: true,
1384
+ },
1385
+ });
1386
+
1387
+ if (!incident || !incident.currentIncidentStateId) {
1388
+ return;
1389
+ }
1390
+
1391
+ const plan: LinkedAlertStatePlan | null =
1392
+ await this.buildLinkedAlertStatePlan({
1393
+ projectId: data.projectId,
1394
+ incidentStateId: incident.currentIncidentStateId,
1395
+ switches: switches,
1396
+ });
1397
+
1398
+ if (!plan) {
1399
+ return;
1400
+ }
1401
+
1402
+ await this.applyLinkedAlertStatePlan({
1403
+ plan: plan,
1404
+ projectId: data.projectId,
1405
+ incidentId: data.incidentId,
1406
+ incidentNumber: formatNumber(
1407
+ incident.incidentNumberWithPrefix,
1408
+ incident.incidentNumber,
1409
+ ),
1410
+ alertIds: [data.alertId],
1411
+ });
1412
+ } catch (error) {
1413
+ logger.error(
1414
+ `IncidentAlertService could not sync a linked alert with its incident's state: ${error}`,
1415
+ {
1416
+ projectId: data.projectId.toString(),
1417
+ incidentId: data.incidentId.toString(),
1418
+ alertId: data.alertId.toString(),
1419
+ } as LogAttributes,
1420
+ );
1421
+ }
1422
+ }
1423
+
1424
+ // Null when both project switches are off (the default).
1425
+ @CaptureSpan()
1426
+ private async getLinkedAlertSwitches(
1427
+ projectId: ObjectID,
1428
+ ): Promise<LinkedAlertSwitches | null> {
1429
+ const project: Project | null = await ProjectService.findOneById({
1430
+ id: projectId,
1431
+ select: {
1432
+ acknowledgeLinkedAlertsWhenIncidentAcknowledged: true,
1433
+ resolveLinkedAlertsWhenIncidentResolved: true,
1434
+ },
1435
+ props: {
1436
+ isRoot: true,
1437
+ },
1438
+ });
1439
+
1440
+ const switches: LinkedAlertSwitches = {
1441
+ acknowledge:
1442
+ project?.acknowledgeLinkedAlertsWhenIncidentAcknowledged === true,
1443
+ resolve: project?.resolveLinkedAlertsWhenIncidentResolved === true,
1444
+ };
1445
+
1446
+ if (!switches.acknowledge && !switches.resolve) {
1447
+ return null;
1448
+ }
1449
+
1450
+ return switches;
1451
+ }
1452
+
1453
+ // Null when the incident's state calls for nothing.
1454
+ @CaptureSpan()
1455
+ private async buildLinkedAlertStatePlan(data: {
1456
+ projectId: ObjectID;
1457
+ incidentStateId: ObjectID;
1458
+ switches: LinkedAlertSwitches;
1459
+ }): Promise<LinkedAlertStatePlan | null> {
1460
+ const logAttributes: LogAttributes = {
1461
+ projectId: data.projectId.toString(),
1462
+ } as LogAttributes;
1463
+
1464
+ const incidentStates: Array<IncidentState> =
1465
+ await IncidentStateService.getAllIncidentStates({
1466
+ projectId: data.projectId,
1467
+ props: {
1468
+ isRoot: true,
1469
+ },
1470
+ });
1471
+
1472
+ const incidentStateOrderById: Map<string, number> = new Map();
1473
+
1474
+ for (const state of incidentStates) {
1475
+ if (state._id && state.order !== undefined && state.order !== null) {
1476
+ incidentStateOrderById.set(normalizeId(state._id), state.order);
1477
+ }
1478
+ }
1479
+
1480
+ const incidentStateOrder: number | undefined = incidentStateOrderById.get(
1481
+ normalizeId(data.incidentStateId),
1482
+ );
1483
+
1484
+ if (incidentStateOrder === undefined) {
1485
+ logger.error(
1486
+ `IncidentAlertService: incident state ${data.incidentStateId.toString()} was not found in its project, linked alerts were left as they are.`,
1487
+ logAttributes,
1488
+ );
1489
+ return null;
1490
+ }
1491
+
1492
+ const acknowledgedIncidentState: IncidentState | undefined =
1493
+ incidentStates.find((state: IncidentState) => {
1494
+ return state.isAcknowledgedState;
1495
+ });
1496
+ const resolvedIncidentState: IncidentState | undefined =
1497
+ incidentStates.find((state: IncidentState) => {
1498
+ return state.isResolvedState;
1499
+ });
1500
+
1501
+ const targets: LinkedAlertStateTargets = getLinkedAlertStateTargets({
1502
+ incidentStateOrder: incidentStateOrder,
1503
+ acknowledgedIncidentStateOrder: acknowledgedIncidentState?.order,
1504
+ resolvedIncidentStateOrder: resolvedIncidentState?.order,
1505
+ acknowledgeSwitch: data.switches.acknowledge,
1506
+ resolveSwitch: data.switches.resolve,
1507
+ });
1508
+
1509
+ if (!targets.acknowledge && !targets.resolve) {
1510
+ return null;
1511
+ }
1512
+
1513
+ const alertStates: Array<AlertState> =
1514
+ await AlertStateService.getAllAlertStates({
1515
+ projectId: data.projectId,
1516
+ props: {
1517
+ isRoot: true,
1518
+ },
1519
+ });
1520
+
1521
+ const alertStateOrderById: Map<string, number> = new Map();
1522
+
1523
+ for (const state of alertStates) {
1524
+ if (state._id && state.order !== undefined && state.order !== null) {
1525
+ alertStateOrderById.set(normalizeId(state._id), state.order);
1526
+ }
1527
+ }
1528
+
1529
+ let acknowledgedAlertState: AlertState | undefined = undefined;
1530
+ let resolvedAlertState: AlertState | undefined = undefined;
1531
+
1532
+ if (targets.acknowledge) {
1533
+ acknowledgedAlertState = alertStates.find((state: AlertState) => {
1534
+ return state.isAcknowledgedState;
1535
+ });
1536
+
1537
+ if (!acknowledgedAlertState) {
1538
+ logger.error(
1539
+ "IncidentAlertService: the project has no Acknowledged alert state, so linked alerts could not be acknowledged.",
1540
+ logAttributes,
1541
+ );
1542
+ }
1543
+ }
1544
+
1545
+ if (targets.resolve) {
1546
+ resolvedAlertState = alertStates.find((state: AlertState) => {
1547
+ return state.isResolvedState;
1548
+ });
1549
+
1550
+ if (!resolvedAlertState) {
1551
+ logger.error(
1552
+ "IncidentAlertService: the project has no Resolved alert state, so linked alerts could not be resolved.",
1553
+ logAttributes,
1554
+ );
1555
+ }
1556
+ }
1557
+
1558
+ if (!acknowledgedAlertState && !resolvedAlertState) {
1559
+ return null;
1560
+ }
1561
+
1562
+ return {
1563
+ acknowledgedAlertState: acknowledgedAlertState,
1564
+ resolvedAlertState: resolvedAlertState,
1565
+ incidentReachedResolved: targets.incidentReachedResolved,
1566
+ resolvedIncidentStateOrder: resolvedIncidentState?.order,
1567
+ alertStateOrderById: alertStateOrderById,
1568
+ incidentStateOrderById: incidentStateOrderById,
1569
+ };
1570
+ }
1571
+
1572
+ @CaptureSpan()
1573
+ private async applyLinkedAlertStatePlan(data: {
1574
+ plan: LinkedAlertStatePlan;
1575
+ projectId: ObjectID;
1576
+ incidentId: ObjectID;
1577
+ incidentNumber: string;
1578
+ alertIds: Array<ObjectID>;
1579
+ }): Promise<void> {
1580
+ const { plan, projectId, incidentId } = data;
1581
+
1582
+ const alerts: Array<Alert> = await AlertService.findBy({
1583
+ query: {
1584
+ _id: QueryHelper.any(data.alertIds),
1585
+ projectId: projectId,
1586
+ },
1587
+ select: {
1588
+ _id: true,
1589
+ currentAlertStateId: true,
1590
+ },
1591
+ limit: LIMIT_PER_PROJECT,
1592
+ skip: 0,
1593
+ props: {
1594
+ isRoot: true,
1595
+ },
1596
+ });
1597
+
1598
+ const blockedFromResolve: Set<string> = plan.resolvedAlertState
1599
+ ? await this.getAlertsHeldOpenByAnotherIncident({
1600
+ plan: plan,
1601
+ projectId: projectId,
1602
+ incidentId: incidentId,
1603
+ alerts: alerts,
1604
+ })
1605
+ : new Set();
1606
+
1607
+ const incidentLabel: string = withNumber("Incident", data.incidentNumber);
1608
+
1609
+ for (const alert of alerts) {
1610
+ const alertId: string = alert._id?.toString() || "";
1611
+
1612
+ const alertStateOrder: number | undefined = alert.currentAlertStateId
1613
+ ? plan.alertStateOrderById.get(normalizeId(alert.currentAlertStateId))
1614
+ : undefined;
1615
+
1616
+ if (!alertId || alertStateOrder === undefined) {
1617
+ logger.error(
1618
+ `IncidentAlertService: the current state of linked alert ${alertId} is unknown, so it was left as it is.`,
1619
+ {
1620
+ projectId: projectId.toString(),
1621
+ incidentId: incidentId.toString(),
1622
+ alertId: alertId,
1623
+ } as LogAttributes,
1624
+ );
1625
+ continue;
1626
+ }
1627
+
1628
+ const target: AlertState | null = chooseLinkedAlertTargetState({
1629
+ alertStateOrder: alertStateOrder,
1630
+ acknowledgedAlertState: plan.acknowledgedAlertState,
1631
+ resolvedAlertState: plan.resolvedAlertState,
1632
+ isBlockedFromResolve: blockedFromResolve.has(normalizeId(alertId)),
1633
+ });
1634
+
1635
+ if (!target || !target._id) {
1636
+ continue;
1637
+ }
1638
+
1639
+ const isResolving: boolean = target === plan.resolvedAlertState;
1640
+
1641
+ const rootCause: string = isResolving
1642
+ ? `Resolved because linked ${incidentLabel} was resolved.`
1643
+ : `Acknowledged because linked ${incidentLabel} was ${
1644
+ plan.incidentReachedResolved ? "resolved" : "acknowledged"
1645
+ }.`;
1646
+
1647
+ try {
1648
+ await AlertService.changeAlertState({
1649
+ projectId: projectId,
1650
+ alertId: new ObjectID(alertId),
1651
+ alertStateId: new ObjectID(target._id.toString()),
1652
+ notifyOwners: false,
1653
+ rootCause: rootCause,
1654
+ stateChangeLog: undefined,
1655
+ props: {
1656
+ isRoot: true,
1657
+ },
1658
+ });
1659
+ } catch (error) {
1660
+ logger.error(
1661
+ `IncidentAlertService could not change the state of linked alert ${alertId}: ${error}`,
1662
+ {
1663
+ projectId: projectId.toString(),
1664
+ incidentId: incidentId.toString(),
1665
+ alertId: alertId,
1666
+ } as LogAttributes,
1667
+ );
1668
+ }
1669
+ }
1670
+ }
1671
+
1672
+ /*
1673
+ * An alert linked to several incidents is resolved only once none of them
1674
+ * is still open: resolving one incident must not close an alert another
1675
+ * open incident is still tracking. Only alerts that would otherwise be
1676
+ * resolved are looked up.
1677
+ */
1678
+ @CaptureSpan()
1679
+ private async getAlertsHeldOpenByAnotherIncident(data: {
1680
+ plan: LinkedAlertStatePlan;
1681
+ projectId: ObjectID;
1682
+ incidentId: ObjectID;
1683
+ alerts: Array<Alert>;
1684
+ }): Promise<Set<string>> {
1685
+ const held: Set<string> = new Set();
1686
+ const resolvedAlertStateOrder: number | undefined =
1687
+ data.plan.resolvedAlertState?.order;
1688
+
1689
+ if (resolvedAlertStateOrder === undefined) {
1690
+ return held;
1691
+ }
1692
+
1693
+ const candidateIds: Array<string> = [];
1694
+
1695
+ for (const alert of data.alerts) {
1696
+ const order: number | undefined = alert.currentAlertStateId
1697
+ ? data.plan.alertStateOrderById.get(
1698
+ normalizeId(alert.currentAlertStateId),
1699
+ )
1700
+ : undefined;
1701
+
1702
+ if (alert._id && order !== undefined && order < resolvedAlertStateOrder) {
1703
+ candidateIds.push(normalizeId(alert._id));
1704
+ }
1705
+ }
1706
+
1707
+ if (candidateIds.length === 0) {
1708
+ return held;
1709
+ }
1710
+
1711
+ const otherLinks: Array<Model> = await this.findBy({
1712
+ query: {
1713
+ alertId: QueryHelper.any(candidateIds),
1714
+ projectId: data.projectId,
1715
+ },
1716
+ select: {
1717
+ alertId: true,
1718
+ incidentId: true,
1719
+ },
1720
+ limit: LIMIT_PER_PROJECT,
1721
+ skip: 0,
1722
+ props: {
1723
+ isRoot: true,
1724
+ },
1725
+ });
1726
+
1727
+ const thisIncidentId: string = normalizeId(data.incidentId);
1728
+ const otherIncidentIdsByAlert: Map<string, Array<string>> = new Map();
1729
+ const otherIncidentIds: Set<string> = new Set();
1730
+
1731
+ for (const link of otherLinks) {
1732
+ if (!link.alertId || !link.incidentId) {
1733
+ continue;
1734
+ }
1735
+
1736
+ const incidentId: string = normalizeId(link.incidentId);
1737
+
1738
+ if (incidentId === thisIncidentId) {
1739
+ continue;
1740
+ }
1741
+
1742
+ const alertId: string = normalizeId(link.alertId);
1743
+ const incidentIds: Array<string> =
1744
+ otherIncidentIdsByAlert.get(alertId) || [];
1745
+ incidentIds.push(incidentId);
1746
+ otherIncidentIdsByAlert.set(alertId, incidentIds);
1747
+ otherIncidentIds.add(incidentId);
1748
+ }
1749
+
1750
+ if (otherIncidentIds.size === 0) {
1751
+ return held;
1752
+ }
1753
+
1754
+ const otherIncidents: Array<Incident> = await IncidentService.findBy({
1755
+ query: {
1756
+ _id: QueryHelper.any(Array.from(otherIncidentIds)),
1757
+ projectId: data.projectId,
1758
+ },
1759
+ select: {
1760
+ _id: true,
1761
+ currentIncidentStateId: true,
1762
+ },
1763
+ limit: LIMIT_PER_PROJECT,
1764
+ skip: 0,
1765
+ props: {
1766
+ isRoot: true,
1767
+ },
1768
+ });
1769
+
1770
+ const openIncidentIds: Set<string> = new Set();
1771
+
1772
+ for (const incident of otherIncidents) {
1773
+ if (!incident._id) {
1774
+ continue;
1775
+ }
1776
+
1777
+ const order: number | undefined = incident.currentIncidentStateId
1778
+ ? data.plan.incidentStateOrderById.get(
1779
+ normalizeId(incident.currentIncidentStateId),
1780
+ )
1781
+ : undefined;
1782
+
1783
+ /*
1784
+ * An incident whose state cannot be placed is treated as open: leaving
1785
+ * an alert unresolved is recoverable, resolving it too early is not.
1786
+ */
1787
+ const isResolved: boolean =
1788
+ order !== undefined &&
1789
+ data.plan.resolvedIncidentStateOrder !== undefined &&
1790
+ order >= data.plan.resolvedIncidentStateOrder;
1791
+
1792
+ if (!isResolved) {
1793
+ openIncidentIds.add(normalizeId(incident._id));
1794
+ }
1795
+ }
1796
+
1797
+ for (const [alertId, incidentIds] of otherIncidentIdsByAlert) {
1798
+ if (
1799
+ incidentIds.some((incidentId: string) => {
1800
+ return openIncidentIds.has(incidentId);
1801
+ })
1802
+ ) {
1803
+ held.add(alertId);
1804
+ }
1805
+ }
1806
+
1807
+ return held;
1808
+ }
1809
+ }
1810
+
1811
+ export default new Service();