@oneuptime/common 14.0.1 → 14.0.2

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 (1090) hide show
  1. package/Models/DatabaseModels/AlertEpisodeMember.ts +8 -1
  2. package/Models/DatabaseModels/AutoRemediationSuggestion.ts +63 -0
  3. package/Models/DatabaseModels/IncidentEpisodeMember.ts +8 -1
  4. package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +9 -2
  5. package/Models/DatabaseModels/IncidentPublicNote.ts +9 -2
  6. package/Models/DatabaseModels/KubernetesCluster.ts +429 -0
  7. package/Models/DatabaseModels/Monitor.ts +48 -0
  8. package/Models/DatabaseModels/Runner.ts +5 -4
  9. package/Models/DatabaseModels/RunnerJob.ts +66 -0
  10. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +10 -2
  11. package/Models/DatabaseModels/WorkflowVariable.ts +479 -2
  12. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +79 -25
  13. package/Server/API/AIInvestigationAPI.ts +341 -0
  14. package/Server/API/AutoRemediationAPI.ts +184 -2
  15. package/Server/API/CommonAPI.ts +70 -0
  16. package/Server/API/KubernetesClusterAiAccessAPI.ts +793 -0
  17. package/Server/API/MicrosoftTeamsAPI.ts +770 -315
  18. package/Server/API/MonitorAPI.ts +140 -0
  19. package/Server/API/OnCallScheduleTimelineAPI.ts +5 -21
  20. package/Server/API/SlackAPI.ts +447 -99
  21. package/Server/API/StatusPageAPI.ts +146 -26
  22. package/Server/API/TelemetryAPI.ts +216 -5
  23. package/Server/API/UserTwoFactorBackupCodeAPI.ts +1 -0
  24. package/Server/API/WorkflowVariableAPI.ts +156 -0
  25. package/Server/Infrastructure/GlobalCache.ts +35 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1794300000000-AddOAuth2WorkflowVariables.ts +97 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1794400000000-AddKubernetesClusterAiAccess.ts +129 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1794500000000-AddIncomingEmailCustomAddressToMonitor.ts +25 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1794600000000-AddAuthTokenExpiresAtToWorkspaceProjectAuthToken.ts +20 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1794700000000-RemoveAppAccessTokenFromWorkspaceProjectAuthTokenMiscData.ts +38 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  32. package/Server/Middleware/MasterAdminAuthorization.ts +28 -0
  33. package/Server/Middleware/TelemetryIngest.ts +47 -2
  34. package/Server/Middleware/UserAuthorization.ts +56 -2
  35. package/Server/Services/AIAgentService.ts +1 -0
  36. package/Server/Services/AccessTokenService.ts +121 -48
  37. package/Server/Services/AlertEpisodeMemberService.ts +9 -0
  38. package/Server/Services/AlertEpisodeService.ts +14 -1
  39. package/Server/Services/AlertService.ts +134 -22
  40. package/Server/Services/AutoRemediationRuleEngineService.ts +968 -39
  41. package/Server/Services/AutoRemediationRuleService.ts +118 -0
  42. package/Server/Services/BillingService.ts +1 -0
  43. package/Server/Services/InboundEmail/Providers/SendGridInboundProvider.ts +16 -22
  44. package/Server/Services/IncidentEpisodeMemberService.ts +9 -0
  45. package/Server/Services/IncidentEpisodePublicNoteService.ts +66 -0
  46. package/Server/Services/IncidentEpisodeRoleMemberService.ts +27 -0
  47. package/Server/Services/IncidentEpisodeService.ts +14 -1
  48. package/Server/Services/IncidentGroupingEngineService.ts +11 -0
  49. package/Server/Services/IncidentMemberService.ts +21 -0
  50. package/Server/Services/IncidentPublicNoteService.ts +63 -0
  51. package/Server/Services/IncidentService.ts +120 -20
  52. package/Server/Services/IncidentStateTimelineService.ts +15 -0
  53. package/Server/Services/IncidentTemplateService.ts +83 -3
  54. package/Server/Services/KubernetesClusterAiAccessService.ts +1943 -0
  55. package/Server/Services/KubernetesClusterService.ts +1570 -1
  56. package/Server/Services/LogAggregationService.ts +14 -6
  57. package/Server/Services/MonitorService.ts +651 -52
  58. package/Server/Services/MonitorStatusTimelineService.ts +639 -2
  59. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +2 -0
  60. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +2 -0
  61. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +2 -0
  62. package/Server/Services/OnCallDutyPolicyScheduleService.ts +3 -0
  63. package/Server/Services/OnCallNotificationAlertingService.ts +36 -12
  64. package/Server/Services/OnCallSetupReminderService.ts +1 -0
  65. package/Server/Services/ProbeService.ts +7 -1
  66. package/Server/Services/ProjectService.ts +11 -1
  67. package/Server/Services/RunbookCredentialService.ts +26 -1
  68. package/Server/Services/RunbookSecretService.ts +36 -0
  69. package/Server/Services/RunnerJobService.ts +941 -23
  70. package/Server/Services/RunnerService.ts +439 -6
  71. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +66 -0
  72. package/Server/Services/ScheduledMaintenanceService.ts +124 -19
  73. package/Server/Services/ScheduledMaintenanceTemplateService.ts +82 -3
  74. package/Server/Services/ServiceLevelObjectiveService.ts +14 -1
  75. package/Server/Services/StatusPagePrivateUserService.ts +1 -0
  76. package/Server/Services/StatusPageService.ts +301 -74
  77. package/Server/Services/StatusPageSubscriberService.ts +4 -0
  78. package/Server/Services/TeamMemberService.ts +309 -7
  79. package/Server/Services/TraceAggregationService.ts +10 -6
  80. package/Server/Services/UserEmailService.ts +1 -0
  81. package/Server/Services/UserNotificationMethodAdminService.ts +1 -0
  82. package/Server/Services/UserNotificationRuleAdminService.ts +1 -0
  83. package/Server/Services/UserNotificationRuleService.ts +4 -0
  84. package/Server/Services/UserService.ts +122 -1
  85. package/Server/Services/WorkflowVariableService.ts +593 -8
  86. package/Server/Services/WorkspaceNotificationRuleService.ts +588 -8
  87. package/Server/Services/WorkspaceProjectAuthTokenService.ts +170 -1
  88. package/Server/Types/Database/QueryHelper.ts +22 -0
  89. package/Server/Types/Markdown.ts +502 -27
  90. package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +182 -0
  91. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +525 -0
  92. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +854 -0
  93. package/Server/Utils/AI/CodeFix/CodeFixAgentAuth.ts +22 -2
  94. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1916 -307
  95. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +1601 -74
  96. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +139 -7
  97. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +58 -1
  98. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +54 -1
  99. package/Server/Utils/AI/Toolbox/AIActionTools.ts +14 -6
  100. package/Server/Utils/AI/Toolbox/ResourceTools.ts +4 -2
  101. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +1341 -150
  102. package/Server/Utils/AutoRemediation/RemediationVerifier.ts +375 -4
  103. package/Server/Utils/Database/AffectedResourceRelations.ts +127 -0
  104. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +240 -1
  105. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +1 -0
  106. package/Server/Utils/Monitor/MonitorAlert.ts +83 -9
  107. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +5 -1
  108. package/Server/Utils/Monitor/MonitorIncident.ts +104 -9
  109. package/Server/Utils/Monitor/MonitorPayloadRedaction.ts +124 -7
  110. package/Server/Utils/Monitor/ProbeMonitorsNotification.ts +407 -0
  111. package/Server/Utils/OnCall/OnCallShiftReminderRunner.ts +1 -0
  112. package/Server/Utils/PushNotificationUtil.ts +45 -0
  113. package/Server/Utils/Rules/OwnerRuleAssignment.ts +40 -3
  114. package/Server/Utils/Runbook/RunbookExecutePermission.ts +56 -6
  115. package/Server/Utils/SessionReplay/SessionReplayReadService.ts +223 -33
  116. package/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.ts +559 -0
  117. package/Server/Utils/StartServer.ts +4 -3
  118. package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +528 -0
  119. package/Server/Utils/TwoFactorBackupCodeNotification.ts +1 -0
  120. package/Server/Utils/UserPermission/UserPermission.ts +16 -0
  121. package/Server/Utils/Workflow/OAuth2TokenClient.ts +704 -0
  122. package/Server/Utils/Workflow/WorkflowVariableOAuthToken.ts +318 -0
  123. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +47 -7
  124. package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +57 -16
  125. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +193 -214
  126. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +57 -13
  127. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.ts +54 -17
  128. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +179 -161
  129. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +281 -167
  130. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsServiceUrl.ts +114 -0
  131. package/Server/Utils/Workspace/MicrosoftTeams/ReactionNoteSync.ts +895 -0
  132. package/Server/Utils/Workspace/Slack/Actions/ActionTypes.ts +7 -9
  133. package/Server/Utils/Workspace/Slack/Actions/Alert.ts +96 -227
  134. package/Server/Utils/Workspace/Slack/Actions/AlertEpisode.ts +93 -214
  135. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +30 -3
  136. package/Server/Utils/Workspace/Slack/Actions/Authorization.ts +99 -0
  137. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +117 -283
  138. package/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.ts +101 -196
  139. package/Server/Utils/Workspace/Slack/Actions/ReactionNote.ts +329 -0
  140. package/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.ts +111 -287
  141. package/Server/Utils/Workspace/Slack/Slack.ts +86 -17
  142. package/Server/Utils/Workspace/Slack/app-manifest.json +2 -0
  143. package/Server/Utils/Workspace/Workspace.ts +171 -54
  144. package/Server/Utils/Workspace/WorkspaceActionAuthorization.ts +252 -0
  145. package/Server/Utils/Workspace/WorkspaceBase.ts +39 -0
  146. package/Server/Utils/Workspace/WorkspaceOAuthState.ts +280 -0
  147. package/Server/Utils/Workspace/WorkspaceProjectReferenceValidator.ts +96 -0
  148. package/Server/Utils/Workspace/WorkspaceReactionNote.ts +620 -0
  149. package/Tests/App/Dashboard/AttributesJSONDashboardSurfaces.test.tsx +496 -0
  150. package/Tests/App/Dashboard/AutoRemediationRulesTableCommandRunners.test.tsx +152 -0
  151. package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +32 -0
  152. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +794 -0
  153. package/Tests/App/Dashboard/CreateOAuthWorkflowVariableModal.test.tsx +840 -0
  154. package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +653 -0
  155. package/Tests/App/Dashboard/DatabaseMonitorStepForm.test.tsx +197 -0
  156. package/Tests/App/Dashboard/DatabaseMonitorView.test.tsx +376 -0
  157. package/Tests/App/Dashboard/DisabledWarningRobustness.test.tsx +262 -0
  158. package/Tests/App/Dashboard/EventNotes.test.tsx +2080 -0
  159. package/Tests/App/Dashboard/EventNotesPages.test.tsx +486 -0
  160. package/Tests/App/Dashboard/EventNotesUtil.test.ts +933 -0
  161. package/Tests/App/Dashboard/ExceptionMonitorEnvironmentFilter.test.tsx +218 -0
  162. package/Tests/App/Dashboard/IncidentChangeStateNotifyDefault.test.tsx +665 -0
  163. package/Tests/App/Dashboard/IncidentEpisodeFeedPublicNoteNotifyDefault.test.tsx +494 -0
  164. package/Tests/App/Dashboard/IncidentEpisodeOverviewNotifyDefault.test.tsx +706 -0
  165. package/Tests/App/Dashboard/IncidentFeedPublicNoteNotifyDefault.test.tsx +472 -0
  166. package/Tests/App/Dashboard/IncidentOverviewNotifyDefault.test.tsx +858 -0
  167. package/Tests/App/Dashboard/IncomingEmailAddressSettings.test.tsx +567 -0
  168. package/Tests/App/Dashboard/InvestigationClusterToolFormat.test.ts +241 -0
  169. package/Tests/App/Dashboard/InvestigationEvidenceKubectl.test.tsx +322 -0
  170. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +12 -0
  171. package/Tests/App/Dashboard/InvestigationPanelClusterAccess.test.tsx +476 -0
  172. package/Tests/App/Dashboard/InvestigationRunDetailsKubectl.test.tsx +383 -0
  173. package/Tests/App/Dashboard/KubectlActivitySummary.test.tsx +366 -0
  174. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +2886 -0
  175. package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +2688 -0
  176. package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +915 -0
  177. package/Tests/App/Dashboard/LayerDateTimeFieldTimezoneName.test.tsx +66 -0
  178. package/Tests/App/Dashboard/LogMonitorPreview.test.tsx +174 -0
  179. package/Tests/App/Dashboard/MonitorFeedRefresh.test.tsx +279 -0
  180. package/Tests/App/Dashboard/MonitorMetricQueryConfig.test.ts +244 -0
  181. package/Tests/App/Dashboard/MonitorOpenWorkCard.test.tsx +381 -0
  182. package/Tests/App/Dashboard/MonitorOpenWorkHook.test.tsx +784 -0
  183. package/Tests/App/Dashboard/MonitorOverviewData.test.tsx +2199 -0
  184. package/Tests/App/Dashboard/MonitorOverviewHero.test.tsx +1169 -0
  185. package/Tests/App/Dashboard/MonitorOverviewInput.test.ts +1127 -0
  186. package/Tests/App/Dashboard/MonitorOverviewPage.test.tsx +2136 -0
  187. package/Tests/App/Dashboard/MonitorOverviewSelectReadable.test.ts +368 -0
  188. package/Tests/App/Dashboard/MonitorOverviewStatBar.test.tsx +526 -0
  189. package/Tests/App/Dashboard/MonitorOverviewSupportingCards.test.tsx +542 -0
  190. package/Tests/App/Dashboard/MonitorOwnersCombine.test.ts +299 -0
  191. package/Tests/App/Dashboard/MonitorProbesCard.test.tsx +602 -0
  192. package/Tests/App/Dashboard/MonitorResponseTimeCard.test.tsx +386 -0
  193. package/Tests/App/Dashboard/MonitorSetupAndConnectionCards.test.tsx +612 -0
  194. package/Tests/App/Dashboard/MonitorStatusChangesCard.test.tsx +257 -0
  195. package/Tests/App/Dashboard/MonitorSummaryTestMonitorButton.test.tsx +360 -1
  196. package/Tests/App/Dashboard/MonitorUptimeHistoryCard.test.tsx +835 -0
  197. package/Tests/App/Dashboard/MonitorUptimeSummaryHook.test.tsx +971 -0
  198. package/Tests/App/Dashboard/MonitorViewLayout.test.tsx +580 -0
  199. package/Tests/App/Dashboard/OnCallLayerRestrictionTimesPreserved.test.tsx +441 -0
  200. package/Tests/App/Dashboard/OnCallNavbar.test.tsx +214 -0
  201. package/Tests/App/Dashboard/OnCallSchedulePreviewCalendarDisplay.test.tsx +1389 -0
  202. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +205 -1
  203. package/Tests/App/Dashboard/OnCallScheduleTimeInputsSettingsZone.test.tsx +198 -0
  204. package/Tests/App/Dashboard/PublicNotePagesNotifyDefault.test.tsx +524 -0
  205. package/Tests/App/Dashboard/RemediationSuggestionCardApproval.test.tsx +702 -0
  206. package/Tests/App/Dashboard/RemoveUserFromProject.test.tsx +427 -0
  207. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +4 -0
  208. package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +3 -1
  209. package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +166 -0
  210. package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +622 -0
  211. package/Tests/App/Dashboard/ScheduledMaintenanceChangeStateNotifyDefault.test.tsx +1491 -0
  212. package/Tests/App/Dashboard/ScheduledMaintenanceFeedPublicNoteNotifyDefault.test.tsx +489 -0
  213. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewNotifyDefault.test.tsx +909 -0
  214. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +14 -0
  215. package/Tests/App/Dashboard/ScheduledMaintenanceWindowStatsTranslation.test.tsx +307 -0
  216. package/Tests/App/Dashboard/SecurityEventAttributeColumnPicker.test.tsx +542 -0
  217. package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +174 -0
  218. package/Tests/App/Dashboard/SecurityEventConnectionsEmptyState.test.tsx +973 -212
  219. package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +491 -52
  220. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +301 -0
  221. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +158 -1
  222. package/Tests/App/Dashboard/SecurityEventProviderTile.test.tsx +869 -0
  223. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +959 -94
  224. package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +2 -0
  225. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +274 -1
  226. package/Tests/App/Dashboard/TeamMembershipRemoval.test.ts +900 -0
  227. package/Tests/App/Dashboard/TeamMembershipRemovalPages.test.tsx +460 -0
  228. package/Tests/App/Dashboard/TimezoneElements.test.tsx +321 -0
  229. package/Tests/App/Dashboard/TimezoneSelectButton.test.tsx +634 -0
  230. package/Tests/App/Dashboard/TraceExplorer.test.tsx +260 -0
  231. package/Tests/App/Dashboard/TraceMonitorPreview.test.tsx +182 -0
  232. package/Tests/App/Dashboard/UserTimezoneInit.test.tsx +544 -0
  233. package/Tests/App/Dashboard/WorkflowVariableModals.test.tsx +1630 -0
  234. package/Tests/App/Dashboard/WorkflowVariableRoutes.test.tsx +603 -0
  235. package/Tests/App/Dashboard/WorkflowVariableTokenStatus.test.tsx +589 -0
  236. package/Tests/App/Dashboard/WorkflowVariableUtil.test.ts +1543 -0
  237. package/Tests/App/Dashboard/WorkflowVariableView.test.tsx +3227 -0
  238. package/Tests/App/Dashboard/WorkflowVariablesTable.test.tsx +1277 -395
  239. package/Tests/App/StatusPage/StatusPageOverviewMonitorGroupUptime.test.tsx +714 -0
  240. package/Tests/App/StatusPage/StatusPageOverviewUptimeBars.NewYork.test.tsx +1009 -0
  241. package/Tests/App/StatusPage/StatusPageOverviewUptimeBars.test.tsx +1092 -0
  242. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +5 -0
  243. package/Tests/Models/DatabaseModels/KubernetesClusterAiAccessColumns.test.ts +520 -0
  244. package/Tests/Models/DatabaseModels/MonitorSecretKeyColumnAccessControl.test.ts +66 -2
  245. package/Tests/Models/DatabaseModels/WorkspaceProjectAuthTokenAccessControl.test.ts +236 -0
  246. package/Tests/Models/IncidentEpisodePublicNoteNotifyColumnContract.test.ts +103 -0
  247. package/Tests/Models/IncidentPublicNoteNotifyColumnContract.test.ts +96 -0
  248. package/Tests/Models/ScheduledMaintenancePublicNoteNotifyColumnContract.test.ts +111 -0
  249. package/Tests/Server/API/AIInvestigationAPI.test.ts +976 -0
  250. package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +836 -0
  251. package/Tests/Server/API/CommonAPIAssertCanCreateTable.test.ts +565 -0
  252. package/Tests/Server/API/CommonAPIAssertCanReadTable.test.ts +282 -0
  253. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +1744 -0
  254. package/Tests/Server/API/LogHistogramAPI.test.ts +371 -0
  255. package/Tests/Server/API/MicrosoftTeamsLegacyWebhookRemoval.test.ts +125 -30
  256. package/Tests/Server/API/MicrosoftTeamsOAuthState.test.ts +1121 -0
  257. package/Tests/Server/API/MonitorUptimeSummaryAPI.test.ts +685 -0
  258. package/Tests/Server/API/SessionReplayAPI.test.ts +602 -1
  259. package/Tests/Server/API/SlackChannelCacheAPI.test.ts +358 -0
  260. package/Tests/Server/API/SlackOAuthState.test.ts +688 -0
  261. package/Tests/Server/API/StatusPageOverviewMonitorGroupUptime.test.ts +527 -0
  262. package/Tests/Server/API/StatusPageTestEmailReportAuth.test.ts +2 -0
  263. package/Tests/Server/API/StatusPageUptimeAPI.test.ts +427 -0
  264. package/Tests/Server/API/UserProjectsAPI.test.ts +4 -0
  265. package/Tests/Server/API/WorkflowVariableAPI.test.ts +404 -0
  266. package/Tests/Server/API/WorkspaceOAuthTestHelpers.ts +289 -0
  267. package/Tests/Server/API/WorkspaceSendTestNotificationRoutes.test.ts +2064 -0
  268. package/Tests/Server/Infrastructure/GlobalCache.test.ts +86 -0
  269. package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +589 -0
  270. package/Tests/Server/Infrastructure/Postgres/AddOAuth2WorkflowVariablesMigration.test.ts +254 -0
  271. package/Tests/Server/Middleware/BlockedUserMiddleware.test.ts +403 -0
  272. package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +13 -0
  273. package/Tests/Server/Middleware/PublicRouteUserMiddleware.test.ts +2 -0
  274. package/Tests/Server/Middleware/RemovedProjectMemberAuthorization.test.ts +469 -0
  275. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +77 -1
  276. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +211 -0
  277. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +358 -0
  278. package/Tests/Server/Middleware/UserAuthorization.test.ts +97 -0
  279. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +2 -0
  280. package/Tests/Server/Services/AccessTokenProjectUserGrant.test.ts +14 -2
  281. package/Tests/Server/Services/AccessTokenRemovedMemberAccess.test.ts +1044 -0
  282. package/Tests/Server/Services/AddOwnersIdempotency.test.ts +5 -0
  283. package/Tests/Server/Services/AlertEpisodeMemberCreatePermission.test.ts +139 -0
  284. package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +1361 -0
  285. package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +375 -0
  286. package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +2384 -0
  287. package/Tests/Server/Services/FindOwnersProjectMembership.test.ts +267 -0
  288. package/Tests/Server/Services/InboundEmail/SendGridInboundProviderAddress.test.ts +90 -0
  289. package/Tests/Server/Services/IncidentEpisodeMemberCreatePermission.test.ts +143 -0
  290. package/Tests/Server/Services/IncidentEpisodePublicNoteNotifyDefault.test.ts +805 -0
  291. package/Tests/Server/Services/IncidentPublicNoteNotifyDefault.test.ts +724 -0
  292. package/Tests/Server/Services/IncidentRoleProjectMembership.test.ts +233 -0
  293. package/Tests/Server/Services/KubernetesClusterAiAccessAgentRunnerAssignments.test.ts +372 -0
  294. package/Tests/Server/Services/KubernetesClusterAiAccessBindingGuard.test.ts +1876 -0
  295. package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +620 -0
  296. package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +421 -0
  297. package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +3662 -0
  298. package/Tests/Server/Services/KubernetesClusterAiAccessSubjectClusters.test.ts +405 -0
  299. package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +975 -0
  300. package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +497 -0
  301. package/Tests/Server/Services/KubernetesClusterServiceDeleteSettlesRemediation.test.ts +328 -0
  302. package/Tests/Server/Services/LogAggregationService.test.ts +99 -0
  303. package/Tests/Server/Services/MonitorServiceIncomingEmailCustomAddress.test.ts +447 -0
  304. package/Tests/Server/Services/MonitorServiceProbeFlagSync.test.ts +1334 -0
  305. package/Tests/Server/Services/MonitorServiceProbeStatusGrouping.test.ts +1640 -0
  306. package/Tests/Server/Services/MonitorServiceRefreshCurrentStatus.test.ts +225 -0
  307. package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +8 -8
  308. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +264 -1
  309. package/Tests/Server/Services/MonitorStatusTimelineMergedDowntime.test.ts +284 -0
  310. package/Tests/Server/Services/MonitorUptimeSummaryService.test.ts +1043 -0
  311. package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +5 -0
  312. package/Tests/Server/Services/OnCallUndeliverablePageOwnerMembership.test.ts +359 -0
  313. package/Tests/Server/Services/ProbeServiceDashboardLink.test.ts +191 -0
  314. package/Tests/Server/Services/ProjectOwnersProjectMembership.test.ts +221 -0
  315. package/Tests/Server/Services/RuleRun/IncidentAlertMaintenanceRuleEnginesRun.test.ts +5 -0
  316. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupARun.test.ts +28 -0
  317. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +9 -1
  318. package/Tests/Server/Services/RunnerJobEnqueueAiCommandAgentRunner.test.ts +230 -0
  319. package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +978 -0
  320. package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +866 -0
  321. package/Tests/Server/Services/RunnerJobSubmitResultRedaction.test.ts +322 -0
  322. package/Tests/Server/Services/RunnerJobSubmitResultUnstorableText.test.ts +357 -0
  323. package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +227 -0
  324. package/Tests/Server/Services/RunnerServiceAgentName.test.ts +581 -0
  325. package/Tests/Server/Services/ScheduledMaintenancePublicNoteNotifyDefault.test.ts +802 -0
  326. package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +53 -0
  327. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +5 -0
  328. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +12 -0
  329. package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +1176 -1
  330. package/Tests/Server/Services/TeamMemberBillingSeatSync.test.ts +9 -0
  331. package/Tests/Server/Services/TeamMemberOnCallCleanup.test.ts +18 -0
  332. package/Tests/Server/Services/TeamMemberProjectMembership.test.ts +255 -0
  333. package/Tests/Server/Services/TeamMemberRemovalRevokesProjectAccess.test.ts +600 -0
  334. package/Tests/Server/Services/TeamMemberResourceCleanup.test.ts +731 -0
  335. package/Tests/Server/Services/TeamMemberWorkspaceAccountCleanup.test.ts +164 -0
  336. package/Tests/Server/Services/TraceAggregationService.test.ts +64 -0
  337. package/Tests/Server/Services/UserServiceBlockedUser.test.ts +293 -0
  338. package/Tests/Server/Services/WorkflowVariableOAuthHooks.test.ts +1016 -0
  339. package/Tests/Server/Services/WorkflowVariableOAuthPostgres.test.ts +543 -0
  340. package/Tests/Server/Services/WorkflowVariableRenameUniqueness.test.ts +16 -5
  341. package/Tests/Server/Services/WorkspaceNotificationRuleNoteDelivery.test.ts +473 -0
  342. package/Tests/Server/Services/WorkspaceNotificationRuleSendTestNotification.test.ts +3690 -0
  343. package/Tests/Server/Services/WorkspaceProjectAuthTokenMiscDataSecrets.test.ts +374 -0
  344. package/Tests/Server/Services/WorkspaceProjectAuthTokenSlackChannelCache.test.ts +143 -0
  345. package/Tests/Server/Types/Database/Permissions/WorkflowVariableOAuthColumnPermission.test.ts +250 -0
  346. package/Tests/Server/Types/Database/QueryHelperJsonContains.test.ts +96 -0
  347. package/Tests/Server/Types/Markdown.test.ts +1033 -0
  348. package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +285 -0
  349. package/Tests/Server/Utils/AI/CodeFix/CodeFixAgentAuth.test.ts +159 -1
  350. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +752 -0
  351. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +1840 -0
  352. package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +1067 -0
  353. package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +355 -0
  354. package/Tests/Server/Utils/AI/PostIncidentStatusUpdateTool.test.ts +496 -0
  355. package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +305 -0
  356. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +1365 -0
  357. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +639 -0
  358. package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +1585 -0
  359. package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +1065 -0
  360. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +2138 -1
  361. package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +1035 -0
  362. package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +517 -0
  363. package/Tests/Server/Utils/AI/ResourceTools.test.ts +27 -1
  364. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +1371 -24
  365. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorRollbackRace.test.ts +962 -0
  366. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +518 -0
  367. package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +939 -2
  368. package/Tests/Server/Utils/Database/ProjectScopedRelationReferences.test.ts +371 -0
  369. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +64 -0
  370. package/Tests/Server/Utils/Monitor/DatabaseMetricObservationRemediation.test.ts +102 -0
  371. package/Tests/Server/Utils/Monitor/MonitorAlertCriteriaReferences.test.ts +362 -0
  372. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +55 -0
  373. package/Tests/Server/Utils/Monitor/MonitorEmailAddressRedaction.test.ts +255 -0
  374. package/Tests/Server/Utils/Monitor/MonitorIncidentCriteriaReferences.test.ts +347 -0
  375. package/Tests/Server/Utils/Monitor/MonitorIncidentMemberRoleMembership.test.ts +203 -0
  376. package/Tests/Server/Utils/Monitor/ProbeMonitorsNotification.test.ts +1147 -0
  377. package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +79 -0
  378. package/Tests/Server/Utils/ResourceFeed/ResourceFeedUtil.test.ts +21 -1
  379. package/Tests/Server/Utils/Rules/OwnerRuleAssignment.test.ts +155 -1
  380. package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +288 -0
  381. package/Tests/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.test.ts +304 -0
  382. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +40 -3
  383. package/Tests/Server/Utils/Workflow/OAuth2TokenClient.test.ts +702 -0
  384. package/Tests/Server/Utils/Workflow/OAuth2TokenClientHttpIntegration.test.ts +507 -0
  385. package/Tests/Server/Utils/Workflow/WorkflowVariableOAuthToken.test.ts +831 -0
  386. package/Tests/Server/Utils/Workspace/MicrosoftTeamsActionAuthorization.test.ts +63 -1
  387. package/Tests/Server/Utils/Workspace/MicrosoftTeamsAppAccessToken.test.ts +256 -0
  388. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +60 -0
  389. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChatActionAuthorization.test.ts +442 -0
  390. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +44 -2
  391. package/Tests/Server/Utils/Workspace/MicrosoftTeamsDirectMessage.test.ts +55 -0
  392. package/Tests/Server/Utils/Workspace/MicrosoftTeamsReactionNoteSync.test.ts +1522 -0
  393. package/Tests/Server/Utils/Workspace/MicrosoftTeamsServiceUrl.test.ts +130 -0
  394. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +4 -4
  395. package/Tests/Server/Utils/Workspace/Slack/SlackActionAuthorization.test.ts +691 -0
  396. package/Tests/Server/Utils/Workspace/Slack/SlackMessageByTimestamp.test.ts +253 -0
  397. package/Tests/Server/Utils/Workspace/Slack/SlackReactionNote.test.ts +574 -0
  398. package/Tests/Server/Utils/Workspace/WorkspaceActionAuthorization.test.ts +488 -0
  399. package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +861 -0
  400. package/Tests/Server/Utils/Workspace/WorkspaceMessageAuthor.test.ts +635 -0
  401. package/Tests/Server/Utils/Workspace/WorkspaceOAuthState.test.ts +548 -0
  402. package/Tests/Server/Utils/Workspace/WorkspaceReactionNote.test.ts +839 -0
  403. package/Tests/Server/Utils/Workspace/WorkspaceSendErrorMessage.test.ts +725 -0
  404. package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +283 -9
  405. package/Tests/Types/DateBrowserLocalWallClock.test.ts +280 -0
  406. package/Tests/Types/DateLocalShortMonthNameFallback.test.ts +389 -0
  407. package/Tests/Types/DateUserTimezone.test.ts +177 -4
  408. package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +306 -0
  409. package/Tests/Types/Kubernetes/KubernetesClusterAiAccess.test.ts +283 -0
  410. package/Tests/Types/Kubernetes/KubernetesRunnerPostureWriteScope.test.ts +68 -0
  411. package/Tests/Types/Monitor/DatabaseMonitor/SqlServerPlatform.test.ts +144 -0
  412. package/Tests/Types/Monitor/MonitorStepExceptionMonitor.test.ts +160 -0
  413. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +53 -0
  414. package/Tests/Types/Runbook/RunbookStepType.test.ts +91 -16
  415. package/Tests/Types/Runner/RunnerLiveStatus.test.ts +14 -3
  416. package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +15 -0
  417. package/Tests/Types/StatusPage/PublicNoteSubscriberNotificationDefault.test.ts +1868 -0
  418. package/Tests/Types/Timezone.test.ts +5 -0
  419. package/Tests/Types/TimezoneAlias.test.ts +1034 -0
  420. package/Tests/Types/Workflow/JiraTemplateFixtures.ts +833 -0
  421. package/Tests/Types/Workflow/JiraTemplateScripts.test.ts +5414 -0
  422. package/Tests/Types/Workflow/JiraTemplateSimulation.test.ts +4803 -0
  423. package/Tests/Types/Workflow/JiraTemplates.test.ts +5429 -0
  424. package/Tests/Types/Workflow/Templates.test.ts +79 -4
  425. package/Tests/Types/Workflow/WorkflowVariableOAuth.test.ts +520 -0
  426. package/Tests/Types/Workspace/WorkspaceNoteReaction.test.ts +177 -0
  427. package/Tests/UI/Components/AttributesJSON/AttributesJSONView.test.tsx +390 -0
  428. package/Tests/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.test.tsx +566 -0
  429. package/Tests/UI/Components/AttributesJSON/JSONHighlight.test.ts +131 -0
  430. package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +276 -1
  431. package/Tests/UI/Components/Calendar/Calendar.test.tsx +1611 -0
  432. package/Tests/UI/Components/Calendar/CalendarDayLayout.test.ts +1486 -0
  433. package/Tests/UI/Components/Calendar/CalendarDayLayoutDst.test.ts +632 -0
  434. package/Tests/UI/Components/Calendar/CalendarDst.test.tsx +388 -0
  435. package/Tests/UI/Components/Charts/ChartGroupPlotFloor.test.tsx +170 -0
  436. package/Tests/UI/Components/Charts/HistogramSelection.test.ts +282 -0
  437. package/Tests/UI/Components/CustomTimeRangeModal.test.tsx +6 -0
  438. package/Tests/UI/Components/CustomTimeRangeModalTimezoneTranslation.test.tsx +285 -0
  439. package/Tests/UI/Components/Dropdown.test.tsx +999 -2
  440. package/Tests/UI/Components/Forms/FormFieldCheckboxTranslation.test.tsx +216 -0
  441. package/Tests/UI/Components/Forms/FormFieldTimezoneDescriptionTranslation.test.tsx +461 -0
  442. package/Tests/UI/Components/Forms/IncidentEpisodePublicNoteNotifyPayload.test.tsx +641 -0
  443. package/Tests/UI/Components/Forms/IncidentPublicNoteNotifyPayload.test.tsx +346 -0
  444. package/Tests/UI/Components/Forms/ScheduledMaintenancePublicNoteNotifyPayload.test.tsx +493 -0
  445. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +911 -2
  446. package/Tests/UI/Components/Graphs/DayUptimeGraphTimezone.NewYork.test.tsx +730 -0
  447. package/Tests/UI/Components/Graphs/DayUptimeGraphTimezone.Tokyo.test.tsx +506 -0
  448. package/Tests/UI/Components/HistogramClickToZoom.test.tsx +619 -0
  449. package/Tests/UI/Components/LogDetailsPanelAttributesJSON.test.tsx +248 -0
  450. package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +47 -1
  451. package/Tests/UI/Components/LogsViewerSmallScreens.test.tsx +620 -0
  452. package/Tests/UI/Components/ModelPageModelChange.test.tsx +242 -3
  453. package/Tests/UI/Components/ModelTable/BaseModelTableDeleteConfirmation.test.tsx +521 -0
  454. package/Tests/UI/Components/MonitorGraphs/Uptime.test.tsx +406 -2
  455. package/Tests/UI/Components/MonitorGraphs/UptimeBarDayModal.test.tsx +169 -2
  456. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +266 -0
  457. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerSmallScreens.test.tsx +439 -0
  458. package/Tests/UI/Components/TimezoneDropdownLegacyValues.test.tsx +704 -0
  459. package/Tests/UI/Components/UseHistogramZoom.test.tsx +89 -1
  460. package/Tests/UI/Components/UseLogsHistogram.test.tsx +175 -0
  461. package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +5 -5
  462. package/Tests/UI/Telemetry/TelemetryDetailPanel.test.tsx +28 -0
  463. package/Tests/UI/Utils/ProjectUsersModelAPI.test.ts +51 -0
  464. package/Tests/UI/Utils/Timezone.test.ts +747 -33
  465. package/Tests/UI/Workspace/SendTestNotificationButton.test.tsx +1854 -0
  466. package/Tests/UI/Workspace/WorkspaceCardsSendTestNotification.test.tsx +1864 -0
  467. package/Tests/Utils/AI/InvestigationReport.test.ts +435 -7
  468. package/Tests/Utils/AiRemediation/KubectlAllowlistValidatorParity.test.ts +1084 -0
  469. package/Tests/Utils/AiRemediation/KubectlOutputRedactor.test.ts +2531 -0
  470. package/Tests/Utils/AiRemediation/KubectlPolicy.test.ts +1895 -0
  471. package/Tests/Utils/AiRemediation/KubectlPolicyAllowlist.test.ts +428 -0
  472. package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +828 -0
  473. package/Tests/Utils/AiRemediation/KubectlPolicyCustomResourceScope.test.ts +573 -0
  474. package/Tests/Utils/AiRemediation/KubectlPolicyDenials.test.ts +1525 -0
  475. package/Tests/Utils/AiRemediation/KubectlPolicyExposeOverrides.test.ts +275 -0
  476. package/Tests/Utils/AiRemediation/KubectlPolicyNodePatch.test.ts +428 -0
  477. package/Tests/Utils/AiRemediation/KubectlPolicyObjectWords.test.ts +195 -0
  478. package/Tests/Utils/AiRemediation/KubectlPolicyPatchParents.test.ts +637 -0
  479. package/Tests/Utils/AiRemediation/KubectlPolicyPodSecurityBaseline.test.ts +322 -0
  480. package/Tests/Utils/AiRemediation/KubectlPolicySafeWriteScope.test.ts +1026 -0
  481. package/Tests/Utils/AiRemediation/KubectlWaitBudget.test.ts +267 -0
  482. package/Tests/Utils/AiRemediation/KubectlWriteScope.test.ts +390 -0
  483. package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +777 -0
  484. package/Tests/Utils/AiRemediation/KubectlWriteScopeClusterScoped.test.ts +613 -0
  485. package/Tests/Utils/AiRemediation/KubectlWriteScopeEntryPoint.test.ts +576 -0
  486. package/Tests/Utils/AiRemediation/KubectlWriteScopeKubectlSpellings.test.ts +752 -0
  487. package/Tests/Utils/AiRemediation/KubectlWriteScopeObjectWords.test.ts +358 -0
  488. package/Tests/Utils/AiRemediation/KubectlWriteScopeOverrides.test.ts +293 -0
  489. package/Tests/Utils/AiRemediation/KubectlWriteScopeParityCases.ts +598 -0
  490. package/Tests/Utils/AiRemediation/KubectlWriteScopePolicyParity.test.ts +403 -0
  491. package/Tests/Utils/Dashboard/DashboardClockComponent.test.ts +154 -5
  492. package/Tests/Utils/Monitor/IncomingEmailMonitorAddress.test.ts +478 -0
  493. package/Tests/Utils/Monitor/MonitorCheckScheduleUtil.test.ts +646 -0
  494. package/Tests/Utils/Monitor/MonitorOverviewCriteriaUtil.test.ts +292 -0
  495. package/Tests/Utils/Monitor/MonitorOverviewFamily.test.ts +274 -0
  496. package/Tests/Utils/Monitor/MonitorOverviewPresentationUtil.test.ts +3100 -0
  497. package/Tests/Utils/Monitor/MonitorOverviewProbeUtil.test.ts +1412 -0
  498. package/Tests/Utils/Monitor/MonitorOverviewTargetUtil.test.ts +374 -0
  499. package/Tests/Utils/Monitor/MonitorStatusHistoryUtil.test.ts +332 -0
  500. package/Tests/Utils/Monitor/MonitorUptimeSummaryUtil.test.ts +946 -0
  501. package/Tests/Utils/Rum/SessionIdentity.test.ts +94 -0
  502. package/Tests/Utils/Rum/SessionReplayWafCompatibility.test.ts +840 -0
  503. package/Tests/Utils/Rum/SessionReplayWireEncoding.test.ts +208 -0
  504. package/Tests/Utils/Rum/UserFlow.test.ts +1010 -0
  505. package/Tests/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.test.ts +217 -0
  506. package/Tests/Utils/StatusPage/ResourceUptime.test.ts +1272 -1
  507. package/Tests/Utils/StatusPage/UptimeDailyAggregateTotals.test.ts +298 -0
  508. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +649 -1
  509. package/Tests/Utils/StatusPage/UptimeDailyAggregateWindow.test.ts +314 -0
  510. package/Tests/Utils/Telemetry/AttributesJSON.test.ts +454 -0
  511. package/Tests/Utils/Uptime/DayUptimeGraphUtil.test.ts +418 -2
  512. package/Tests/Utils/Uptime/DayUptimeGraphUtilMidnightDst.test.ts +160 -0
  513. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.Auckland.test.ts +45 -0
  514. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.Kolkata.test.ts +40 -0
  515. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.London.test.ts +147 -0
  516. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.NewYork.test.ts +48 -0
  517. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.Tokyo.test.ts +39 -0
  518. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezoneCases.ts +1015 -0
  519. package/Tests/Utils/Uptime/UptimeUtil.test.ts +75 -0
  520. package/Tests/Utils/Uptime/UptimeUtilChronologicalOrder.test.ts +1279 -0
  521. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +203 -5
  522. package/Types/Date.ts +121 -7
  523. package/Types/Email/EmailMessage.ts +8 -0
  524. package/Types/Email/EmailTemplateType.ts +1 -0
  525. package/Types/Exception/ExceptionMessages.ts +1 -0
  526. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +488 -0
  527. package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +54 -0
  528. package/Types/Kubernetes/KubernetesClusterAiAccessToolNames.ts +17 -0
  529. package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +9 -0
  530. package/Types/Monitor/DatabaseMonitor/SqlServerPlatform.ts +117 -0
  531. package/Types/Monitor/KubernetesAlertTemplates.ts +6 -5
  532. package/Types/Monitor/MonitorStepExceptionMonitor.ts +56 -0
  533. package/Types/Monitor/MonitorUptimeSummary.ts +113 -0
  534. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +11 -0
  535. package/Types/Rum/SessionReplay.ts +55 -2
  536. package/Types/Rum/SessionReplayApi.ts +44 -1
  537. package/Types/Rum/UserFlow.ts +187 -0
  538. package/Types/Runbook/RunbookStepType.ts +10 -0
  539. package/Types/Runbook/RunnerJobOrigin.ts +15 -0
  540. package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +6 -2
  541. package/Types/StatusPage/MergedDowntimeTotals.ts +17 -0
  542. package/Types/StatusPage/PublicNoteSubscriberNotificationDefault.ts +148 -0
  543. package/Types/StatusPage/UptimeDailyAggregate.ts +15 -0
  544. package/Types/Telemetry/TelemetryIngestSurface.ts +9 -0
  545. package/Types/Timezone.ts +5 -0
  546. package/Types/TimezoneAlias.ts +385 -0
  547. package/Types/Workflow/Templates.ts +3041 -2
  548. package/Types/Workflow/WorkflowVariableOAuth.ts +476 -0
  549. package/Types/Workspace/WorkspaceNoteReaction.ts +132 -0
  550. package/Typings/Index.d.ts +24 -0
  551. package/UI/Components/AttributesJSON/AttributesJSONPreferences.ts +175 -0
  552. package/UI/Components/AttributesJSON/AttributesJSONView.tsx +138 -0
  553. package/UI/Components/AttributesJSON/AttributesViewToggle.tsx +79 -0
  554. package/UI/Components/AttributesJSON/BracesGlyph.tsx +30 -0
  555. package/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.tsx +491 -0
  556. package/UI/Components/AttributesJSON/JSONHighlight.ts +77 -0
  557. package/UI/Components/Calendar/Calendar.css +83 -0
  558. package/UI/Components/Calendar/Calendar.tsx +136 -7
  559. package/UI/Components/Calendar/CalendarDayLayout.ts +236 -0
  560. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +23 -1
  561. package/UI/Components/Charts/Utils/HistogramSelection.ts +117 -0
  562. package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +269 -0
  563. package/UI/Components/Charts/Utils/useHistogramZoom.ts +26 -2
  564. package/UI/Components/Date/CustomTimeRangeModal.tsx +26 -3
  565. package/UI/Components/Dropdown/Dropdown.tsx +58 -9
  566. package/UI/Components/Forms/Fields/FormField.tsx +49 -14
  567. package/UI/Components/Graphs/DayUptimeGraph.tsx +166 -25
  568. package/UI/Components/Graphs/UptimeBarTooltip.tsx +10 -2
  569. package/UI/Components/Graphs/UptimeDaySummary.tsx +8 -0
  570. package/UI/Components/LogsViewer/LogsViewer.tsx +52 -5
  571. package/UI/Components/LogsViewer/components/ColumnSelector.tsx +13 -2
  572. package/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.tsx +13 -1
  573. package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +91 -76
  574. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +15 -1
  575. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +28 -106
  576. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +54 -6
  577. package/UI/Components/LogsViewer/components/SavedViewsDropdown.tsx +8 -2
  578. package/UI/Components/LogsViewer/useLogsHistogram.ts +39 -6
  579. package/UI/Components/ModelTable/BaseModelTable.tsx +66 -14
  580. package/UI/Components/MonitorGraphs/Uptime.tsx +12 -0
  581. package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +10 -2
  582. package/UI/Components/Page/ModelPage.tsx +59 -3
  583. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +69 -5
  584. package/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.tsx +12 -1
  585. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +15 -1
  586. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +36 -104
  587. package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +9 -1
  588. package/UI/Utils/ModelAPI/ProjectUsersModelAPI.ts +19 -1
  589. package/UI/Utils/Timezone.ts +69 -28
  590. package/Utils/AI/InvestigationReport.ts +195 -25
  591. package/Utils/AiRemediation/KubectlOutputRedactor.ts +1724 -0
  592. package/Utils/AiRemediation/KubectlPolicy.ts +4136 -0
  593. package/Utils/AiRemediation/KubectlWaitBudget.ts +156 -0
  594. package/Utils/AiRemediation/KubectlWriteScope.ts +1964 -0
  595. package/Utils/Dashboard/Components/DashboardClockComponent.ts +7 -6
  596. package/Utils/Monitor/IncomingEmailMonitorAddress.ts +292 -0
  597. package/Utils/Monitor/MonitorCheckScheduleUtil.ts +654 -0
  598. package/Utils/Monitor/MonitorOverviewCriteriaUtil.ts +188 -0
  599. package/Utils/Monitor/MonitorOverviewFamily.ts +263 -0
  600. package/Utils/Monitor/MonitorOverviewPresentationUtil.ts +1958 -0
  601. package/Utils/Monitor/MonitorOverviewProbeUtil.ts +979 -0
  602. package/Utils/Monitor/MonitorOverviewTargetUtil.ts +299 -0
  603. package/Utils/Monitor/MonitorStatusHistoryUtil.ts +201 -0
  604. package/Utils/Monitor/MonitorUptimeSummaryUtil.ts +638 -0
  605. package/Utils/Rum/SessionIdentity.ts +44 -0
  606. package/Utils/Rum/SessionReplayWireEncoding.ts +137 -0
  607. package/Utils/Rum/UserFlow.ts +1527 -0
  608. package/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.ts +107 -0
  609. package/Utils/StatusPage/ResourceUptime.ts +99 -0
  610. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +197 -0
  611. package/Utils/Telemetry/AttributesJSON.ts +367 -0
  612. package/Utils/Uptime/DayUptimeGraphUtil.ts +165 -0
  613. package/Utils/Uptime/UptimeUtil.ts +122 -38
  614. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +8 -1
  615. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
  616. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
  617. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
  618. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +8 -1
  619. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
  620. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +10 -3
  621. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
  622. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +10 -3
  623. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  624. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +434 -0
  625. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  626. package/build/dist/Models/DatabaseModels/Monitor.js +49 -0
  627. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  628. package/build/dist/Models/DatabaseModels/Runner.js +4 -4
  629. package/build/dist/Models/DatabaseModels/Runner.js.map +1 -1
  630. package/build/dist/Models/DatabaseModels/RunnerJob.js +66 -0
  631. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
  632. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +11 -3
  633. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  634. package/build/dist/Models/DatabaseModels/WorkflowVariable.js +487 -3
  635. package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
  636. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js +64 -16
  637. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  638. package/build/dist/Server/API/AIInvestigationAPI.js +205 -0
  639. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  640. package/build/dist/Server/API/AutoRemediationAPI.js +115 -2
  641. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  642. package/build/dist/Server/API/CommonAPI.js +49 -0
  643. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  644. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +564 -0
  645. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -0
  646. package/build/dist/Server/API/MicrosoftTeamsAPI.js +465 -176
  647. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  648. package/build/dist/Server/API/MonitorAPI.js +107 -1
  649. package/build/dist/Server/API/MonitorAPI.js.map +1 -1
  650. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js +5 -16
  651. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js.map +1 -1
  652. package/build/dist/Server/API/SlackAPI.js +322 -78
  653. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  654. package/build/dist/Server/API/StatusPageAPI.js +123 -17
  655. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  656. package/build/dist/Server/API/TelemetryAPI.js +144 -5
  657. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  658. package/build/dist/Server/API/UserTwoFactorBackupCodeAPI.js +1 -0
  659. package/build/dist/Server/API/UserTwoFactorBackupCodeAPI.js.map +1 -1
  660. package/build/dist/Server/API/WorkflowVariableAPI.js +109 -0
  661. package/build/dist/Server/API/WorkflowVariableAPI.js.map +1 -0
  662. package/build/dist/Server/Infrastructure/GlobalCache.js +29 -0
  663. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  664. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794300000000-AddOAuth2WorkflowVariables.js +38 -0
  665. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794300000000-AddOAuth2WorkflowVariables.js.map +1 -0
  666. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794400000000-AddKubernetesClusterAiAccess.js +54 -0
  667. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794400000000-AddKubernetesClusterAiAccess.js.map +1 -0
  668. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794500000000-AddIncomingEmailCustomAddressToMonitor.js +14 -0
  669. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794500000000-AddIncomingEmailCustomAddressToMonitor.js.map +1 -0
  670. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794600000000-AddAuthTokenExpiresAtToWorkspaceProjectAuthToken.js +12 -0
  671. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794600000000-AddAuthTokenExpiresAtToWorkspaceProjectAuthToken.js.map +1 -0
  672. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794700000000-RemoveAppAccessTokenFromWorkspaceProjectAuthTokenMiscData.js +32 -0
  673. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794700000000-RemoveAppAccessTokenFromWorkspaceProjectAuthTokenMiscData.js.map +1 -0
  674. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  675. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  676. package/build/dist/Server/Middleware/MasterAdminAuthorization.js +21 -0
  677. package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
  678. package/build/dist/Server/Middleware/TelemetryIngest.js +32 -2
  679. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  680. package/build/dist/Server/Middleware/UserAuthorization.js +39 -6
  681. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  682. package/build/dist/Server/Services/AIAgentService.js +1 -0
  683. package/build/dist/Server/Services/AIAgentService.js.map +1 -1
  684. package/build/dist/Server/Services/AccessTokenService.js +87 -42
  685. package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
  686. package/build/dist/Server/Services/AlertEpisodeMemberService.js +4 -0
  687. package/build/dist/Server/Services/AlertEpisodeMemberService.js.map +1 -1
  688. package/build/dist/Server/Services/AlertEpisodeService.js +12 -1
  689. package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
  690. package/build/dist/Server/Services/AlertService.js +110 -23
  691. package/build/dist/Server/Services/AlertService.js.map +1 -1
  692. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +716 -30
  693. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  694. package/build/dist/Server/Services/AutoRemediationRuleService.js +100 -0
  695. package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
  696. package/build/dist/Server/Services/BillingService.js +1 -0
  697. package/build/dist/Server/Services/BillingService.js.map +1 -1
  698. package/build/dist/Server/Services/InboundEmail/Providers/SendGridInboundProvider.js +11 -16
  699. package/build/dist/Server/Services/InboundEmail/Providers/SendGridInboundProvider.js.map +1 -1
  700. package/build/dist/Server/Services/IncidentEpisodeMemberService.js +4 -0
  701. package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
  702. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +48 -0
  703. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  704. package/build/dist/Server/Services/IncidentEpisodeRoleMemberService.js +21 -0
  705. package/build/dist/Server/Services/IncidentEpisodeRoleMemberService.js.map +1 -1
  706. package/build/dist/Server/Services/IncidentEpisodeService.js +12 -1
  707. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  708. package/build/dist/Server/Services/IncidentGroupingEngineService.js +8 -0
  709. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  710. package/build/dist/Server/Services/IncidentMemberService.js +14 -0
  711. package/build/dist/Server/Services/IncidentMemberService.js.map +1 -1
  712. package/build/dist/Server/Services/IncidentPublicNoteService.js +48 -0
  713. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  714. package/build/dist/Server/Services/IncidentService.js +99 -21
  715. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  716. package/build/dist/Server/Services/IncidentStateTimelineService.js +12 -0
  717. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  718. package/build/dist/Server/Services/IncidentTemplateService.js +68 -4
  719. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  720. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +1470 -0
  721. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -0
  722. package/build/dist/Server/Services/KubernetesClusterService.js +1097 -0
  723. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  724. package/build/dist/Server/Services/LogAggregationService.js +14 -6
  725. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  726. package/build/dist/Server/Services/MonitorService.js +487 -48
  727. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  728. package/build/dist/Server/Services/MonitorStatusTimelineService.js +540 -3
  729. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  730. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +2 -0
  731. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  732. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +2 -0
  733. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  734. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +2 -0
  735. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  736. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +3 -0
  737. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  738. package/build/dist/Server/Services/OnCallNotificationAlertingService.js +29 -7
  739. package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -1
  740. package/build/dist/Server/Services/OnCallSetupReminderService.js +1 -0
  741. package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -1
  742. package/build/dist/Server/Services/ProbeService.js +7 -1
  743. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  744. package/build/dist/Server/Services/ProjectService.js +11 -1
  745. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  746. package/build/dist/Server/Services/RunbookCredentialService.js +24 -0
  747. package/build/dist/Server/Services/RunbookCredentialService.js.map +1 -1
  748. package/build/dist/Server/Services/RunbookSecretService.js +44 -0
  749. package/build/dist/Server/Services/RunbookSecretService.js.map +1 -1
  750. package/build/dist/Server/Services/RunnerJobService.js +641 -21
  751. package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
  752. package/build/dist/Server/Services/RunnerService.js +344 -5
  753. package/build/dist/Server/Services/RunnerService.js.map +1 -1
  754. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +48 -0
  755. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  756. package/build/dist/Server/Services/ScheduledMaintenanceService.js +102 -20
  757. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  758. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +67 -4
  759. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
  760. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +12 -1
  761. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  762. package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -0
  763. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  764. package/build/dist/Server/Services/StatusPageService.js +230 -32
  765. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  766. package/build/dist/Server/Services/StatusPageSubscriberService.js +4 -0
  767. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  768. package/build/dist/Server/Services/TeamMemberService.js +270 -11
  769. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  770. package/build/dist/Server/Services/TraceAggregationService.js +10 -6
  771. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  772. package/build/dist/Server/Services/UserEmailService.js +1 -0
  773. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  774. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1 -0
  775. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -1
  776. package/build/dist/Server/Services/UserNotificationRuleAdminService.js +1 -0
  777. package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -1
  778. package/build/dist/Server/Services/UserNotificationRuleService.js +4 -0
  779. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  780. package/build/dist/Server/Services/UserService.js +107 -1
  781. package/build/dist/Server/Services/UserService.js.map +1 -1
  782. package/build/dist/Server/Services/WorkflowVariableService.js +396 -7
  783. package/build/dist/Server/Services/WorkflowVariableService.js.map +1 -1
  784. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +463 -7
  785. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  786. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +144 -2
  787. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
  788. package/build/dist/Server/Types/Database/QueryHelper.js +20 -0
  789. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  790. package/build/dist/Server/Types/Markdown.js +394 -27
  791. package/build/dist/Server/Types/Markdown.js.map +1 -1
  792. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +123 -0
  793. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -0
  794. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +344 -0
  795. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -0
  796. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +587 -0
  797. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -0
  798. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js +18 -2
  799. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js.map +1 -1
  800. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1380 -239
  801. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  802. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +1099 -68
  803. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  804. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +88 -6
  805. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  806. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +45 -11
  807. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  808. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +41 -11
  809. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  810. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js +11 -4
  811. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -1
  812. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +4 -2
  813. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -1
  814. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +997 -141
  815. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
  816. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +299 -4
  817. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
  818. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js +120 -0
  819. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js.map +1 -0
  820. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +160 -1
  821. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
  822. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +1 -0
  823. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
  824. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +59 -12
  825. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  826. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +5 -1
  827. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  828. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +84 -22
  829. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  830. package/build/dist/Server/Utils/Monitor/MonitorPayloadRedaction.js +70 -5
  831. package/build/dist/Server/Utils/Monitor/MonitorPayloadRedaction.js.map +1 -1
  832. package/build/dist/Server/Utils/Monitor/ProbeMonitorsNotification.js +249 -0
  833. package/build/dist/Server/Utils/Monitor/ProbeMonitorsNotification.js.map +1 -0
  834. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js +1 -0
  835. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js.map +1 -1
  836. package/build/dist/Server/Utils/PushNotificationUtil.js +27 -0
  837. package/build/dist/Server/Utils/PushNotificationUtil.js.map +1 -1
  838. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +26 -3
  839. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -1
  840. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js +38 -3
  841. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js.map +1 -1
  842. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +143 -23
  843. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
  844. package/build/dist/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.js +406 -0
  845. package/build/dist/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.js.map +1 -0
  846. package/build/dist/Server/Utils/StartServer.js +4 -3
  847. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  848. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +382 -0
  849. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -0
  850. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js +1 -0
  851. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js.map +1 -1
  852. package/build/dist/Server/Utils/UserPermission/UserPermission.js +10 -0
  853. package/build/dist/Server/Utils/UserPermission/UserPermission.js.map +1 -1
  854. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js +447 -0
  855. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js.map +1 -0
  856. package/build/dist/Server/Utils/Workflow/WorkflowVariableOAuthToken.js +202 -0
  857. package/build/dist/Server/Utils/Workflow/WorkflowVariableOAuthToken.js.map +1 -0
  858. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +39 -1
  859. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
  860. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +44 -4
  861. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
  862. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +150 -191
  863. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  864. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +44 -4
  865. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  866. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js +39 -17
  867. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js.map +1 -1
  868. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +151 -145
  869. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
  870. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +221 -127
  871. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  872. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsServiceUrl.js +91 -0
  873. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsServiceUrl.js.map +1 -0
  874. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/ReactionNoteSync.js +673 -0
  875. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/ReactionNoteSync.js.map +1 -0
  876. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js +3 -9
  877. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js.map +1 -1
  878. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +65 -166
  879. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js.map +1 -1
  880. package/build/dist/Server/Utils/Workspace/Slack/Actions/AlertEpisode.js +63 -157
  881. package/build/dist/Server/Utils/Workspace/Slack/Actions/AlertEpisode.js.map +1 -1
  882. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +23 -3
  883. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -1
  884. package/build/dist/Server/Utils/Workspace/Slack/Actions/Authorization.js +92 -0
  885. package/build/dist/Server/Utils/Workspace/Slack/Actions/Authorization.js.map +1 -0
  886. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +81 -210
  887. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js.map +1 -1
  888. package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js +68 -138
  889. package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js.map +1 -1
  890. package/build/dist/Server/Utils/Workspace/Slack/Actions/ReactionNote.js +240 -0
  891. package/build/dist/Server/Utils/Workspace/Slack/Actions/ReactionNote.js.map +1 -0
  892. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js +85 -212
  893. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js.map +1 -1
  894. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +60 -17
  895. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  896. package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +2 -0
  897. package/build/dist/Server/Utils/Workspace/Workspace.js +134 -41
  898. package/build/dist/Server/Utils/Workspace/Workspace.js.map +1 -1
  899. package/build/dist/Server/Utils/Workspace/WorkspaceActionAuthorization.js +197 -0
  900. package/build/dist/Server/Utils/Workspace/WorkspaceActionAuthorization.js.map +1 -0
  901. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js +32 -0
  902. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  903. package/build/dist/Server/Utils/Workspace/WorkspaceOAuthState.js +199 -0
  904. package/build/dist/Server/Utils/Workspace/WorkspaceOAuthState.js.map +1 -0
  905. package/build/dist/Server/Utils/Workspace/WorkspaceProjectReferenceValidator.js +91 -0
  906. package/build/dist/Server/Utils/Workspace/WorkspaceProjectReferenceValidator.js.map +1 -0
  907. package/build/dist/Server/Utils/Workspace/WorkspaceReactionNote.js +450 -0
  908. package/build/dist/Server/Utils/Workspace/WorkspaceReactionNote.js.map +1 -0
  909. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +103 -5
  910. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
  911. package/build/dist/Types/Date.js +97 -7
  912. package/build/dist/Types/Date.js.map +1 -1
  913. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  914. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  915. package/build/dist/Types/Exception/ExceptionMessages.js +1 -0
  916. package/build/dist/Types/Exception/ExceptionMessages.js.map +1 -1
  917. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +245 -0
  918. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -0
  919. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +49 -0
  920. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -0
  921. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessToolNames.js +16 -0
  922. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessToolNames.js.map +1 -0
  923. package/build/dist/Types/Monitor/DatabaseMonitor/SqlServerPlatform.js +104 -0
  924. package/build/dist/Types/Monitor/DatabaseMonitor/SqlServerPlatform.js.map +1 -0
  925. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +6 -5
  926. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  927. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js +32 -0
  928. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js.map +1 -1
  929. package/build/dist/Types/Monitor/MonitorUptimeSummary.js +52 -0
  930. package/build/dist/Types/Monitor/MonitorUptimeSummary.js.map +1 -0
  931. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +9 -1
  932. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
  933. package/build/dist/Types/Rum/SessionReplay.js +52 -2
  934. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  935. package/build/dist/Types/Rum/SessionReplayApi.js +11 -0
  936. package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
  937. package/build/dist/Types/Rum/UserFlow.js +115 -0
  938. package/build/dist/Types/Rum/UserFlow.js.map +1 -0
  939. package/build/dist/Types/Runbook/RunbookStepType.js +10 -0
  940. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  941. package/build/dist/Types/Runbook/RunnerJobOrigin.js +14 -0
  942. package/build/dist/Types/Runbook/RunnerJobOrigin.js.map +1 -1
  943. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +2 -2
  944. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -1
  945. package/build/dist/Types/StatusPage/MergedDowntimeTotals.js +2 -0
  946. package/build/dist/Types/StatusPage/MergedDowntimeTotals.js.map +1 -0
  947. package/build/dist/Types/StatusPage/PublicNoteSubscriberNotificationDefault.js +65 -0
  948. package/build/dist/Types/StatusPage/PublicNoteSubscriberNotificationDefault.js.map +1 -0
  949. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +8 -0
  950. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
  951. package/build/dist/Types/Timezone.js +5 -0
  952. package/build/dist/Types/Timezone.js.map +1 -1
  953. package/build/dist/Types/TimezoneAlias.js +340 -0
  954. package/build/dist/Types/TimezoneAlias.js.map +1 -0
  955. package/build/dist/Types/Workflow/Templates.js +2694 -2
  956. package/build/dist/Types/Workflow/Templates.js.map +1 -1
  957. package/build/dist/Types/Workflow/WorkflowVariableOAuth.js +314 -0
  958. package/build/dist/Types/Workflow/WorkflowVariableOAuth.js.map +1 -0
  959. package/build/dist/Types/Workspace/WorkspaceNoteReaction.js +98 -0
  960. package/build/dist/Types/Workspace/WorkspaceNoteReaction.js.map +1 -0
  961. package/build/dist/UI/Components/AttributesJSON/AttributesJSONPreferences.js +95 -0
  962. package/build/dist/UI/Components/AttributesJSON/AttributesJSONPreferences.js.map +1 -0
  963. package/build/dist/UI/Components/AttributesJSON/AttributesJSONView.js +44 -0
  964. package/build/dist/UI/Components/AttributesJSON/AttributesJSONView.js.map +1 -0
  965. package/build/dist/UI/Components/AttributesJSON/AttributesViewToggle.js +27 -0
  966. package/build/dist/UI/Components/AttributesJSON/AttributesViewToggle.js.map +1 -0
  967. package/build/dist/UI/Components/AttributesJSON/BracesGlyph.js +9 -0
  968. package/build/dist/UI/Components/AttributesJSON/BracesGlyph.js.map +1 -0
  969. package/build/dist/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.js +260 -0
  970. package/build/dist/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.js.map +1 -0
  971. package/build/dist/UI/Components/AttributesJSON/JSONHighlight.js +56 -0
  972. package/build/dist/UI/Components/AttributesJSON/JSONHighlight.js.map +1 -0
  973. package/build/dist/UI/Components/Calendar/Calendar.js +94 -7
  974. package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
  975. package/build/dist/UI/Components/Calendar/CalendarDayLayout.js +136 -0
  976. package/build/dist/UI/Components/Calendar/CalendarDayLayout.js.map +1 -0
  977. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +1 -1
  978. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  979. package/build/dist/UI/Components/Charts/Utils/HistogramSelection.js +72 -0
  980. package/build/dist/UI/Components/Charts/Utils/HistogramSelection.js.map +1 -0
  981. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +178 -0
  982. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -0
  983. package/build/dist/UI/Components/Charts/Utils/useHistogramZoom.js +13 -1
  984. package/build/dist/UI/Components/Charts/Utils/useHistogramZoom.js.map +1 -1
  985. package/build/dist/UI/Components/Date/CustomTimeRangeModal.js +20 -4
  986. package/build/dist/UI/Components/Date/CustomTimeRangeModal.js.map +1 -1
  987. package/build/dist/UI/Components/Dropdown/Dropdown.js +33 -9
  988. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  989. package/build/dist/UI/Components/Forms/Fields/FormField.js +36 -13
  990. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  991. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +117 -11
  992. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  993. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +5 -1
  994. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
  995. package/build/dist/UI/Components/Graphs/UptimeDaySummary.js.map +1 -1
  996. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +36 -8
  997. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  998. package/build/dist/UI/Components/LogsViewer/components/ColumnSelector.js +10 -2
  999. package/build/dist/UI/Components/LogsViewer/components/ColumnSelector.js.map +1 -1
  1000. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js +9 -1
  1001. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js.map +1 -1
  1002. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +16 -15
  1003. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
  1004. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +1 -1
  1005. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  1006. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +14 -74
  1007. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  1008. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +22 -5
  1009. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  1010. package/build/dist/UI/Components/LogsViewer/components/SavedViewsDropdown.js +9 -2
  1011. package/build/dist/UI/Components/LogsViewer/components/SavedViewsDropdown.js.map +1 -1
  1012. package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js +16 -5
  1013. package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js.map +1 -1
  1014. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +23 -8
  1015. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  1016. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +7 -1
  1017. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  1018. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +5 -1
  1019. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
  1020. package/build/dist/UI/Components/Page/ModelPage.js +37 -3
  1021. package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
  1022. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +27 -6
  1023. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  1024. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js +7 -1
  1025. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js.map +1 -1
  1026. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +1 -1
  1027. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  1028. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +17 -77
  1029. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  1030. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +10 -1
  1031. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
  1032. package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js +15 -1
  1033. package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js.map +1 -1
  1034. package/build/dist/UI/Utils/Timezone.js +52 -17
  1035. package/build/dist/UI/Utils/Timezone.js.map +1 -1
  1036. package/build/dist/Utils/AI/InvestigationReport.js +116 -21
  1037. package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
  1038. package/build/dist/Utils/AiRemediation/KubectlOutputRedactor.js +1209 -0
  1039. package/build/dist/Utils/AiRemediation/KubectlOutputRedactor.js.map +1 -0
  1040. package/build/dist/Utils/AiRemediation/KubectlPolicy.js +2973 -0
  1041. package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -0
  1042. package/build/dist/Utils/AiRemediation/KubectlWaitBudget.js +99 -0
  1043. package/build/dist/Utils/AiRemediation/KubectlWaitBudget.js.map +1 -0
  1044. package/build/dist/Utils/AiRemediation/KubectlWriteScope.js +1429 -0
  1045. package/build/dist/Utils/AiRemediation/KubectlWriteScope.js.map +1 -0
  1046. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js +7 -6
  1047. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js.map +1 -1
  1048. package/build/dist/Utils/Monitor/IncomingEmailMonitorAddress.js +214 -0
  1049. package/build/dist/Utils/Monitor/IncomingEmailMonitorAddress.js.map +1 -0
  1050. package/build/dist/Utils/Monitor/MonitorCheckScheduleUtil.js +471 -0
  1051. package/build/dist/Utils/Monitor/MonitorCheckScheduleUtil.js.map +1 -0
  1052. package/build/dist/Utils/Monitor/MonitorOverviewCriteriaUtil.js +107 -0
  1053. package/build/dist/Utils/Monitor/MonitorOverviewCriteriaUtil.js.map +1 -0
  1054. package/build/dist/Utils/Monitor/MonitorOverviewFamily.js +191 -0
  1055. package/build/dist/Utils/Monitor/MonitorOverviewFamily.js.map +1 -0
  1056. package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js +1259 -0
  1057. package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js.map +1 -0
  1058. package/build/dist/Utils/Monitor/MonitorOverviewProbeUtil.js +593 -0
  1059. package/build/dist/Utils/Monitor/MonitorOverviewProbeUtil.js.map +1 -0
  1060. package/build/dist/Utils/Monitor/MonitorOverviewTargetUtil.js +195 -0
  1061. package/build/dist/Utils/Monitor/MonitorOverviewTargetUtil.js.map +1 -0
  1062. package/build/dist/Utils/Monitor/MonitorStatusHistoryUtil.js +127 -0
  1063. package/build/dist/Utils/Monitor/MonitorStatusHistoryUtil.js.map +1 -0
  1064. package/build/dist/Utils/Monitor/MonitorUptimeSummaryUtil.js +464 -0
  1065. package/build/dist/Utils/Monitor/MonitorUptimeSummaryUtil.js.map +1 -0
  1066. package/build/dist/Utils/Rum/SessionIdentity.js +31 -1
  1067. package/build/dist/Utils/Rum/SessionIdentity.js.map +1 -1
  1068. package/build/dist/Utils/Rum/SessionReplayWireEncoding.js +128 -0
  1069. package/build/dist/Utils/Rum/SessionReplayWireEncoding.js.map +1 -0
  1070. package/build/dist/Utils/Rum/UserFlow.js +941 -0
  1071. package/build/dist/Utils/Rum/UserFlow.js.map +1 -0
  1072. package/build/dist/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.js +82 -0
  1073. package/build/dist/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.js.map +1 -0
  1074. package/build/dist/Utils/StatusPage/ResourceUptime.js +46 -0
  1075. package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
  1076. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  1077. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -1
  1078. package/build/dist/Utils/Telemetry/AttributesJSON.js +245 -0
  1079. package/build/dist/Utils/Telemetry/AttributesJSON.js.map +1 -0
  1080. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js +103 -0
  1081. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js.map +1 -1
  1082. package/build/dist/Utils/Uptime/UptimeUtil.js +91 -27
  1083. package/build/dist/Utils/Uptime/UptimeUtil.js.map +1 -1
  1084. package/jest.config.json +2 -1
  1085. package/package.json +2 -1
  1086. package/tsconfig.tests.json +36 -0
  1087. package/Tests/UI/Components/EmptyState/EmptyStateGuideLinks.test.tsx +0 -337
  1088. package/UI/Components/EmptyState/EmptyStateGuideLinks.tsx +0 -124
  1089. package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js +0 -47
  1090. package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js.map +0 -1
@@ -0,0 +1,1361 @@
1
+ import AutoRemediationRuleEngineService, {
2
+ ClusterRoundHold,
3
+ DEFAULT_VERIFICATION_WINDOW_MINUTES,
4
+ MAX_CLUSTER_REMEDIATION_ROUNDS_PER_SUBJECT,
5
+ MAX_SUGGESTIONS_PER_SUBJECT,
6
+ getClusterRoundNameSnapshot,
7
+ parseClusterRoundNameSnapshot,
8
+ } from "../../../Server/Services/AutoRemediationRuleEngineService";
9
+ import AutoRemediationRuleService from "../../../Server/Services/AutoRemediationRuleService";
10
+ import AutoRemediationSuggestionService from "../../../Server/Services/AutoRemediationSuggestionService";
11
+ import AlertFeedService from "../../../Server/Services/AlertFeedService";
12
+ import IncidentFeedService from "../../../Server/Services/IncidentFeedService";
13
+ import KubernetesClusterAiAccessService from "../../../Server/Services/KubernetesClusterAiAccessService";
14
+ import ProjectService from "../../../Server/Services/ProjectService";
15
+ import RunnerJobService from "../../../Server/Services/RunnerJobService";
16
+ import AIInvestigationQueue from "../../../Server/Utils/AI/SRE/InvestigationQueue";
17
+ import logger from "../../../Server/Utils/Logger";
18
+ import AutoRemediationSuggestion from "../../../Models/DatabaseModels/AutoRemediationSuggestion";
19
+ import Alert from "../../../Models/DatabaseModels/Alert";
20
+ import Incident from "../../../Models/DatabaseModels/Incident";
21
+ import Project from "../../../Models/DatabaseModels/Project";
22
+ import RunnerJob from "../../../Models/DatabaseModels/RunnerJob";
23
+ import AIRunType from "../../../Types/AI/AIRunType";
24
+ import AutoRemediationExecutionMode from "../../../Types/AutoRemediation/AutoRemediationExecutionMode";
25
+ import AutoRemediationSuggestionStatus from "../../../Types/AutoRemediation/AutoRemediationSuggestionStatus";
26
+ import AutoRemediationSuggestionType from "../../../Types/AutoRemediation/AutoRemediationSuggestionType";
27
+ import AutoRemediationVerificationStatus from "../../../Types/AutoRemediation/AutoRemediationVerificationStatus";
28
+ import {
29
+ KubernetesAiRemediationMode,
30
+ KubernetesClusterAiAccessStatus,
31
+ } from "../../../Types/Kubernetes/KubernetesClusterAiAccess";
32
+ import {
33
+ KUBECTL_ALWAYS_ASKS_SUMMARY,
34
+ KUBECTL_SAFE_CHANGES_SUMMARY,
35
+ } from "../../../Types/AutoRemediation/AiRemediationCommandPlan";
36
+ import ObjectID from "../../../Types/ObjectID";
37
+ import PositiveNumber from "../../../Types/PositiveNumber";
38
+ import { afterEach, beforeEach, describe, expect, it } from "@jest/globals";
39
+
40
+ // A node taint always needs a human, in every mode (the canonical comment).
41
+ const TAINT_WORD_PATTERN: RegExp = /\btaint\b/;
42
+
43
+ /*
44
+ * Contract under test — cluster-level remediation in the rule engine, the
45
+ * lane a cluster's AI page turns on without any AutoRemediationRule:
46
+ *
47
+ * - every remediation-ready cluster the signal is about gets ONE Planning
48
+ * CommandPlan suggestion that carries the cluster id, snapshots the mode
49
+ * (Automatic → FullAuto with auto-resolve, RequireApproval → Suggest) and
50
+ * enqueues a RemediationExecution run linked back onto it;
51
+ * - a cluster that is not ready, or already has a round on this subject,
52
+ * is skipped; the per-subject suggestion cap still applies;
53
+ * - the cluster lane runs BEFORE rules and never depends on a rule
54
+ * matching; a rule read that returns nothing changes nothing;
55
+ * - a failed access lookup skips the lane quietly;
56
+ * - the follow-up round ("ask again") is Suggest for Automatic and
57
+ * RequireApproval clusters, FullAuto again for BypassApproval clusters,
58
+ * and stops at MAX_CLUSTER_REMEDIATION_ROUNDS_PER_SUBJECT for all;
59
+ * - a BypassApproval cluster's rounds do not ask: round 1 and the follow-up
60
+ * are both FullAuto with auto-resolve, and the feed says approvals are
61
+ * bypassed — except for what always needs a human;
62
+ * - the feed states exactly what each round does, in the canonical mode
63
+ * terms: an Automatic round runs safe (and allowlisted) changes on its
64
+ * own and a riskier change never runs on its own — a round that finds
65
+ * only riskier fixes proposes exactly those for one-click approval (the
66
+ * execution runner settles a round that ran nothing but refused riskier
67
+ * changes as an approval card for exactly those), and after safe fixes
68
+ * a riskier one is proposed only if verification fails; in both
69
+ * unattended modes a protected-namespace write, a node drain and a node
70
+ * taint always need a human, and the round becomes a proposal when the
71
+ * breaker trips or another unattended round holds the cluster;
72
+ * - at most one UNATTENDED round per cluster at a time, whatever the
73
+ * subject: a round that would run unattended while another round on the
74
+ * same cluster is still running or verifying its fix is created asking
75
+ * first — the alert and the incident of one monitor never both change a
76
+ * cluster at once. A failed check asks first too;
77
+ * - a follow-up forced to ask (its predecessor's rollback did not complete)
78
+ * asks first even on a BypassApproval cluster, and says why;
79
+ * - the in-flight round check and the cluster-round name snapshot helpers
80
+ * classify exactly what they claim to.
81
+ */
82
+
83
+ const PROJECT_ID: ObjectID = new ObjectID(
84
+ "22222222-2222-4222-8222-222222222222",
85
+ );
86
+ const INCIDENT_ID: ObjectID = new ObjectID(
87
+ "cccccccc-cccc-4ccc-8ccc-cccccccccccc",
88
+ );
89
+ const ALERT_ID: ObjectID = new ObjectID("dddddddd-dddd-4ddd-8ddd-dddddddddddd");
90
+ const CLUSTER_ID: ObjectID = new ObjectID(
91
+ "33333333-3333-4333-8333-333333333333",
92
+ );
93
+ const SUGGESTION_ID: ObjectID = new ObjectID(
94
+ "77777777-7777-4777-8777-777777777777",
95
+ );
96
+ const AI_RUN_ID: ObjectID = new ObjectID(
97
+ "88888888-8888-4888-8888-888888888888",
98
+ );
99
+
100
+ function readyCluster(
101
+ overrides: Partial<KubernetesClusterAiAccessStatus> = {},
102
+ ): KubernetesClusterAiAccessStatus {
103
+ return {
104
+ clusterId: CLUSTER_ID.toString(),
105
+ clusterName: "prod-us",
106
+ runner: {
107
+ id: "44444444-4444-4444-8444-444444444444",
108
+ name: "kubernetes-agent/prod-us",
109
+ isOnline: true,
110
+ canRunAiCommands: true,
111
+ },
112
+ accessMethod: "in_cluster",
113
+ kubectlAllowlist: [],
114
+ isInvestigationEnabled: true,
115
+ isInvestigationReady: true,
116
+ remediationMode: KubernetesAiRemediationMode.Automatic,
117
+ isRemediationReady: true,
118
+ gaps: [],
119
+ evaluatedAt: new Date().toISOString(),
120
+ ...overrides,
121
+ };
122
+ }
123
+
124
+ function fakeIncident(): Incident {
125
+ return {
126
+ id: INCIDENT_ID,
127
+ _id: INCIDENT_ID.toString(),
128
+ projectId: PROJECT_ID,
129
+ title: "Pods stuck in Pending",
130
+ monitors: [],
131
+ labels: [],
132
+ } as unknown as Incident;
133
+ }
134
+
135
+ let createdSuggestions: Array<AutoRemediationSuggestion>;
136
+ let suggestionUpdates: Array<Record<string, unknown>>;
137
+ let enqueue: jest.SpyInstance;
138
+
139
+ function mockBaseline(data: {
140
+ existing?: Array<AutoRemediationSuggestion> | undefined;
141
+ statuses?: Array<KubernetesClusterAiAccessStatus> | undefined;
142
+ }): void {
143
+ createdSuggestions = [];
144
+ suggestionUpdates = [];
145
+
146
+ jest.spyOn(logger, "error").mockImplementation((): void => {
147
+ return undefined;
148
+ });
149
+ jest.spyOn(logger, "warn").mockImplementation((): void => {
150
+ return undefined;
151
+ });
152
+ jest.spyOn(logger, "debug").mockImplementation((): void => {
153
+ return undefined;
154
+ });
155
+ jest.spyOn(ProjectService, "findOneById").mockResolvedValue({
156
+ enableAi: true,
157
+ enableAutoRemediation: true,
158
+ enableAiCommandExecution: true,
159
+ } as unknown as Project);
160
+ jest
161
+ .spyOn(AutoRemediationSuggestionService, "findBy")
162
+ .mockResolvedValue(data.existing || []);
163
+ jest
164
+ .spyOn(AutoRemediationSuggestionService, "create")
165
+ .mockImplementation(
166
+ async (args: unknown): Promise<AutoRemediationSuggestion> => {
167
+ const suggestion: AutoRemediationSuggestion = (
168
+ args as { data: AutoRemediationSuggestion }
169
+ ).data;
170
+ suggestion.id = SUGGESTION_ID;
171
+ createdSuggestions.push(suggestion);
172
+ return suggestion;
173
+ },
174
+ );
175
+ jest
176
+ .spyOn(AutoRemediationSuggestionService, "updateOneById")
177
+ .mockImplementation(async (args: unknown): Promise<never> => {
178
+ suggestionUpdates.push((args as { data: Record<string, unknown> }).data);
179
+ return undefined as never;
180
+ });
181
+ jest
182
+ .spyOn(KubernetesClusterAiAccessService, "getStatusesForSubject")
183
+ .mockResolvedValue(data.statuses || [readyCluster()]);
184
+ enqueue = jest
185
+ .spyOn(AIInvestigationQueue, "enqueue")
186
+ .mockResolvedValue(AI_RUN_ID);
187
+ jest.spyOn(AutoRemediationRuleService, "findBy").mockResolvedValue([]);
188
+ jest
189
+ .spyOn(IncidentFeedService, "createIncidentFeedItem")
190
+ .mockResolvedValue(undefined as never);
191
+ jest
192
+ .spyOn(AlertFeedService, "createAlertFeedItem")
193
+ .mockResolvedValue(undefined as never);
194
+ /*
195
+ * The in-flight check also reads the AI kubectl jobs on the cluster (a
196
+ * rule-driven run that changed it holds it too): none unless a test
197
+ * says otherwise.
198
+ */
199
+ jest.spyOn(RunnerJobService, "findBy").mockResolvedValue([]);
200
+ }
201
+
202
+ describe("AutoRemediationRuleEngineService cluster-level remediation", () => {
203
+ afterEach(() => {
204
+ jest.restoreAllMocks();
205
+ });
206
+
207
+ it("starts a FullAuto command run for an Automatic cluster with no rule involved", async () => {
208
+ mockBaseline({});
209
+
210
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
211
+
212
+ expect(createdSuggestions).toHaveLength(1);
213
+ const suggestion: AutoRemediationSuggestion = createdSuggestions[0]!;
214
+ expect(suggestion.kubernetesClusterId?.toString()).toBe(
215
+ CLUSTER_ID.toString(),
216
+ );
217
+ expect(suggestion.autoRemediationRuleId).toBeUndefined();
218
+ expect(suggestion.status).toBe(AutoRemediationSuggestionStatus.Planning);
219
+ expect(suggestion.suggestionType).toBe(
220
+ AutoRemediationSuggestionType.CommandPlan,
221
+ );
222
+ expect(suggestion.executionMode).toBe(
223
+ AutoRemediationExecutionMode.FullAuto,
224
+ );
225
+ expect(suggestion.autoResolveOnRecovery).toBe(true);
226
+ expect(suggestion.verificationWindowMinutes).toBe(
227
+ DEFAULT_VERIFICATION_WINDOW_MINUTES,
228
+ );
229
+ expect(suggestion.ruleNameSnapshot).toBe(
230
+ 'AI remediation for cluster "prod-us"',
231
+ );
232
+ expect(suggestion.incidentId?.toString()).toBe(INCIDENT_ID.toString());
233
+
234
+ expect(enqueue).toHaveBeenCalledTimes(1);
235
+ expect(enqueue.mock.calls[0]![0]).toMatchObject({
236
+ projectId: PROJECT_ID,
237
+ subjectIncidentId: INCIDENT_ID,
238
+ subjectAutoRemediationSuggestionId: SUGGESTION_ID,
239
+ remediationRunType: AIRunType.RemediationExecution,
240
+ });
241
+ expect(suggestionUpdates).toContainEqual({ aiRunId: AI_RUN_ID });
242
+ expect(IncidentFeedService.createIncidentFeedItem).toHaveBeenCalledTimes(1);
243
+ });
244
+
245
+ it("starts a Suggest run without auto-resolve for a RequireApproval cluster, on an alert", async () => {
246
+ mockBaseline({
247
+ statuses: [
248
+ readyCluster({
249
+ remediationMode: KubernetesAiRemediationMode.RequireApproval,
250
+ }),
251
+ ],
252
+ });
253
+
254
+ await AutoRemediationRuleEngineService.applyRulesToAlert({
255
+ id: ALERT_ID,
256
+ _id: ALERT_ID.toString(),
257
+ projectId: PROJECT_ID,
258
+ title: "Pods stuck in Pending",
259
+ } as unknown as Alert);
260
+
261
+ expect(createdSuggestions).toHaveLength(1);
262
+ expect(createdSuggestions[0]!.executionMode).toBe(
263
+ AutoRemediationExecutionMode.Suggest,
264
+ );
265
+ expect(createdSuggestions[0]!.autoResolveOnRecovery).toBe(false);
266
+ expect(createdSuggestions[0]!.alertId?.toString()).toBe(
267
+ ALERT_ID.toString(),
268
+ );
269
+ expect(enqueue.mock.calls[0]![0]).toMatchObject({
270
+ subjectAlertId: ALERT_ID,
271
+ });
272
+ expect(AlertFeedService.createAlertFeedItem).toHaveBeenCalledTimes(1);
273
+ });
274
+
275
+ it("starts a FullAuto run with auto-resolve for a BypassApproval cluster and says approvals are bypassed", async () => {
276
+ mockBaseline({
277
+ statuses: [
278
+ readyCluster({
279
+ remediationMode: KubernetesAiRemediationMode.BypassApproval,
280
+ }),
281
+ ],
282
+ });
283
+
284
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
285
+
286
+ expect(createdSuggestions).toHaveLength(1);
287
+ expect(createdSuggestions[0]!.executionMode).toBe(
288
+ AutoRemediationExecutionMode.FullAuto,
289
+ );
290
+ expect(createdSuggestions[0]!.autoResolveOnRecovery).toBe(true);
291
+ expect(createdSuggestions[0]!.ruleNameSnapshot).toBe(
292
+ 'AI remediation for cluster "prod-us"',
293
+ );
294
+ expect(enqueue).toHaveBeenCalledTimes(1);
295
+
296
+ const feed: jest.SpyInstance =
297
+ IncidentFeedService.createIncidentFeedItem as unknown as jest.SpyInstance;
298
+ expect(feed).toHaveBeenCalledTimes(1);
299
+ const markdown: string = (
300
+ feed.mock.calls[0]![0] as { feedInfoInMarkdown: string }
301
+ ).feedInfoInMarkdown;
302
+ expect(markdown).toContain("Approvals are bypassed");
303
+ expect(markdown).not.toContain("riskier changes will ask");
304
+ expect(markdown).not.toContain("for approval");
305
+ });
306
+
307
+ it("skips a cluster that is not remediation-ready", async () => {
308
+ mockBaseline({
309
+ statuses: [readyCluster({ isRemediationReady: false })],
310
+ });
311
+
312
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
313
+
314
+ expect(createdSuggestions).toHaveLength(0);
315
+ expect(enqueue).not.toHaveBeenCalled();
316
+ });
317
+
318
+ it("does not start a second round for a cluster that already has a suggestion on this subject", async () => {
319
+ mockBaseline({
320
+ existing: [
321
+ {
322
+ id: SUGGESTION_ID,
323
+ _id: SUGGESTION_ID.toString(),
324
+ kubernetesClusterId: CLUSTER_ID,
325
+ } as unknown as AutoRemediationSuggestion,
326
+ ],
327
+ });
328
+
329
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
330
+
331
+ expect(createdSuggestions).toHaveLength(0);
332
+ });
333
+
334
+ it("respects the per-subject suggestion cap", async () => {
335
+ const existing: Array<AutoRemediationSuggestion> = [];
336
+ for (let i: number = 0; i < MAX_SUGGESTIONS_PER_SUBJECT; i++) {
337
+ existing.push({
338
+ id: ObjectID.generate(),
339
+ _id: ObjectID.generate().toString(),
340
+ } as unknown as AutoRemediationSuggestion);
341
+ }
342
+ mockBaseline({ existing });
343
+
344
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
345
+
346
+ expect(createdSuggestions).toHaveLength(0);
347
+ expect(AutoRemediationRuleService.findBy).not.toHaveBeenCalled();
348
+ });
349
+
350
+ it("settles the suggestion as NoneApplicable when the run cannot be queued", async () => {
351
+ mockBaseline({});
352
+ enqueue.mockResolvedValue(null);
353
+
354
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
355
+
356
+ expect(createdSuggestions).toHaveLength(1);
357
+ expect(suggestionUpdates[0]).toMatchObject({
358
+ status: AutoRemediationSuggestionStatus.NoneApplicable,
359
+ });
360
+ });
361
+
362
+ it("skips the lane quietly when the access lookup fails and still evaluates rules", async () => {
363
+ mockBaseline({});
364
+ (
365
+ KubernetesClusterAiAccessService.getStatusesForSubject as unknown as jest.SpyInstance
366
+ ).mockRejectedValue(new Error("db down"));
367
+
368
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
369
+
370
+ expect(createdSuggestions).toHaveLength(0);
371
+ expect(AutoRemediationRuleService.findBy).toHaveBeenCalledTimes(1);
372
+ });
373
+ });
374
+
375
+ describe("AutoRemediationRuleEngineService.startFollowUpClusterRemediation", () => {
376
+ let getStatusForCluster: jest.SpyInstance;
377
+
378
+ beforeEach(() => {
379
+ mockBaseline({});
380
+ getStatusForCluster = jest
381
+ .spyOn(KubernetesClusterAiAccessService, "getStatusForCluster")
382
+ .mockResolvedValue(readyCluster());
383
+ });
384
+
385
+ afterEach(() => {
386
+ jest.restoreAllMocks();
387
+ });
388
+
389
+ it("starts a Suggest round even on an Automatic cluster and labels it as round 2", async () => {
390
+ jest
391
+ .spyOn(AutoRemediationSuggestionService, "countBy")
392
+ .mockResolvedValue(new PositiveNumber(1));
393
+
394
+ const started: boolean =
395
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
396
+ projectId: PROJECT_ID,
397
+ kubernetesClusterId: CLUSTER_ID,
398
+ incidentId: INCIDENT_ID,
399
+ });
400
+
401
+ expect(started).toBe(true);
402
+ expect(createdSuggestions).toHaveLength(1);
403
+ expect(createdSuggestions[0]!.executionMode).toBe(
404
+ AutoRemediationExecutionMode.Suggest,
405
+ );
406
+ expect(createdSuggestions[0]!.autoResolveOnRecovery).toBe(false);
407
+ expect(createdSuggestions[0]!.ruleNameSnapshot).toContain("round 2");
408
+ expect(enqueue).toHaveBeenCalledTimes(1);
409
+ });
410
+
411
+ it("runs the follow-up round unattended again on a BypassApproval cluster", async () => {
412
+ jest
413
+ .spyOn(AutoRemediationSuggestionService, "countBy")
414
+ .mockResolvedValue(new PositiveNumber(1));
415
+ getStatusForCluster.mockResolvedValue(
416
+ readyCluster({
417
+ remediationMode: KubernetesAiRemediationMode.BypassApproval,
418
+ }),
419
+ );
420
+
421
+ const started: boolean =
422
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
423
+ projectId: PROJECT_ID,
424
+ kubernetesClusterId: CLUSTER_ID,
425
+ incidentId: INCIDENT_ID,
426
+ });
427
+
428
+ expect(started).toBe(true);
429
+ expect(createdSuggestions).toHaveLength(1);
430
+ expect(createdSuggestions[0]!.executionMode).toBe(
431
+ AutoRemediationExecutionMode.FullAuto,
432
+ );
433
+ expect(createdSuggestions[0]!.autoResolveOnRecovery).toBe(true);
434
+ expect(createdSuggestions[0]!.ruleNameSnapshot).toContain("round 2");
435
+
436
+ const markdown: string = (
437
+ (
438
+ IncidentFeedService.createIncidentFeedItem as unknown as jest.SpyInstance
439
+ ).mock.calls[0]![0] as { feedInfoInMarkdown: string }
440
+ ).feedInfoInMarkdown;
441
+ expect(markdown).toContain("round 2");
442
+ expect(markdown).toContain("Approvals are bypassed");
443
+ expect(markdown).not.toContain("for approval");
444
+ });
445
+
446
+ it("still stops the BypassApproval follow-up at the round cap", async () => {
447
+ jest
448
+ .spyOn(AutoRemediationSuggestionService, "countBy")
449
+ .mockResolvedValue(
450
+ new PositiveNumber(MAX_CLUSTER_REMEDIATION_ROUNDS_PER_SUBJECT),
451
+ );
452
+ getStatusForCluster.mockResolvedValue(
453
+ readyCluster({
454
+ remediationMode: KubernetesAiRemediationMode.BypassApproval,
455
+ }),
456
+ );
457
+
458
+ expect(
459
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
460
+ projectId: PROJECT_ID,
461
+ kubernetesClusterId: CLUSTER_ID,
462
+ incidentId: INCIDENT_ID,
463
+ }),
464
+ ).toBe(false);
465
+ expect(createdSuggestions).toHaveLength(0);
466
+ });
467
+
468
+ it("stops asking once the round cap is spent", async () => {
469
+ jest
470
+ .spyOn(AutoRemediationSuggestionService, "countBy")
471
+ .mockResolvedValue(
472
+ new PositiveNumber(MAX_CLUSTER_REMEDIATION_ROUNDS_PER_SUBJECT),
473
+ );
474
+
475
+ const started: boolean =
476
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
477
+ projectId: PROJECT_ID,
478
+ kubernetesClusterId: CLUSTER_ID,
479
+ incidentId: INCIDENT_ID,
480
+ });
481
+
482
+ expect(started).toBe(false);
483
+ expect(createdSuggestions).toHaveLength(0);
484
+ expect(getStatusForCluster).not.toHaveBeenCalled();
485
+ });
486
+
487
+ it("does nothing when the cluster is no longer ready or auto-remediation is off", async () => {
488
+ jest
489
+ .spyOn(AutoRemediationSuggestionService, "countBy")
490
+ .mockResolvedValue(new PositiveNumber(1));
491
+ getStatusForCluster.mockResolvedValue(
492
+ readyCluster({ isRemediationReady: false }),
493
+ );
494
+
495
+ expect(
496
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
497
+ projectId: PROJECT_ID,
498
+ kubernetesClusterId: CLUSTER_ID,
499
+ alertId: ALERT_ID,
500
+ }),
501
+ ).toBe(false);
502
+
503
+ (
504
+ ProjectService.findOneById as unknown as jest.SpyInstance
505
+ ).mockResolvedValue({ enableAutoRemediation: false } as unknown as Project);
506
+
507
+ expect(
508
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
509
+ projectId: PROJECT_ID,
510
+ kubernetesClusterId: CLUSTER_ID,
511
+ alertId: ALERT_ID,
512
+ }),
513
+ ).toBe(false);
514
+
515
+ expect(createdSuggestions).toHaveLength(0);
516
+ });
517
+ });
518
+
519
+ describe("AutoRemediationRuleEngineService cluster feed copy states exactly what each round does", () => {
520
+ afterEach(() => {
521
+ jest.restoreAllMocks();
522
+ });
523
+
524
+ function incidentFeedMarkdown(): string {
525
+ const feed: jest.SpyInstance =
526
+ IncidentFeedService.createIncidentFeedItem as unknown as jest.SpyInstance;
527
+ expect(feed).toHaveBeenCalledTimes(1);
528
+ return (feed.mock.calls[0]![0] as { feedInfoInMarkdown: string })
529
+ .feedInfoInMarkdown;
530
+ }
531
+
532
+ async function followUp(mode: KubernetesAiRemediationMode): Promise<string> {
533
+ mockBaseline({});
534
+ jest
535
+ .spyOn(AutoRemediationSuggestionService, "countBy")
536
+ .mockResolvedValue(new PositiveNumber(1));
537
+ jest
538
+ .spyOn(KubernetesClusterAiAccessService, "getStatusForCluster")
539
+ .mockResolvedValue(readyCluster({ remediationMode: mode }));
540
+
541
+ expect(
542
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
543
+ projectId: PROJECT_ID,
544
+ kubernetesClusterId: CLUSTER_ID,
545
+ incidentId: INCIDENT_ID,
546
+ }),
547
+ ).toBe(true);
548
+
549
+ return incidentFeedMarkdown();
550
+ }
551
+
552
+ it("Automatic, round 1: safe changes run on their own; a riskier change never runs on its own — it is proposed for one-click approval", async () => {
553
+ /*
554
+ * Changed with the "Automatic proposes the riskier fix" fix: this copy
555
+ * used to say a riskier change is "neither run nor proposed in this
556
+ * round". A round that ran nothing but refused a riskier change now
557
+ * ends as an approval card for it, so the copy promises exactly that.
558
+ */
559
+ mockBaseline({
560
+ statuses: [
561
+ readyCluster({
562
+ remediationMode: KubernetesAiRemediationMode.Automatic,
563
+ }),
564
+ ],
565
+ });
566
+
567
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
568
+
569
+ const markdown: string = incidentFeedMarkdown();
570
+ expect(markdown).toContain("Automatic remediation is on for this cluster");
571
+ expect(markdown).toContain("on its own");
572
+ /*
573
+ * The shared SafeWrite wording (PR #3953 round-two review): one named
574
+ * object, and never "delete a named pod or job" — deleting a job is a
575
+ * riskier change.
576
+ */
577
+ expect(markdown).toContain(KUBECTL_SAFE_CHANGES_SUMMARY);
578
+ expect(markdown).not.toContain("pod or job");
579
+ expect(markdown).toContain("cluster's kubectl allowlist");
580
+ expect(markdown).toContain("A riskier change never runs on its own");
581
+ /*
582
+ * Changed in the round-three review: "AI proposes it for your one-click
583
+ * approval instead" was unconditional. The canonical Automatic
584
+ * semantics have two cases — a round that finds only riskier fixes
585
+ * proposes exactly those; after safe fixes, a riskier one is proposed
586
+ * only if verification shows the service did not recover — and the
587
+ * every-mode rules (a protected-namespace write, a node drain and a
588
+ * node taint always need a human; the breaker or another round's hold
589
+ * turns the round into a proposal) apply to Automatic too.
590
+ */
591
+ expect(markdown).toContain(
592
+ "if the round finds only riskier fixes, AI proposes exactly those for your one-click approval",
593
+ );
594
+ expect(markdown).toContain(
595
+ "a riskier fix is proposed only if verification shows the service did not recover",
596
+ );
597
+ expect(markdown).toContain(
598
+ "riskier changes whose shape the cluster's kubectl allowlist names",
599
+ );
600
+ expect(markdown.toLowerCase()).toContain(
601
+ KUBECTL_ALWAYS_ASKS_SUMMARY.toLowerCase(),
602
+ );
603
+ expect(markdown).toMatch(TAINT_WORD_PATTERN);
604
+ expect(markdown).toContain("hourly circuit breaker for this cluster trips");
605
+ expect(markdown).toContain(
606
+ "another unattended OneUptime AI round already holds the cluster",
607
+ );
608
+ expect(markdown).toContain("destructive commands never run");
609
+ expect(markdown).not.toContain("proposes it for your one-click approval");
610
+ expect(markdown).not.toContain("neither run nor proposed");
611
+ expect(markdown).not.toContain("asks first");
612
+ expect(markdown).not.toContain("bypassed");
613
+ });
614
+
615
+ it("Automatic, round 2: the follow-up asks first — nothing runs until the new plan is approved", async () => {
616
+ const markdown: string = await followUp(
617
+ KubernetesAiRemediationMode.Automatic,
618
+ );
619
+
620
+ expect(markdown).toContain("round 2");
621
+ expect(markdown).toContain("did not recover the service");
622
+ expect(markdown).toContain("nothing runs until you approve the new plan");
623
+ expect(markdown).not.toContain("on its own");
624
+ expect(markdown).not.toContain("recommendations");
625
+ });
626
+
627
+ it("RequireApproval, round 1: nothing runs until the plan is approved", async () => {
628
+ mockBaseline({
629
+ statuses: [
630
+ readyCluster({
631
+ remediationMode: KubernetesAiRemediationMode.RequireApproval,
632
+ }),
633
+ ],
634
+ });
635
+
636
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
637
+
638
+ const markdown: string = incidentFeedMarkdown();
639
+ expect(markdown).toContain("composing a kubectl fix");
640
+ expect(markdown).toContain("Nothing runs until you approve the plan");
641
+ expect(markdown).not.toContain("on its own");
642
+ });
643
+
644
+ it("RequireApproval, round 2: the follow-up asks again", async () => {
645
+ const markdown: string = await followUp(
646
+ KubernetesAiRemediationMode.RequireApproval,
647
+ );
648
+
649
+ expect(markdown).toContain("round 2");
650
+ expect(markdown).toContain("nothing runs until you approve the new plan");
651
+ expect(markdown).not.toContain("on its own");
652
+ });
653
+
654
+ it("BypassApproval, round 1 and 2: every allowed change runs on its own, riskier ones included, destructive never", async () => {
655
+ mockBaseline({
656
+ statuses: [
657
+ readyCluster({
658
+ remediationMode: KubernetesAiRemediationMode.BypassApproval,
659
+ }),
660
+ ],
661
+ });
662
+
663
+ await AutoRemediationRuleEngineService.applyRulesToIncident(fakeIncident());
664
+
665
+ const first: string = incidentFeedMarkdown();
666
+ expect(first).toContain("Approvals are bypassed for this cluster");
667
+ expect(first).toContain("safe or riskier");
668
+ expect(first).toContain("without asking");
669
+ expect(first).toContain("destructive commands never run");
670
+ // Bypass approval still asks for what needs a human in every mode.
671
+ expect(first).toContain(KUBECTL_ALWAYS_ASKS_SUMMARY);
672
+ expect(first).toMatch(TAINT_WORD_PATTERN);
673
+ /*
674
+ * ...and a Bypass round still becomes a proposal when the breaker trips
675
+ * or another unattended round holds the cluster (the canonical
676
+ * KubernetesAiRemediationMode comment's Bypass exceptions).
677
+ */
678
+ expect(first).toContain("hourly circuit breaker for this cluster trips");
679
+ expect(first).toContain(
680
+ "another unattended OneUptime AI round already holds the cluster",
681
+ );
682
+ expect(first).toContain("this round becomes a proposal");
683
+ expect(first).not.toContain("approve");
684
+ expect(first).not.toContain("recommendations");
685
+
686
+ jest.restoreAllMocks();
687
+
688
+ const second: string = await followUp(
689
+ KubernetesAiRemediationMode.BypassApproval,
690
+ );
691
+ expect(second).toContain("round 2");
692
+ expect(second).toContain("runs on its own");
693
+ expect(second).toContain("safe or riskier");
694
+ expect(second).toContain("destructive commands never run");
695
+ expect(second).toContain(KUBECTL_ALWAYS_ASKS_SUMMARY);
696
+ expect(second).toContain("this round becomes a proposal");
697
+ expect(second).not.toContain("approve");
698
+ });
699
+ });
700
+
701
+ /*
702
+ * The other rounds on the cluster, as the in-flight round check reads them
703
+ * (its query names the cluster; the per-subject dedupe's does not).
704
+ */
705
+ function mockRoundsOnCluster(
706
+ rows: Array<Record<string, unknown>>,
707
+ existing: Array<AutoRemediationSuggestion> = [],
708
+ ): jest.SpyInstance {
709
+ return (
710
+ AutoRemediationSuggestionService.findBy as unknown as jest.SpyInstance
711
+ ).mockImplementation(
712
+ async (args: unknown): Promise<Array<AutoRemediationSuggestion>> => {
713
+ const query: Record<string, unknown> =
714
+ (args as { query?: Record<string, unknown> }).query || {};
715
+ return (query["kubernetesClusterId"]
716
+ ? rows
717
+ : existing) as unknown as Array<AutoRemediationSuggestion>;
718
+ },
719
+ );
720
+ }
721
+
722
+ function roundOnCluster(
723
+ overrides: Record<string, unknown> = {},
724
+ ): Record<string, unknown> {
725
+ const id: ObjectID = ObjectID.generate();
726
+ return {
727
+ id,
728
+ _id: id.toString(),
729
+ status: AutoRemediationSuggestionStatus.AutoExecuted,
730
+ executionMode: AutoRemediationExecutionMode.FullAuto,
731
+ verificationStatus: AutoRemediationVerificationStatus.Pending,
732
+ verificationDeadlineAt: new Date(Date.now() + 10 * 60 * 1000),
733
+ incidentId: INCIDENT_ID,
734
+ ruleNameSnapshot: 'AI remediation for cluster "prod-us"',
735
+ createdAt: new Date(Date.now() - 5 * 60 * 1000),
736
+ ...overrides,
737
+ };
738
+ }
739
+
740
+ describe("AutoRemediationRuleEngineService — one unattended round per cluster at a time", () => {
741
+ afterEach(() => {
742
+ jest.restoreAllMocks();
743
+ });
744
+
745
+ async function startAlertRound(): Promise<string> {
746
+ await AutoRemediationRuleEngineService.applyRulesToAlert({
747
+ id: ALERT_ID,
748
+ _id: ALERT_ID.toString(),
749
+ projectId: PROJECT_ID,
750
+ title: "Pods stuck in Pending",
751
+ } as unknown as Alert);
752
+
753
+ const feed: jest.SpyInstance =
754
+ AlertFeedService.createAlertFeedItem as unknown as jest.SpyInstance;
755
+ expect(feed).toHaveBeenCalledTimes(1);
756
+ return (feed.mock.calls[0]![0] as { feedInfoInMarkdown: string })
757
+ .feedInfoInMarkdown;
758
+ }
759
+
760
+ it("creates the alert's round ASKING FIRST while the incident's round on the same cluster is still being verified — the alert and the incident of one monitor", async () => {
761
+ mockBaseline({});
762
+ const holdRead: jest.SpyInstance = mockRoundsOnCluster([roundOnCluster()]);
763
+
764
+ const markdown: string = await startAlertRound();
765
+
766
+ expect(createdSuggestions).toHaveLength(1);
767
+ expect(createdSuggestions[0]!.executionMode).toBe(
768
+ AutoRemediationExecutionMode.Suggest,
769
+ );
770
+ expect(createdSuggestions[0]!.autoResolveOnRecovery).toBe(false);
771
+ expect(markdown).toContain(
772
+ "This round asks first because another OneUptime AI round on this cluster applied a fix that is still being verified",
773
+ );
774
+ expect(markdown).toContain("nothing runs until you approve the plan");
775
+ expect(markdown).not.toContain("on its own");
776
+
777
+ // The check read this cluster, in this project, across subjects.
778
+ const query: Record<string, unknown> = (
779
+ holdRead.mock.calls.find((call: Array<unknown>) => {
780
+ return Boolean(
781
+ (call[0] as { query: Record<string, unknown> }).query[
782
+ "kubernetesClusterId"
783
+ ],
784
+ );
785
+ })![0] as { query: Record<string, unknown> }
786
+ ).query;
787
+ expect((query["kubernetesClusterId"] as ObjectID).toString()).toBe(
788
+ CLUSTER_ID.toString(),
789
+ );
790
+ expect((query["projectId"] as ObjectID).toString()).toBe(
791
+ PROJECT_ID.toString(),
792
+ );
793
+ expect(query["incidentId"]).toBeUndefined();
794
+ expect(query["alertId"]).toBeUndefined();
795
+ });
796
+
797
+ it("asks first while another round on the cluster is still running unattended — on a BypassApproval cluster too", async () => {
798
+ mockBaseline({
799
+ statuses: [
800
+ readyCluster({
801
+ remediationMode: KubernetesAiRemediationMode.BypassApproval,
802
+ }),
803
+ ],
804
+ });
805
+ mockRoundsOnCluster([
806
+ roundOnCluster({
807
+ status: AutoRemediationSuggestionStatus.Planning,
808
+ verificationStatus: undefined,
809
+ verificationDeadlineAt: undefined,
810
+ createdAt: new Date(Date.now() - 60 * 1000),
811
+ }),
812
+ ]);
813
+
814
+ const markdown: string = await startAlertRound();
815
+
816
+ expect(createdSuggestions[0]!.executionMode).toBe(
817
+ AutoRemediationExecutionMode.Suggest,
818
+ );
819
+ expect(markdown).toContain("is still running unattended");
820
+ expect(markdown).not.toContain("Approvals are bypassed");
821
+ });
822
+
823
+ it("creates the alert's round ASKING FIRST while a rule-driven run on the monitor's incident still has its fix on the cluster under verification", async () => {
824
+ mockBaseline({});
825
+ const ruleRunId: ObjectID = ObjectID.generate();
826
+ (
827
+ AutoRemediationSuggestionService.findBy as unknown as jest.SpyInstance
828
+ ).mockImplementation(
829
+ async (args: unknown): Promise<Array<AutoRemediationSuggestion>> => {
830
+ const query: Record<string, unknown> =
831
+ (args as { query?: Record<string, unknown> }).query || {};
832
+ if (!query["_id"]) {
833
+ return [];
834
+ }
835
+ return [
836
+ {
837
+ id: ruleRunId,
838
+ _id: ruleRunId.toString(),
839
+ status: AutoRemediationSuggestionStatus.AutoExecuted,
840
+ executionMode: AutoRemediationExecutionMode.FullAuto,
841
+ verificationStatus: AutoRemediationVerificationStatus.Pending,
842
+ verificationDeadlineAt: new Date(Date.now() + 10 * 60 * 1000),
843
+ incidentId: INCIDENT_ID,
844
+ ruleNameSnapshot: "Restart web on 5xx",
845
+ createdAt: new Date(Date.now() - 5 * 60 * 1000),
846
+ },
847
+ ] as unknown as Array<AutoRemediationSuggestion>;
848
+ },
849
+ );
850
+ (RunnerJobService.findBy as unknown as jest.SpyInstance).mockResolvedValue([
851
+ {
852
+ id: ObjectID.generate(),
853
+ autoRemediationSuggestionId: ruleRunId,
854
+ stepId: "ai-command-1",
855
+ } as unknown as RunnerJob,
856
+ ]);
857
+
858
+ const markdown: string = await startAlertRound();
859
+
860
+ expect(createdSuggestions[0]!.executionMode).toBe(
861
+ AutoRemediationExecutionMode.Suggest,
862
+ );
863
+ expect(markdown).toContain(
864
+ "This round asks first because another OneUptime AI round on this cluster applied a fix that is still being verified",
865
+ );
866
+ });
867
+
868
+ it("negative control: with no rule-driven kubectl job on the cluster the alert's round runs unattended", async () => {
869
+ mockBaseline({});
870
+
871
+ const markdown: string = await startAlertRound();
872
+
873
+ expect(createdSuggestions[0]!.executionMode).toBe(
874
+ AutoRemediationExecutionMode.FullAuto,
875
+ );
876
+ expect(markdown).toContain("Automatic remediation is on for this cluster");
877
+ });
878
+
879
+ it("asks first when the in-flight round check itself fails", async () => {
880
+ mockBaseline({});
881
+ (
882
+ AutoRemediationSuggestionService.findBy as unknown as jest.SpyInstance
883
+ ).mockImplementation(
884
+ async (args: unknown): Promise<Array<AutoRemediationSuggestion>> => {
885
+ const query: Record<string, unknown> =
886
+ (args as { query?: Record<string, unknown> }).query || {};
887
+ if (query["kubernetesClusterId"]) {
888
+ throw new Error("db down");
889
+ }
890
+ return [];
891
+ },
892
+ );
893
+
894
+ const markdown: string = await startAlertRound();
895
+
896
+ expect(createdSuggestions[0]!.executionMode).toBe(
897
+ AutoRemediationExecutionMode.Suggest,
898
+ );
899
+ expect(markdown).toContain(
900
+ "OneUptime AI could not confirm that no other AI round is changing this cluster",
901
+ );
902
+ });
903
+
904
+ it.each([
905
+ [
906
+ "a verified fix",
907
+ {
908
+ verificationStatus: AutoRemediationVerificationStatus.Verified,
909
+ },
910
+ ],
911
+ [
912
+ "a fix whose verification deadline passed long ago (the verifier is not running)",
913
+ {
914
+ verificationDeadlineAt: new Date(Date.now() - 60 * 60 * 1000),
915
+ },
916
+ ],
917
+ [
918
+ "a round stuck in Planning for hours",
919
+ {
920
+ status: AutoRemediationSuggestionStatus.Planning,
921
+ verificationStatus: undefined,
922
+ createdAt: new Date(Date.now() - 3 * 60 * 60 * 1000),
923
+ },
924
+ ],
925
+ [
926
+ "a round that only asks",
927
+ {
928
+ status: AutoRemediationSuggestionStatus.Planning,
929
+ executionMode: AutoRemediationExecutionMode.Suggest,
930
+ verificationStatus: undefined,
931
+ },
932
+ ],
933
+ ])(
934
+ "negative control: %s does not hold the cluster — the round runs unattended as its mode says",
935
+ async (_label: string, overrides: Record<string, unknown>) => {
936
+ mockBaseline({});
937
+ mockRoundsOnCluster([roundOnCluster(overrides)]);
938
+
939
+ const markdown: string = await startAlertRound();
940
+
941
+ expect(createdSuggestions[0]!.executionMode).toBe(
942
+ AutoRemediationExecutionMode.FullAuto,
943
+ );
944
+ expect(createdSuggestions[0]!.autoResolveOnRecovery).toBe(true);
945
+ expect(markdown).toContain(
946
+ "Automatic remediation is on for this cluster",
947
+ );
948
+ },
949
+ );
950
+
951
+ it("negative control: a cluster that asks for approval never needs the check — its round asks anyway", async () => {
952
+ mockBaseline({
953
+ statuses: [
954
+ readyCluster({
955
+ remediationMode: KubernetesAiRemediationMode.RequireApproval,
956
+ }),
957
+ ],
958
+ });
959
+ const holdRead: jest.SpyInstance = mockRoundsOnCluster([roundOnCluster()]);
960
+
961
+ await startAlertRound();
962
+
963
+ expect(createdSuggestions[0]!.executionMode).toBe(
964
+ AutoRemediationExecutionMode.Suggest,
965
+ );
966
+ expect(
967
+ holdRead.mock.calls.some((call: Array<unknown>) => {
968
+ return Boolean(
969
+ (call[0] as { query: Record<string, unknown> }).query[
970
+ "kubernetesClusterId"
971
+ ],
972
+ );
973
+ }),
974
+ ).toBe(false);
975
+ });
976
+ });
977
+
978
+ describe("AutoRemediationRuleEngineService.startFollowUpClusterRemediation — forced to ask first", () => {
979
+ beforeEach(() => {
980
+ mockBaseline({});
981
+ jest
982
+ .spyOn(AutoRemediationSuggestionService, "countBy")
983
+ .mockResolvedValue(new PositiveNumber(1));
984
+ jest
985
+ .spyOn(KubernetesClusterAiAccessService, "getStatusForCluster")
986
+ .mockResolvedValue(
987
+ readyCluster({
988
+ remediationMode: KubernetesAiRemediationMode.BypassApproval,
989
+ }),
990
+ );
991
+ });
992
+
993
+ afterEach(() => {
994
+ jest.restoreAllMocks();
995
+ });
996
+
997
+ it("asks first on a BypassApproval cluster when the previous round's rollback did not complete, and says why", async () => {
998
+ const started: boolean =
999
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
1000
+ projectId: PROJECT_ID,
1001
+ kubernetesClusterId: CLUSTER_ID,
1002
+ incidentId: INCIDENT_ID,
1003
+ forceSuggest: true,
1004
+ });
1005
+
1006
+ expect(started).toBe(true);
1007
+ expect(createdSuggestions[0]!.executionMode).toBe(
1008
+ AutoRemediationExecutionMode.Suggest,
1009
+ );
1010
+ expect(createdSuggestions[0]!.autoResolveOnRecovery).toBe(false);
1011
+ expect(createdSuggestions[0]!.ruleNameSnapshot).toContain("round 2");
1012
+
1013
+ const markdown: string = (
1014
+ (
1015
+ IncidentFeedService.createIncidentFeedItem as unknown as jest.SpyInstance
1016
+ ).mock.calls[0]![0] as { feedInfoInMarkdown: string }
1017
+ ).feedInfoInMarkdown;
1018
+ expect(markdown).toContain("round 2");
1019
+ expect(markdown).toContain(
1020
+ "This round asks first because the previous fix's rollback did not complete",
1021
+ );
1022
+ expect(markdown).not.toContain("Approvals are bypassed");
1023
+ });
1024
+
1025
+ it("uses the reason it was given", async () => {
1026
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
1027
+ projectId: PROJECT_ID,
1028
+ kubernetesClusterId: CLUSTER_ID,
1029
+ incidentId: INCIDENT_ID,
1030
+ forceSuggest: true,
1031
+ forceSuggestReason: "a human must look first",
1032
+ });
1033
+
1034
+ const markdown: string = (
1035
+ (
1036
+ IncidentFeedService.createIncidentFeedItem as unknown as jest.SpyInstance
1037
+ ).mock.calls[0]![0] as { feedInfoInMarkdown: string }
1038
+ ).feedInfoInMarkdown;
1039
+ expect(markdown).toContain("asks first because a human must look first");
1040
+ });
1041
+
1042
+ it("negative control: without forceSuggest the BypassApproval follow-up runs unattended, as before", async () => {
1043
+ await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
1044
+ projectId: PROJECT_ID,
1045
+ kubernetesClusterId: CLUSTER_ID,
1046
+ incidentId: INCIDENT_ID,
1047
+ });
1048
+
1049
+ expect(createdSuggestions[0]!.executionMode).toBe(
1050
+ AutoRemediationExecutionMode.FullAuto,
1051
+ );
1052
+ expect(createdSuggestions[0]!.autoResolveOnRecovery).toBe(true);
1053
+ });
1054
+ });
1055
+
1056
+ describe("AutoRemediationRuleEngineService.findRoundHoldingCluster", () => {
1057
+ const MINE: ObjectID = new ObjectID("12121212-1212-4212-8212-121212121212");
1058
+ const NOW: number = Date.now();
1059
+
1060
+ afterEach(() => {
1061
+ jest.restoreAllMocks();
1062
+ });
1063
+
1064
+ function holding(
1065
+ rows: Array<Record<string, unknown>>,
1066
+ data: {
1067
+ anyOrder?: boolean;
1068
+ subject?: { incidentId?: ObjectID; alertId?: ObjectID };
1069
+ } = {},
1070
+ ): Promise<ClusterRoundHold | null> {
1071
+ jest
1072
+ .spyOn(AutoRemediationSuggestionService, "findBy")
1073
+ .mockResolvedValue(rows as unknown as Array<AutoRemediationSuggestion>);
1074
+ jest.spyOn(RunnerJobService, "findBy").mockResolvedValue([]);
1075
+ return AutoRemediationRuleEngineService.findRoundHoldingCluster({
1076
+ projectId: PROJECT_ID,
1077
+ clusterId: CLUSTER_ID.toString(),
1078
+ forRound: { suggestionId: MINE, createdAt: new Date(NOW - 1000) },
1079
+ ...data,
1080
+ });
1081
+ }
1082
+
1083
+ it("never holds a cluster against the round itself", async () => {
1084
+ expect(
1085
+ await holding([
1086
+ roundOnCluster({
1087
+ id: MINE,
1088
+ _id: MINE.toString(),
1089
+ status: AutoRemediationSuggestionStatus.Planning,
1090
+ }),
1091
+ ]),
1092
+ ).toBeNull();
1093
+ });
1094
+
1095
+ it("orders Planning unattended rounds: an earlier one holds, a later one does not — unless any order counts", async () => {
1096
+ const earlier: Record<string, unknown> = roundOnCluster({
1097
+ status: AutoRemediationSuggestionStatus.Planning,
1098
+ verificationStatus: undefined,
1099
+ createdAt: new Date(NOW - 5000),
1100
+ });
1101
+ const later: Record<string, unknown> = roundOnCluster({
1102
+ status: AutoRemediationSuggestionStatus.Planning,
1103
+ verificationStatus: undefined,
1104
+ createdAt: new Date(NOW),
1105
+ });
1106
+
1107
+ expect((await holding([earlier]))?.description).toContain(
1108
+ "still running unattended",
1109
+ );
1110
+ expect(await holding([later])).toBeNull();
1111
+ expect(await holding([later], { anyOrder: true })).not.toBeNull();
1112
+ });
1113
+
1114
+ it("holds for the same signal's round that is still composing — asking or not — only when a subject is given", async () => {
1115
+ const composing: Record<string, unknown> = roundOnCluster({
1116
+ status: AutoRemediationSuggestionStatus.Planning,
1117
+ executionMode: AutoRemediationExecutionMode.Suggest,
1118
+ verificationStatus: undefined,
1119
+ });
1120
+
1121
+ const sameSignal: ClusterRoundHold | null = await holding([composing], {
1122
+ subject: { incidentId: INCIDENT_ID },
1123
+ });
1124
+ expect(sameSignal?.isSameSubject).toBe(true);
1125
+ expect(sameSignal?.description).toContain("same signal");
1126
+
1127
+ expect(
1128
+ await holding([composing], { subject: { alertId: ALERT_ID } }),
1129
+ ).toBeNull();
1130
+ expect(await holding([composing])).toBeNull();
1131
+ });
1132
+
1133
+ it("holds while an Approved (human-approved) fix is still being verified", async () => {
1134
+ expect(
1135
+ (
1136
+ await holding([
1137
+ roundOnCluster({ status: AutoRemediationSuggestionStatus.Approved }),
1138
+ ])
1139
+ )?.description,
1140
+ ).toContain("still being verified");
1141
+ });
1142
+
1143
+ /*
1144
+ * A rule-driven run carries no cluster id; its kubectl jobs do. One that
1145
+ * changed the cluster holds it like a cluster round would (PR #3953
1146
+ * review, remediation-r2-04) — so "one unattended AI run per cluster at a
1147
+ * time" holds in both directions.
1148
+ */
1149
+ describe("a rule-driven run found through its kubectl jobs on the cluster", () => {
1150
+ const RULE_RUN: ObjectID = new ObjectID(
1151
+ "abababab-abab-4bab-8bab-abababababab",
1152
+ );
1153
+
1154
+ function ruleRun(
1155
+ overrides: Record<string, unknown> = {},
1156
+ ): Record<string, unknown> {
1157
+ return {
1158
+ id: RULE_RUN,
1159
+ _id: RULE_RUN.toString(),
1160
+ status: AutoRemediationSuggestionStatus.AutoExecuted,
1161
+ executionMode: AutoRemediationExecutionMode.FullAuto,
1162
+ verificationStatus: AutoRemediationVerificationStatus.Pending,
1163
+ verificationDeadlineAt: new Date(NOW + 10 * 60 * 1000),
1164
+ incidentId: INCIDENT_ID,
1165
+ ruleNameSnapshot: "Restart web on 5xx",
1166
+ createdAt: new Date(NOW - 5 * 60 * 1000),
1167
+ ...overrides,
1168
+ };
1169
+ }
1170
+
1171
+ function holdingThroughJobs(data: {
1172
+ jobs: Array<{ suggestionId: ObjectID; stepId: string }>;
1173
+ runs: Array<Record<string, unknown>>;
1174
+ forRound?: ObjectID | undefined;
1175
+ }): {
1176
+ hold: Promise<ClusterRoundHold | null>;
1177
+ runRead: jest.SpyInstance;
1178
+ } {
1179
+ const runRead: jest.SpyInstance = jest
1180
+ .spyOn(AutoRemediationSuggestionService, "findBy")
1181
+ .mockImplementation(
1182
+ async (args: unknown): Promise<Array<AutoRemediationSuggestion>> => {
1183
+ const query: Record<string, unknown> =
1184
+ (args as { query?: Record<string, unknown> }).query || {};
1185
+ // No cluster round on the cluster; the runs behind the jobs by id.
1186
+ return (query["kubernetesClusterId"]
1187
+ ? []
1188
+ : data.runs) as unknown as Array<AutoRemediationSuggestion>;
1189
+ },
1190
+ );
1191
+ jest.spyOn(RunnerJobService, "findBy").mockResolvedValue(
1192
+ data.jobs.map(
1193
+ (job: { suggestionId: ObjectID; stepId: string }): RunnerJob => {
1194
+ return {
1195
+ id: ObjectID.generate(),
1196
+ autoRemediationSuggestionId: job.suggestionId,
1197
+ stepId: job.stepId,
1198
+ } as unknown as RunnerJob;
1199
+ },
1200
+ ),
1201
+ );
1202
+
1203
+ return {
1204
+ hold: AutoRemediationRuleEngineService.findRoundHoldingCluster({
1205
+ projectId: PROJECT_ID,
1206
+ clusterId: CLUSTER_ID.toString(),
1207
+ forRound: {
1208
+ suggestionId: data.forRound || MINE,
1209
+ createdAt: new Date(NOW - 1000),
1210
+ },
1211
+ }),
1212
+ runRead,
1213
+ };
1214
+ }
1215
+
1216
+ it("holds while its fix on the cluster is still being verified, naming the run", async () => {
1217
+ const hold: ClusterRoundHold | null = await holdingThroughJobs({
1218
+ jobs: [{ suggestionId: RULE_RUN, stepId: "ai-command-1" }],
1219
+ runs: [ruleRun()],
1220
+ }).hold;
1221
+
1222
+ expect(hold?.suggestionId).toBe(RULE_RUN.toString());
1223
+ expect(hold?.ruleNameSnapshot).toBe("Restart web on 5xx");
1224
+ expect(hold?.description).toBe(
1225
+ "applied a fix that is still being verified",
1226
+ );
1227
+ });
1228
+
1229
+ it("holds while it is still running and already changed the cluster — created after the asking round, without anyOrder", async () => {
1230
+ const hold: ClusterRoundHold | null = await holdingThroughJobs({
1231
+ jobs: [{ suggestionId: RULE_RUN, stepId: "ai-command-2" }],
1232
+ runs: [
1233
+ ruleRun({
1234
+ status: AutoRemediationSuggestionStatus.Planning,
1235
+ verificationStatus: undefined,
1236
+ createdAt: new Date(NOW),
1237
+ }),
1238
+ ],
1239
+ }).hold;
1240
+
1241
+ expect(hold?.description).toBe("is still changing it");
1242
+ });
1243
+
1244
+ it("reads the runs behind the jobs by id, in this project, CommandPlan only", async () => {
1245
+ const lookup: {
1246
+ hold: Promise<ClusterRoundHold | null>;
1247
+ runRead: jest.SpyInstance;
1248
+ } = holdingThroughJobs({
1249
+ jobs: [{ suggestionId: RULE_RUN, stepId: "ai-command-1" }],
1250
+ runs: [ruleRun()],
1251
+ });
1252
+ await lookup.hold;
1253
+
1254
+ const byId: Record<string, unknown> | undefined =
1255
+ lookup.runRead.mock.calls
1256
+ .map((call: Array<unknown>) => {
1257
+ return (call[0] as { query: Record<string, unknown> }).query;
1258
+ })
1259
+ .find((query: Record<string, unknown>) => {
1260
+ return Boolean(query["_id"]);
1261
+ });
1262
+ expect(byId).toBeDefined();
1263
+ expect((byId!["projectId"] as ObjectID).toString()).toBe(
1264
+ PROJECT_ID.toString(),
1265
+ );
1266
+ expect(byId!["suggestionType"]).toBe(
1267
+ AutoRemediationSuggestionType.CommandPlan,
1268
+ );
1269
+ });
1270
+
1271
+ it.each([
1272
+ [
1273
+ "its fix was verified",
1274
+ [{ stepId: "ai-command-1" }],
1275
+ { verificationStatus: AutoRemediationVerificationStatus.Verified },
1276
+ ],
1277
+ [
1278
+ "its only job on the cluster is a rollback of a failed fix",
1279
+ [{ stepId: "ai-rollback-1" }],
1280
+ {},
1281
+ ],
1282
+ ["it has no job on the cluster", [], {}],
1283
+ ])(
1284
+ "negative control: no hold when %s",
1285
+ async (
1286
+ _label: string,
1287
+ jobs: Array<{ stepId: string }>,
1288
+ overrides: Record<string, unknown>,
1289
+ ) => {
1290
+ const lookup: {
1291
+ hold: Promise<ClusterRoundHold | null>;
1292
+ runRead: jest.SpyInstance;
1293
+ } = holdingThroughJobs({
1294
+ jobs: jobs.map((job: { stepId: string }) => {
1295
+ return { suggestionId: RULE_RUN, stepId: job.stepId };
1296
+ }),
1297
+ runs: [ruleRun(overrides)],
1298
+ });
1299
+
1300
+ expect(await lookup.hold).toBeNull();
1301
+ },
1302
+ );
1303
+
1304
+ it("negative control: the asking run's own jobs never hold the cluster against it", async () => {
1305
+ expect(
1306
+ await holdingThroughJobs({
1307
+ jobs: [{ suggestionId: RULE_RUN, stepId: "ai-command-1" }],
1308
+ runs: [ruleRun()],
1309
+ forRound: RULE_RUN,
1310
+ }).hold,
1311
+ ).toBeNull();
1312
+ });
1313
+
1314
+ it("negative control: a run the read returns that no job named is ignored", async () => {
1315
+ expect(
1316
+ await holdingThroughJobs({
1317
+ jobs: [{ suggestionId: ObjectID.generate(), stepId: "ai-command-1" }],
1318
+ runs: [ruleRun()],
1319
+ }).hold,
1320
+ ).toBeNull();
1321
+ });
1322
+ });
1323
+
1324
+ it("propagates a failed read so callers fail safe", async () => {
1325
+ jest
1326
+ .spyOn(AutoRemediationSuggestionService, "findBy")
1327
+ .mockRejectedValue(new Error("db down"));
1328
+
1329
+ await expect(
1330
+ AutoRemediationRuleEngineService.findRoundHoldingCluster({
1331
+ projectId: PROJECT_ID,
1332
+ clusterId: CLUSTER_ID.toString(),
1333
+ }),
1334
+ ).rejects.toThrow("db down");
1335
+ });
1336
+ });
1337
+
1338
+ describe("cluster round name snapshots", () => {
1339
+ it("round-trips the server-written name, rounds included", () => {
1340
+ expect(getClusterRoundNameSnapshot("prod-us", 1)).toBe(
1341
+ 'AI remediation for cluster "prod-us"',
1342
+ );
1343
+ expect(getClusterRoundNameSnapshot("prod-us", 2)).toBe(
1344
+ 'AI remediation for cluster "prod-us" (round 2)',
1345
+ );
1346
+ expect(
1347
+ parseClusterRoundNameSnapshot(getClusterRoundNameSnapshot("prod-us", 2)),
1348
+ ).toEqual({ clusterName: "prod-us" });
1349
+ expect(
1350
+ parseClusterRoundNameSnapshot('AI remediation for cluster "a "b" c"'),
1351
+ ).toEqual({ clusterName: 'a "b" c' });
1352
+ });
1353
+
1354
+ it("does not take an ordinary rule name for a cluster round", () => {
1355
+ expect(parseClusterRoundNameSnapshot("Restart the API service")).toBeNull();
1356
+ expect(
1357
+ parseClusterRoundNameSnapshot('Custom: AI remediation for cluster "x"'),
1358
+ ).toBeNull();
1359
+ expect(parseClusterRoundNameSnapshot(undefined)).toBeNull();
1360
+ });
1361
+ });