@oneuptime/common 14.0.9 → 14.0.10

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 (383) hide show
  1. package/Models/DatabaseModels/AutoRemediationSuggestion.ts +60 -0
  2. package/Models/DatabaseModels/CephCluster.ts +213 -0
  3. package/Models/DatabaseModels/DatabaseServer.ts +213 -0
  4. package/Models/DatabaseModels/DockerHost.ts +213 -0
  5. package/Models/DatabaseModels/DockerSwarmCluster.ts +213 -0
  6. package/Models/DatabaseModels/GlobalConfig.ts +1 -1
  7. package/Models/DatabaseModels/Host.ts +213 -0
  8. package/Models/DatabaseModels/Index.ts +2 -0
  9. package/Models/DatabaseModels/PodmanHost.ts +213 -0
  10. package/Models/DatabaseModels/ProxmoxCluster.ts +213 -0
  11. package/Models/DatabaseModels/ResourceAiAgent.ts +419 -0
  12. package/Models/DatabaseModels/RunnerJob.ts +144 -0
  13. package/Models/DatabaseModels/VMwareVCenter.ts +213 -0
  14. package/Server/API/AutoRemediationAPI.ts +392 -1
  15. package/Server/API/ResourceAiAccessAPI.ts +1669 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.ts +423 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  18. package/Server/Infrastructure/Semaphore.ts +22 -0
  19. package/Server/Middleware/TelemetryIngest.ts +15 -5
  20. package/Server/Services/AnalyticsDatabaseService.ts +45 -1
  21. package/Server/Services/AutoRemediationRuleEngineService.ts +940 -112
  22. package/Server/Services/CephClusterService.ts +109 -1
  23. package/Server/Services/DatabaseServerService.ts +116 -1
  24. package/Server/Services/DockerHostService.ts +109 -1
  25. package/Server/Services/DockerSwarmClusterService.ts +113 -1
  26. package/Server/Services/HostService.ts +126 -4
  27. package/Server/Services/MetricRecordingRuleService.ts +47 -0
  28. package/Server/Services/PodmanHostService.ts +109 -1
  29. package/Server/Services/ProxmoxClusterService.ts +110 -1
  30. package/Server/Services/ResourceAiAccessService.ts +1439 -0
  31. package/Server/Services/ResourceAiAgentJobService.ts +202 -0
  32. package/Server/Services/ResourceAiAgentService.ts +2432 -0
  33. package/Server/Services/RunnerJobService.ts +611 -4
  34. package/Server/Services/TelemetryUsageBillingService.ts +28 -0
  35. package/Server/Services/TraceRecordingRuleService.ts +33 -0
  36. package/Server/Services/VMwareVCenterService.ts +110 -1
  37. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1434 -32
  38. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +935 -21
  39. package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +25 -1
  40. package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +577 -0
  41. package/Server/Utils/AI/ResourceAccess/ResourceAccessContext.ts +271 -0
  42. package/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.ts +45 -0
  43. package/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.ts +964 -0
  44. package/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.ts +333 -0
  45. package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +873 -0
  46. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +72 -2
  47. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +72 -5
  48. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +72 -5
  49. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +396 -13
  50. package/Server/Utils/AutoRemediation/RemediationVerifier.ts +35 -2
  51. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +9 -1
  52. package/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.ts +920 -0
  53. package/Server/Utils/SessionReplay/SessionReplayUsage.ts +84 -6
  54. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +35 -15
  55. package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +33 -15
  56. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +21 -1
  57. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +298 -224
  58. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +35 -15
  59. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +389 -175
  60. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +366 -143
  61. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.ts +163 -0
  62. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.ts +396 -0
  63. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.ts +418 -0
  64. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.ts +152 -0
  65. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.ts +251 -0
  66. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.ts +214 -0
  67. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +93 -0
  68. package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +18 -6
  69. package/Tests/App/Dashboard/InvestigationInfrastructureTools.test.tsx +506 -0
  70. package/Tests/App/Dashboard/RemediationSuggestionCardDescription.test.tsx +209 -0
  71. package/Tests/App/Dashboard/RemediationSuggestionCardResource.test.tsx +317 -0
  72. package/Tests/App/Dashboard/ResourceAiAccessSettingsUtil.test.ts +921 -0
  73. package/Tests/App/Dashboard/ResourceAiAgentInstall.test.ts +860 -0
  74. package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +1721 -0
  75. package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +1002 -0
  76. package/Tests/App/Dashboard/ResourceAiInsightsPage.test.tsx +931 -0
  77. package/Tests/App/Dashboard/ResourceAiNavigation.test.tsx +575 -0
  78. package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +38 -7
  79. package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +33 -1
  80. package/Tests/Models/DatabaseModels/ResourceAiAccessColumns.test.ts +738 -0
  81. package/Tests/Models/DatabaseModels/ResourceAiAgentModel.test.ts +842 -0
  82. package/Tests/Server/API/AutoRemediationApproveResourceRound.test.ts +835 -0
  83. package/Tests/Server/API/ResourceAiAccessAPI.test.ts +2730 -0
  84. package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +60 -0
  85. package/Tests/Server/Infrastructure/Postgres/AddResourceAiAgentsMigration.test.ts +659 -0
  86. package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +31 -0
  87. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +63 -5
  88. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +103 -5
  89. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +19 -1
  90. package/Tests/Server/Services/AutoRemediationResourceRuleEngine.test.ts +1279 -0
  91. package/Tests/Server/Services/DatabaseServerService.test.ts +55 -0
  92. package/Tests/Server/Services/GroupTelemetryUsageExcludeNames.test.ts +299 -0
  93. package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +44 -0
  94. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +45 -6
  95. package/Tests/Server/Services/RecordingRuleReservedMetricName.test.ts +171 -0
  96. package/Tests/Server/Services/ResourceAiAccessChangeAuthorization.test.ts +256 -0
  97. package/Tests/Server/Services/ResourceAiAccessService.test.ts +1373 -0
  98. package/Tests/Server/Services/ResourceAiAgentJobService.test.ts +375 -0
  99. package/Tests/Server/Services/ResourceAiAgentServiceHelpers.test.ts +1114 -0
  100. package/Tests/Server/Services/ResourceAiAgentServiceLifecycle.test.ts +1050 -0
  101. package/Tests/Server/Services/ResourceAiAgentServiceRegister.test.ts +2251 -0
  102. package/Tests/Server/Services/ResourceAiSettingsCreate.test.ts +373 -0
  103. package/Tests/Server/Services/ResourceAiSettingsPermission.test.ts +1042 -0
  104. package/Tests/Server/Services/ResourceServiceDeleteCleansUpAi.test.ts +319 -0
  105. package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +105 -0
  106. package/Tests/Server/Services/RunnerJobEnqueueResourceCommand.test.ts +986 -0
  107. package/Tests/Server/Services/RunnerJobResourceCommandLane.test.ts +211 -0
  108. package/Tests/Server/Services/RunnerJobResourceCommandTimeoutAndRedaction.test.ts +352 -0
  109. package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +218 -0
  110. package/Tests/Server/TestingUtils/Services/FakeRunnerJobCount.ts +145 -0
  111. package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +453 -0
  112. package/Tests/Server/Utils/AI/InvestigationInfrastructureReport.test.ts +721 -0
  113. package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +94 -1
  114. package/Tests/Server/Utils/AI/RemediationCommandToolsResource.test.ts +1530 -0
  115. package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +1249 -0
  116. package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +117 -0
  117. package/Tests/Server/Utils/AI/RemediationResourceCopyParity.test.ts +463 -0
  118. package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +722 -0
  119. package/Tests/Server/Utils/AI/ResourceAccess/ResourceAccessContext.test.ts +266 -0
  120. package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.test.ts +1220 -0
  121. package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.test.ts +569 -0
  122. package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +830 -0
  123. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorResource.test.ts +717 -0
  124. package/Tests/Server/Utils/AutoRemediation/RemediationVerifierResourceFollowUp.test.ts +338 -0
  125. package/Tests/Server/Utils/Monitor/Criteria/SessionReplayBudgetTemplateCriteria.test.ts +422 -0
  126. package/Tests/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.test.ts +1647 -0
  127. package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +143 -1
  128. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +33 -3
  129. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsAccountNotLinked.test.ts +1093 -0
  130. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.test.ts +1049 -0
  131. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.test.ts +1676 -0
  132. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCards.test.ts +2884 -0
  133. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.test.ts +2490 -0
  134. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmit.test.ts +2293 -0
  135. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmitServerTimezone.test.ts +386 -0
  136. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.test.ts +1477 -0
  137. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.test.ts +1967 -0
  138. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsStripHtmlTags.test.ts +92 -0
  139. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsSubmittedFormRemoval.test.ts +1819 -0
  140. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.test.ts +1033 -0
  141. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezoneServerZone.test.ts +610 -0
  142. package/Tests/Server/Utils/Workspace/MicrosoftTeamsBotMessageHandling.test.ts +2610 -0
  143. package/Tests/Server/Utils/Workspace/MicrosoftTeamsCreateCommandsEndToEnd.test.ts +4672 -0
  144. package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +190 -65
  145. package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +10 -4
  146. package/Tests/Types/AutoRemediation/AiRemediationCommandPlanResourceCommand.test.ts +305 -0
  147. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +277 -13
  148. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +113 -0
  149. package/Tests/Types/Monitor/RumAlertTemplates.test.ts +773 -2
  150. package/Tests/Types/ResourceAiAgent/AiResourceType.test.ts +419 -0
  151. package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +517 -0
  152. package/Tests/Types/Runbook/RunbookStepType.test.ts +147 -8
  153. package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +769 -1
  154. package/Tests/Utils/AiRemediation/Resource/CephCommandPolicy.test.ts +1653 -0
  155. package/Tests/Utils/AiRemediation/Resource/CephOutputRedaction.test.ts +204 -0
  156. package/Tests/Utils/AiRemediation/Resource/DatabaseCommandPolicy.test.ts +1077 -0
  157. package/Tests/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.test.ts +558 -0
  158. package/Tests/Utils/AiRemediation/Resource/DatabaseQueryRedactor.test.ts +834 -0
  159. package/Tests/Utils/AiRemediation/Resource/DockerCliGrammar.test.ts +747 -0
  160. package/Tests/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.test.ts +1259 -0
  161. package/Tests/Utils/AiRemediation/Resource/DockerOutputRedaction.test.ts +386 -0
  162. package/Tests/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.test.ts +782 -0
  163. package/Tests/Utils/AiRemediation/Resource/GovcCommandPolicy.test.ts +2259 -0
  164. package/Tests/Utils/AiRemediation/Resource/HostCommandPolicy.test.ts +2019 -0
  165. package/Tests/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.test.ts +2497 -0
  166. package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicy.test.ts +1305 -0
  167. package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.test.ts +585 -0
  168. package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactor.test.ts +334 -0
  169. package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactorCopyParity.test.ts +98 -0
  170. package/Tests/Utils/AiRemediation/Resource/ResourcePolicyImportClosure.test.ts +391 -0
  171. package/Tests/Utils/AiRemediation/ResourceAiAgentPolicyCopyParity.test.ts +497 -0
  172. package/Tests/Utils/SessionReplay/SessionReplayBudgetMetricType.test.ts +383 -0
  173. package/Types/AI/ResourceAiAccessApi.ts +140 -0
  174. package/Types/AI/ResourceAiAccessPermissions.ts +126 -0
  175. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +183 -2
  176. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +55 -22
  177. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +35 -3
  178. package/Types/Monitor/RumAlertTemplates.ts +351 -4
  179. package/Types/ResourceAiAgent/AiResourceType.ts +310 -0
  180. package/Types/ResourceAiAgent/ResourceAiAccess.ts +574 -0
  181. package/Types/Rum/SessionReplayBudgetMetricType.ts +47 -0
  182. package/Types/Runbook/RunbookStepType.ts +29 -0
  183. package/Types/Telemetry/TelemetryIngestSurface.ts +14 -2
  184. package/Utils/AI/InvestigationReport.ts +121 -15
  185. package/Utils/AiRemediation/Resource/CephCommandPolicy.ts +1936 -0
  186. package/Utils/AiRemediation/Resource/DatabaseCommandPolicy.ts +166 -0
  187. package/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.ts +1532 -0
  188. package/Utils/AiRemediation/Resource/DatabaseQueryRedactor.ts +1394 -0
  189. package/Utils/AiRemediation/Resource/DockerCliGrammar.ts +1839 -0
  190. package/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.ts +490 -0
  191. package/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.ts +687 -0
  192. package/Utils/AiRemediation/Resource/GovcCommandPolicy.ts +2096 -0
  193. package/Utils/AiRemediation/Resource/HostCommandPolicy.ts +2982 -0
  194. package/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.ts +1679 -0
  195. package/Utils/AiRemediation/Resource/ResourceCommandPolicy.ts +851 -0
  196. package/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.ts +593 -0
  197. package/Utils/AiRemediation/Resource/ResourceOutputRedactor.ts +2812 -0
  198. package/Utils/SessionReplay/SessionReplayBudgetMetricType.ts +184 -0
  199. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
  200. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
  201. package/build/dist/Models/DatabaseModels/CephCluster.js +219 -0
  202. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
  203. package/build/dist/Models/DatabaseModels/DatabaseServer.js +219 -0
  204. package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
  205. package/build/dist/Models/DatabaseModels/DockerHost.js +219 -0
  206. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  207. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +219 -0
  208. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
  209. package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
  210. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  211. package/build/dist/Models/DatabaseModels/Host.js +219 -0
  212. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  213. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  214. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  215. package/build/dist/Models/DatabaseModels/PodmanHost.js +219 -0
  216. package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
  217. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +219 -0
  218. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
  219. package/build/dist/Models/DatabaseModels/ResourceAiAgent.js +439 -0
  220. package/build/dist/Models/DatabaseModels/ResourceAiAgent.js.map +1 -0
  221. package/build/dist/Models/DatabaseModels/RunnerJob.js +145 -0
  222. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
  223. package/build/dist/Models/DatabaseModels/VMwareVCenter.js +219 -0
  224. package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
  225. package/build/dist/Server/API/AutoRemediationAPI.js +231 -1
  226. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  227. package/build/dist/Server/API/ResourceAiAccessAPI.js +1119 -0
  228. package/build/dist/Server/API/ResourceAiAccessAPI.js.map +1 -0
  229. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js +168 -0
  230. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js.map +1 -0
  231. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  232. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  233. package/build/dist/Server/Infrastructure/Semaphore.js +6 -0
  234. package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
  235. package/build/dist/Server/Middleware/TelemetryIngest.js +12 -5
  236. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  237. package/build/dist/Server/Services/AnalyticsDatabaseService.js +26 -1
  238. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  239. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +601 -3
  240. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  241. package/build/dist/Server/Services/CephClusterService.js +104 -0
  242. package/build/dist/Server/Services/CephClusterService.js.map +1 -1
  243. package/build/dist/Server/Services/DatabaseServerService.js +99 -0
  244. package/build/dist/Server/Services/DatabaseServerService.js.map +1 -1
  245. package/build/dist/Server/Services/DockerHostService.js +104 -0
  246. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  247. package/build/dist/Server/Services/DockerSwarmClusterService.js +104 -0
  248. package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
  249. package/build/dist/Server/Services/HostService.js +114 -2
  250. package/build/dist/Server/Services/HostService.js.map +1 -1
  251. package/build/dist/Server/Services/MetricRecordingRuleService.js +46 -0
  252. package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -1
  253. package/build/dist/Server/Services/PodmanHostService.js +104 -0
  254. package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
  255. package/build/dist/Server/Services/ProxmoxClusterService.js +104 -0
  256. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
  257. package/build/dist/Server/Services/ResourceAiAccessService.js +1028 -0
  258. package/build/dist/Server/Services/ResourceAiAccessService.js.map +1 -0
  259. package/build/dist/Server/Services/ResourceAiAgentJobService.js +173 -0
  260. package/build/dist/Server/Services/ResourceAiAgentJobService.js.map +1 -0
  261. package/build/dist/Server/Services/ResourceAiAgentService.js +1687 -0
  262. package/build/dist/Server/Services/ResourceAiAgentService.js.map +1 -0
  263. package/build/dist/Server/Services/RunnerJobService.js +344 -5
  264. package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
  265. package/build/dist/Server/Services/TelemetryUsageBillingService.js +26 -0
  266. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  267. package/build/dist/Server/Services/TraceRecordingRuleService.js +37 -0
  268. package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -1
  269. package/build/dist/Server/Services/VMwareVCenterService.js +104 -0
  270. package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
  271. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1029 -30
  272. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  273. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +633 -28
  274. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  275. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +21 -1
  276. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
  277. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +330 -0
  278. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -0
  279. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js +160 -0
  280. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js.map +1 -0
  281. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js +33 -0
  282. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js.map +1 -0
  283. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js +640 -0
  284. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js.map +1 -0
  285. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js +226 -0
  286. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js.map +1 -0
  287. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +600 -0
  288. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -0
  289. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +50 -4
  290. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  291. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +55 -4
  292. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  293. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +55 -4
  294. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  295. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +290 -13
  296. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
  297. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +29 -1
  298. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
  299. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +9 -1
  300. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
  301. package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js +627 -0
  302. package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js.map +1 -0
  303. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +60 -5
  304. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -1
  305. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +19 -15
  306. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
  307. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +19 -15
  308. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
  309. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +17 -1
  310. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
  311. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +183 -209
  312. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  313. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +19 -15
  314. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  315. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +233 -167
  316. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
  317. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +263 -110
  318. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  319. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js +129 -0
  320. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js.map +1 -0
  321. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js +266 -0
  322. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js.map +1 -0
  323. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js +258 -0
  324. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js.map +1 -0
  325. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js +104 -0
  326. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js.map +1 -0
  327. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js +183 -0
  328. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js.map +1 -0
  329. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js +123 -0
  330. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js.map +1 -0
  331. package/build/dist/Types/AI/ResourceAiAccessApi.js +30 -0
  332. package/build/dist/Types/AI/ResourceAiAccessApi.js.map +1 -0
  333. package/build/dist/Types/AI/ResourceAiAccessPermissions.js +98 -0
  334. package/build/dist/Types/AI/ResourceAiAccessPermissions.js.map +1 -0
  335. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +116 -29
  336. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
  337. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +47 -21
  338. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  339. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +5 -0
  340. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  341. package/build/dist/Types/Monitor/RumAlertTemplates.js +199 -3
  342. package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
  343. package/build/dist/Types/ResourceAiAgent/AiResourceType.js +242 -0
  344. package/build/dist/Types/ResourceAiAgent/AiResourceType.js.map +1 -0
  345. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +275 -0
  346. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -0
  347. package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js +45 -0
  348. package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js.map +1 -0
  349. package/build/dist/Types/Runbook/RunbookStepType.js +27 -0
  350. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  351. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +13 -2
  352. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
  353. package/build/dist/Utils/AI/InvestigationReport.js +71 -11
  354. package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
  355. package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js +1462 -0
  356. package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js.map +1 -0
  357. package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js +122 -0
  358. package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js.map +1 -0
  359. package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js +1139 -0
  360. package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js.map +1 -0
  361. package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js +1060 -0
  362. package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js.map +1 -0
  363. package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js +1301 -0
  364. package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js.map +1 -0
  365. package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js +370 -0
  366. package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js.map +1 -0
  367. package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js +498 -0
  368. package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js.map +1 -0
  369. package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js +1565 -0
  370. package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js.map +1 -0
  371. package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js +2206 -0
  372. package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js.map +1 -0
  373. package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js +1129 -0
  374. package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js.map +1 -0
  375. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js +565 -0
  376. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js.map +1 -0
  377. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js +408 -0
  378. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js.map +1 -0
  379. package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js +1910 -0
  380. package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js.map +1 -0
  381. package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js +160 -0
  382. package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js.map +1 -0
  383. package/package.json +1 -1
@@ -52,6 +52,28 @@ import KubectlJobRunner, {
52
52
  KubectlTerminalJobFacts,
53
53
  } from "../AI/ClusterAccess/KubectlJobRunner";
54
54
  import RemediationCommandToolkit from "../AI/Remediation/RemediationCommandTools";
55
+ import ResourceCommandJobRunner, {
56
+ ResourceCommandRunState,
57
+ ResourceCommandTerminalJobFacts,
58
+ } from "../AI/ResourceAccess/ResourceCommandJobRunner";
59
+ import AiResourceType, {
60
+ AI_RESOURCE_TYPE_INFO,
61
+ isAiResourceType,
62
+ } from "../../../Types/ResourceAiAgent/AiResourceType";
63
+ import {
64
+ ResourceAiAccessGap,
65
+ ResourceAiAccessStatus,
66
+ ResourceAiRemediationMode,
67
+ ResourceCommandTier,
68
+ } from "../../../Types/ResourceAiAgent/ResourceAiAccess";
69
+ import ResourceCommandPolicy from "../../../Utils/AiRemediation/Resource/ResourceCommandPolicy";
70
+ import {
71
+ ResourceAutoExecutionVerdict,
72
+ ResourceCommandPolicyResult,
73
+ } from "../../../Utils/AiRemediation/Resource/ResourceCommandPolicyCore";
74
+ import ResourceAiAccessService, {
75
+ describeResourceNoun,
76
+ } from "../../Services/ResourceAiAccessService";
55
77
  import logger from "../Logger";
56
78
  import CaptureSpan from "../Telemetry/CaptureSpan";
57
79
 
@@ -510,6 +532,26 @@ export default class CommandPlanExecutor {
510
532
  anyFailed = true;
511
533
  }
512
534
 
535
+ /*
536
+ * The same for a resource command recorded as failed: its job is read
537
+ * the way every resource job is read
538
+ * (ResourceCommandJobRunner.getRunStateOfJobRow), and one that may
539
+ * have changed the resource is left for a human, never undone blind.
540
+ */
541
+ for (const command of await this.reconcileFailedResourceExecutions(
542
+ suggestion,
543
+ plan,
544
+ )) {
545
+ command.rollbackExecution = {
546
+ status: AiRemediationCommandExecutionStatus.Skipped,
547
+ errorMessage: `Rollback not run: the command reached the resource's AI agent but it did not report a finished result, so whether it changed the ${this.describeCommandResourceNoun(
548
+ command,
549
+ )} is unknown. If it did, undo it manually: ${command.rollbackCommand}`,
550
+ };
551
+ leftForHuman.push(command);
552
+ anyFailed = true;
553
+ }
554
+
513
555
  if (
514
556
  plan.commands.some((command: AiRemediationCommand) => {
515
557
  return (
@@ -561,6 +603,7 @@ export default class CommandPlanExecutor {
561
603
  const denyReason: string | null = this.getDenyReason({
562
604
  stepType: command.stepType,
563
605
  command: rollbackCommand,
606
+ resourceType: command.resourceType,
564
607
  });
565
608
 
566
609
  if (denyReason) {
@@ -581,13 +624,25 @@ export default class CommandPlanExecutor {
581
624
  * stopped bypassing them; a cluster whose remediation was turned
582
625
  * off must not be changed at all. Left for a human, and said so.
583
626
  */
627
+ /*
628
+ * The same for a resource: its AI page as it is NOW, its agent, the
629
+ * agent's write scope, and the resource's CURRENT mode and
630
+ * allowlist (getResourceExecutionRefusal). Null for kubectl and
631
+ * Bash/SSH, which the cluster re-check above covers.
632
+ */
584
633
  const clusterRefusal: string | null =
585
- await this.getClusterExecutionRefusal({
634
+ (await this.getClusterExecutionRefusal({
586
635
  suggestion,
587
636
  command,
588
637
  commandText: rollbackCommand,
589
638
  purpose: "rollback",
590
- });
639
+ })) ||
640
+ (await this.getResourceExecutionRefusal({
641
+ suggestion,
642
+ command,
643
+ commandText: rollbackCommand,
644
+ purpose: "rollback",
645
+ }));
591
646
 
592
647
  if (clusterRefusal) {
593
648
  command.rollbackExecution = {
@@ -630,6 +685,7 @@ export default class CommandPlanExecutor {
630
685
  command.rollbackExecution,
631
686
  terminalJob,
632
687
  "Rollback",
688
+ command,
633
689
  );
634
690
  if (
635
691
  command.rollbackExecution.status !==
@@ -666,7 +722,13 @@ export default class CommandPlanExecutor {
666
722
  suggestion,
667
723
  markdown:
668
724
  leftForHuman.length > 0
669
- ? `⚠️ **Auto-remediation rollback was not run for ${leftForHuman.length} command(s)** — the cluster no longer allows them unattended, or whether they ran could not be confirmed, so a human has to undo them. ${leftForHuman
725
+ ? `⚠️ **Auto-remediation rollback was not run for ${leftForHuman.length} command(s)** — the ${
726
+ leftForHuman.every((command: AiRemediationCommand): boolean => {
727
+ return command.stepType === RunbookStepType.ResourceCommand;
728
+ })
729
+ ? this.describeCommandResourceNoun(leftForHuman[0]!)
730
+ : "cluster"
731
+ } no longer allows them unattended, or whether they ran could not be confirmed, so a human has to undo them. ${leftForHuman
670
732
  .map((command: AiRemediationCommand) => {
671
733
  return this.capForFeed(
672
734
  command.rollbackExecution?.errorMessage || "",
@@ -730,6 +792,7 @@ export default class CommandPlanExecutor {
730
792
  const denyReason: string | null = this.getDenyReason({
731
793
  stepType: command.stepType,
732
794
  command: command.command,
795
+ resourceType: command.resourceType,
733
796
  });
734
797
 
735
798
  if (denyReason) {
@@ -747,16 +810,23 @@ export default class CommandPlanExecutor {
747
810
  * Execution-time cluster re-check: the approve API re-checks the
748
811
  * project switches, this re-checks the cluster's own AI page. An
749
812
  * operator who turned remediation off, or bound a different Runner,
750
- * after the plan was composed expects that to stop the plan too.
813
+ * after the plan was composed expects that to stop the plan too. A
814
+ * resource command gets the same re-check against its resource's AI
815
+ * page and agent (getResourceExecutionRefusal).
751
816
  */
752
- const clusterRefusal: string | null = await this.getClusterExecutionRefusal(
753
- {
817
+ const clusterRefusal: string | null =
818
+ (await this.getClusterExecutionRefusal({
754
819
  suggestion,
755
820
  command,
756
821
  commandText: command.command,
757
822
  purpose: "command",
758
- },
759
- );
823
+ })) ||
824
+ (await this.getResourceExecutionRefusal({
825
+ suggestion,
826
+ command,
827
+ commandText: command.command,
828
+ purpose: "command",
829
+ }));
760
830
 
761
831
  if (clusterRefusal) {
762
832
  return {
@@ -839,7 +909,7 @@ export default class CommandPlanExecutor {
839
909
  throw new Error("Command job did not reach a terminal state.");
840
910
  }
841
911
 
842
- this.settleFromJob(state, terminalJob, "Command");
912
+ this.settleFromJob(state, terminalJob, "Command", command);
843
913
  facts = {
844
914
  status: terminalJob.status,
845
915
  exitCode: terminalJob.exitCode,
@@ -881,14 +951,61 @@ export default class CommandPlanExecutor {
881
951
  });
882
952
  }
883
953
 
954
+ /*
955
+ * The same rule for a resource's "Last error": a success, or a failure
956
+ * about the resource's ACCESS as its program reports it
957
+ * (ResourceCommandJobRunner.isAccessFailure, with the program's own
958
+ * patterns).
959
+ */
960
+ if (
961
+ started.recordsClusterOutcome &&
962
+ command.stepType === RunbookStepType.ResourceCommand &&
963
+ isAiResourceType(command.resourceType) &&
964
+ command.resourceId &&
965
+ ObjectID.isValidUUID(command.resourceId)
966
+ ) {
967
+ const resourceFacts: ResourceCommandTerminalJobFacts | null = facts
968
+ ? { ...facts, program: this.getCommandProgram(command.command) }
969
+ : null;
970
+ const recordsResourceOutcome: boolean =
971
+ succeeded ||
972
+ (resourceFacts !== null &&
973
+ ResourceCommandJobRunner.isAccessFailure(resourceFacts));
974
+
975
+ if (recordsResourceOutcome) {
976
+ await ResourceAiAccessService.recordCommandOutcome({
977
+ resourceType: command.resourceType,
978
+ resourceId: new ObjectID(command.resourceId),
979
+ succeeded,
980
+ errorMessage: state.errorMessage,
981
+ });
982
+ }
983
+ }
984
+
884
985
  return state;
885
986
  }
886
987
 
988
+ // argv[0] of a resource command, for its program's rules.
989
+ private static getCommandProgram(command: string): string {
990
+ return (command || "").trim().split(/\s+/)[0] || "";
991
+ }
992
+
993
+ // "Docker host", "host" — the noun of a resource command's resource.
994
+ private static describeCommandResourceNoun(
995
+ command: AiRemediationCommand,
996
+ ): string {
997
+ return isAiResourceType(command.resourceType)
998
+ ? describeResourceNoun(command.resourceType)
999
+ : "resource";
1000
+ }
1001
+
887
1002
  // Copy a terminal job's outcome onto an execution record.
888
1003
  private static settleFromJob(
889
1004
  state: AiRemediationCommandExecutionState,
890
1005
  job: RunnerJob,
891
1006
  label: "Command" | "Rollback",
1007
+ // The command the job ran: a resource command's output gets its program's redaction.
1008
+ command?: AiRemediationCommand | undefined,
892
1009
  ): void {
893
1010
  const succeeded: boolean = job.status === RunnerJobStatus.Succeeded;
894
1011
 
@@ -897,12 +1014,36 @@ export default class CommandPlanExecutor {
897
1014
  : AiRemediationCommandExecutionStatus.Failed;
898
1015
  state.completedAt = OneUptimeDate.getCurrentDate().toISOString();
899
1016
  state.exitCode = job.exitCode;
900
- state.output = this.capOutput(job.output || "");
1017
+ state.output = this.capCommandOutput(job.output || "", command);
901
1018
  state.errorMessage = succeeded
902
1019
  ? undefined
903
1020
  : job.errorMessage || `${label} ended with status ${job.status}.`;
904
1021
  }
905
1022
 
1023
+ /*
1024
+ * The stored output of a command's job: a resource command's goes through
1025
+ * the resource redaction (its program's rules, then the generic ones) at
1026
+ * the stored cap; everything else through capOutput, as before.
1027
+ */
1028
+ private static capCommandOutput(
1029
+ output: string,
1030
+ command?: AiRemediationCommand | undefined,
1031
+ ): string {
1032
+ if (
1033
+ command?.stepType === RunbookStepType.ResourceCommand &&
1034
+ isAiResourceType(command.resourceType)
1035
+ ) {
1036
+ return ResourceCommandJobRunner.redactAndCap({
1037
+ output,
1038
+ resourceType: command.resourceType,
1039
+ program: this.getCommandProgram(command.command),
1040
+ maxChars: MAX_STORED_OUTPUT_CHARS,
1041
+ }).text;
1042
+ }
1043
+
1044
+ return this.capOutput(output);
1045
+ }
1046
+
906
1047
  /*
907
1048
  * One enqueue for both lanes. Bash/SSH go through enqueueAiCommand
908
1049
  * (script or SSH payload); Kubectl goes through enqueueAiKubectlCommand
@@ -916,6 +1057,38 @@ export default class CommandPlanExecutor {
916
1057
  }): Promise<RunnerJob> {
917
1058
  const { suggestion, command } = data;
918
1059
 
1060
+ /*
1061
+ * A resource command goes through the resource chokepoint
1062
+ * (enqueueAiResourceCommand), which re-runs the policy, the binding, the
1063
+ * resource's fixes switch and the agent's write scope — and targets the
1064
+ * agent the plan names, so a reset or replaced agent never receives a
1065
+ * job composed for its predecessor.
1066
+ */
1067
+ if (command.stepType === RunbookStepType.ResourceCommand) {
1068
+ if (
1069
+ !isAiResourceType(command.resourceType) ||
1070
+ !command.resourceId ||
1071
+ !ObjectID.isValidUUID(command.resourceId) ||
1072
+ !ObjectID.isValidUUID(command.runnerId)
1073
+ ) {
1074
+ throw new Error("The resource command names no resource.");
1075
+ }
1076
+
1077
+ return RunnerJobService.enqueueAiResourceCommand({
1078
+ projectId: suggestion.projectId!,
1079
+ aiRunId: suggestion.aiRunId!,
1080
+ origin: RunnerJobOrigin.AiRemediation,
1081
+ autoRemediationSuggestionId: suggestion.id!,
1082
+ resourceType: command.resourceType,
1083
+ resourceId: new ObjectID(command.resourceId),
1084
+ stepId: data.stepId,
1085
+ targetResourceAiAgentId: new ObjectID(command.runnerId),
1086
+ command: data.commandText,
1087
+ timeoutInMs: command.timeoutInMs,
1088
+ claimTimeoutInMs: AI_COMMAND_CLAIM_TIMEOUT_MS,
1089
+ });
1090
+ }
1091
+
919
1092
  if (command.stepType === RunbookStepType.Kubectl) {
920
1093
  if (
921
1094
  !command.kubernetesClusterId ||
@@ -1073,6 +1246,118 @@ export default class CommandPlanExecutor {
1073
1246
  return null;
1074
1247
  }
1075
1248
 
1249
+ /*
1250
+ * Why a resource command may NOT run on its resource right now, or null
1251
+ * — getClusterExecutionRefusal for a resource. The plan froze the
1252
+ * resource and the AI agent it was composed for; before anything is
1253
+ * enqueued the resource's AI page is read again: fixes must still be on
1254
+ * and ready, the agent must still be the one on the plan (a reset or
1255
+ * replaced agent never receives a job meant for its predecessor), and
1256
+ * the agent's reported write scope must let the command run. A rollback
1257
+ * must ALSO be allowed unattended under the resource's CURRENT mode and
1258
+ * allowlist: nothing shows a rollback to a human when it fires.
1259
+ *
1260
+ * Fails closed: a status that cannot be read is a refusal. Other step
1261
+ * types pass through.
1262
+ */
1263
+ private static async getResourceExecutionRefusal(data: {
1264
+ suggestion: AutoRemediationSuggestion;
1265
+ command: AiRemediationCommand;
1266
+ commandText: string;
1267
+ purpose: "command" | "rollback";
1268
+ }): Promise<string | null> {
1269
+ const { suggestion, command } = data;
1270
+
1271
+ if (command.stepType !== RunbookStepType.ResourceCommand) {
1272
+ return null;
1273
+ }
1274
+
1275
+ if (
1276
+ !isAiResourceType(command.resourceType) ||
1277
+ !command.resourceId ||
1278
+ !ObjectID.isValidUUID(command.resourceId) ||
1279
+ !suggestion.projectId
1280
+ ) {
1281
+ return "the resource command names no valid resource";
1282
+ }
1283
+
1284
+ const resourceType: AiResourceType = command.resourceType;
1285
+ const noun: string = describeResourceNoun(resourceType);
1286
+ const label: string = `${noun} "${
1287
+ command.resourceNameSnapshot || command.resourceId
1288
+ }"`;
1289
+
1290
+ let status: ResourceAiAccessStatus | null;
1291
+
1292
+ try {
1293
+ status = await ResourceAiAccessService.getStatusForResource({
1294
+ projectId: suggestion.projectId,
1295
+ resourceType,
1296
+ resourceId: new ObjectID(command.resourceId),
1297
+ });
1298
+ } catch (error) {
1299
+ logger.error(
1300
+ `CommandPlanExecutor: could not read the AI access status of ${resourceType} ${command.resourceId} before a ${data.purpose}: ${error}`,
1301
+ );
1302
+ return `could not confirm that ${label} still allows AI remediation`;
1303
+ }
1304
+
1305
+ if (!status) {
1306
+ return `${label} no longer exists in this project`;
1307
+ }
1308
+
1309
+ const liveLabel: string = `${noun} "${status.resourceName}"`;
1310
+
1311
+ if (!status.isRemediationReady) {
1312
+ const gap: ResourceAiAccessGap | undefined = status.gaps.find(
1313
+ (candidate: ResourceAiAccessGap): boolean => {
1314
+ return candidate.blocksRemediation;
1315
+ },
1316
+ );
1317
+ return `${liveLabel} no longer allows AI remediation${
1318
+ gap ? ` (${gap.title})` : ""
1319
+ }`;
1320
+ }
1321
+
1322
+ const agentName: string =
1323
+ AI_RESOURCE_TYPE_INFO[resourceType].agentDisplayName;
1324
+
1325
+ if (!status.agent || status.agent.agentId !== command.runnerId) {
1326
+ return `${liveLabel} is no longer reached through the ${agentName} this plan was composed for (the agent was reset or replaced)`;
1327
+ }
1328
+
1329
+ const scopeRefusal: string | null =
1330
+ RemediationCommandToolkit.getResourceWriteScopeRefusal({
1331
+ resource: status,
1332
+ command: data.commandText,
1333
+ });
1334
+
1335
+ if (scopeRefusal) {
1336
+ // The callers end the sentence themselves.
1337
+ return `the ${agentName} would refuse it: ${
1338
+ scopeRefusal.endsWith(".") ? scopeRefusal.slice(0, -1) : scopeRefusal
1339
+ }`;
1340
+ }
1341
+
1342
+ if (data.purpose === "rollback") {
1343
+ const verdict: ResourceAutoExecutionVerdict =
1344
+ ResourceCommandPolicy.evaluateForAutoExecution({
1345
+ resourceType,
1346
+ command: data.commandText,
1347
+ allowlistPatterns: status.aiCommandAllowlist,
1348
+ bypassApproval:
1349
+ status.aiRemediationMode ===
1350
+ ResourceAiRemediationMode.BypassApproval,
1351
+ });
1352
+
1353
+ if (verdict.verdict !== AiRemediationCommandPolicyVerdict.AutoApproved) {
1354
+ return `${liveLabel} no longer allows this change unattended (its AI remediation mode is now ${status.aiRemediationMode}): ${verdict.reason}`;
1355
+ }
1356
+ }
1357
+
1358
+ return null;
1359
+ }
1360
+
1076
1361
  /*
1077
1362
  * The job a command's step ran under, when its record never got the job
1078
1363
  * id. The enqueue and the write that names the job are two steps; a pod
@@ -1123,7 +1408,30 @@ export default class CommandPlanExecutor {
1123
1408
  private static getDenyReason(data: {
1124
1409
  stepType: RunbookStepType;
1125
1410
  command: string;
1411
+ // ResourceCommand only: which resource command policy decides.
1412
+ resourceType?: AiResourceType | undefined;
1126
1413
  }): string | null {
1414
+ /*
1415
+ * A resource command's floor is the Denied tier of its resource's
1416
+ * command policy — never the bash denylist, and never a step whose
1417
+ * resource type is unknown.
1418
+ */
1419
+ if (data.stepType === RunbookStepType.ResourceCommand) {
1420
+ if (!isAiResourceType(data.resourceType)) {
1421
+ return "the resource command names no valid resource type";
1422
+ }
1423
+
1424
+ const resourcePolicy: ResourceCommandPolicyResult =
1425
+ ResourceCommandPolicy.evaluateCommand({
1426
+ resourceType: data.resourceType,
1427
+ command: data.command,
1428
+ });
1429
+
1430
+ return resourcePolicy.tier === ResourceCommandTier.Denied
1431
+ ? resourcePolicy.reason
1432
+ : null;
1433
+ }
1434
+
1127
1435
  if (data.stepType === RunbookStepType.Kubectl) {
1128
1436
  const policy: KubectlPolicyResult = KubectlPolicy.evaluateCommand(
1129
1437
  data.command,
@@ -1224,7 +1532,7 @@ export default class CommandPlanExecutor {
1224
1532
  ? AiRemediationCommandExecutionStatus.Succeeded
1225
1533
  : AiRemediationCommandExecutionStatus.Failed;
1226
1534
  execution.exitCode = job.exitCode;
1227
- execution.output = this.capOutput(job.output || "");
1535
+ execution.output = this.capCommandOutput(job.output || "", command);
1228
1536
  execution.errorMessage = succeeded
1229
1537
  ? undefined
1230
1538
  : job.errorMessage ||
@@ -1303,7 +1611,7 @@ export default class CommandPlanExecutor {
1303
1611
  }
1304
1612
 
1305
1613
  if (isTerminalAgentJobStatus(job.status)) {
1306
- this.settleFromJob(rollback, job, "Rollback");
1614
+ this.settleFromJob(rollback, job, "Rollback", command);
1307
1615
  changed = true;
1308
1616
  }
1309
1617
  } catch (error) {
@@ -1381,7 +1689,7 @@ export default class CommandPlanExecutor {
1381
1689
  }
1382
1690
 
1383
1691
  if (job && job.status === RunnerJobStatus.Succeeded) {
1384
- this.settleFromJob(execution, job, "Command");
1692
+ this.settleFromJob(execution, job, "Command", command);
1385
1693
  changed = true;
1386
1694
  continue;
1387
1695
  }
@@ -1401,6 +1709,81 @@ export default class CommandPlanExecutor {
1401
1709
  return mayHaveRun;
1402
1710
  }
1403
1711
 
1712
+ /*
1713
+ * reconcileFailedKubectlExecutions for resource commands: the ones
1714
+ * recorded as Failed that may nonetheless have changed the resource,
1715
+ * read from their jobs the way ResourceCommandJobRunner reads every
1716
+ * resource job. A job that Succeeded after all is settled from the job
1717
+ * (and so rolled back like any other); one whose run is Unknown, or whose
1718
+ * program ran without finishing (the agent killed it at its timeout), is
1719
+ * returned — its undo is not run blind; one that certainly never ran, or
1720
+ * whose program finished and reported a failure, owes no undo.
1721
+ */
1722
+ private static async reconcileFailedResourceExecutions(
1723
+ suggestion: AutoRemediationSuggestion,
1724
+ plan: AiRemediationCommandPlan,
1725
+ ): Promise<Array<AiRemediationCommand>> {
1726
+ const mayHaveRun: Array<AiRemediationCommand> = [];
1727
+ let changed: boolean = false;
1728
+
1729
+ for (const command of plan.commands) {
1730
+ const execution: AiRemediationCommandExecutionState | undefined =
1731
+ command.execution;
1732
+
1733
+ if (
1734
+ command.stepType !== RunbookStepType.ResourceCommand ||
1735
+ !execution ||
1736
+ execution.status !== AiRemediationCommandExecutionStatus.Failed ||
1737
+ !execution.runnerJobId ||
1738
+ !command.rollbackCommand ||
1739
+ command.rollbackExecution
1740
+ ) {
1741
+ continue;
1742
+ }
1743
+
1744
+ let runState: ResourceCommandRunState = ResourceCommandRunState.Unknown;
1745
+ let job: RunnerJob | null = null;
1746
+
1747
+ try {
1748
+ job = ObjectID.isValidUUID(execution.runnerJobId)
1749
+ ? await RunnerJobService.findOneById({
1750
+ id: new ObjectID(execution.runnerJobId),
1751
+ select: RUN_STATE_JOB_SELECT,
1752
+ props: { isRoot: true },
1753
+ })
1754
+ : null;
1755
+
1756
+ if (job) {
1757
+ runState = ResourceCommandJobRunner.getRunStateOfJobRow(job);
1758
+ }
1759
+ } catch (error) {
1760
+ logger.error(
1761
+ `CommandPlanExecutor: could not read whether resource command ${command.sequence} of suggestion ${suggestion.id?.toString()} ran: ${error}`,
1762
+ );
1763
+ }
1764
+
1765
+ if (job && job.status === RunnerJobStatus.Succeeded) {
1766
+ this.settleFromJob(execution, job, "Command", command);
1767
+ changed = true;
1768
+ continue;
1769
+ }
1770
+
1771
+ const programFinished: boolean =
1772
+ runState === ResourceCommandRunState.Ran &&
1773
+ typeof job?.exitCode === "number";
1774
+
1775
+ if (runState !== ResourceCommandRunState.NotRun && !programFinished) {
1776
+ mayHaveRun.push(command);
1777
+ }
1778
+ }
1779
+
1780
+ if (changed) {
1781
+ await this.persistPlan(suggestion, plan, "rollback");
1782
+ }
1783
+
1784
+ return mayHaveRun;
1785
+ }
1786
+
1404
1787
  private static describeRollbackOutcome(
1405
1788
  plan: AiRemediationCommandPlan | null,
1406
1789
  ): CommandPlanRollbackOutcome {
@@ -157,6 +157,8 @@ export default class RemediationVerifier {
157
157
  ruleNameSnapshot: true,
158
158
  runbookNameSnapshot: true,
159
159
  kubernetesClusterId: true,
160
+ resourceType: true,
161
+ resourceId: true,
160
162
  },
161
163
  limit: 100,
162
164
  skip: 0,
@@ -292,7 +294,19 @@ export default class RemediationVerifier {
292
294
  }
293
295
  }
294
296
 
295
- if (!suggestion.kubernetesClusterId || !suggestion.projectId) {
297
+ /*
298
+ * A resource round (its suggestion names a resource, never a cluster)
299
+ * gets the same follow-up on its resource, on the same terms.
300
+ */
301
+ const isResourceRound: boolean =
302
+ !suggestion.kubernetesClusterId &&
303
+ Boolean(suggestion.resourceType) &&
304
+ Boolean(suggestion.resourceId);
305
+
306
+ if (
307
+ (!suggestion.kubernetesClusterId && !isResourceRound) ||
308
+ !suggestion.projectId
309
+ ) {
296
310
  return;
297
311
  }
298
312
 
@@ -306,9 +320,24 @@ export default class RemediationVerifier {
306
320
  const rollbackIncomplete: boolean =
307
321
  rollback.rollbackStatus === AiRemediationRollbackStatus.Failed;
308
322
 
323
+ if (isResourceRound) {
324
+ await AutoRemediationRuleEngineService.startFollowUpResourceRemediation({
325
+ projectId: suggestion.projectId,
326
+ resourceType: suggestion.resourceType!,
327
+ resourceId: suggestion.resourceId!,
328
+ incidentId: suggestion.incidentId,
329
+ alertId: suggestion.alertId,
330
+ forceSuggest: rollbackIncomplete ? true : undefined,
331
+ forceSuggestReason: rollbackIncomplete
332
+ ? "the previous fix's rollback did not complete, so its change may still be applied"
333
+ : undefined,
334
+ });
335
+ return;
336
+ }
337
+
309
338
  await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
310
339
  projectId: suggestion.projectId,
311
- kubernetesClusterId: suggestion.kubernetesClusterId,
340
+ kubernetesClusterId: suggestion.kubernetesClusterId!,
312
341
  incidentId: suggestion.incidentId,
313
342
  alertId: suggestion.alertId,
314
343
  forceSuggest: rollbackIncomplete ? true : undefined,
@@ -371,6 +400,8 @@ export default class RemediationVerifier {
371
400
  verificationNote: true,
372
401
  ruleNameSnapshot: true,
373
402
  kubernetesClusterId: true,
403
+ resourceType: true,
404
+ resourceId: true,
374
405
  },
375
406
  sort: { verificationCompletedAt: SortOrder.Ascending },
376
407
  limit: ROLLBACK_RESUME_BATCH_SIZE,
@@ -485,6 +516,8 @@ export default class RemediationVerifier {
485
516
  verificationNote: true,
486
517
  ruleNameSnapshot: true,
487
518
  kubernetesClusterId: true,
519
+ resourceType: true,
520
+ resourceId: true,
488
521
  },
489
522
  props: { isRoot: true },
490
523
  });
@@ -162,6 +162,14 @@ export function resolveReferenceIds(value: unknown): Array<ObjectID | string> {
162
162
  return ids;
163
163
  }
164
164
 
165
+ /*
166
+ * Thrown when a payload references another project's records, or records that
167
+ * do not exist. Still a BadDataException with the same message, so API callers
168
+ * see no change; its own type lets a chat reply say something fixed instead of
169
+ * naming another project's record.
170
+ */
171
+ export class ProjectScopedReferenceException extends BadDataException {}
172
+
165
173
  export default class ProjectScopedReferenceValidator {
166
174
  public static async validateReferencesBelongToProject(data: {
167
175
  projectId: ObjectID | undefined;
@@ -354,7 +362,7 @@ export default class ProjectScopedReferenceValidator {
354
362
  return;
355
363
  }
356
364
 
357
- throw new BadDataException(
365
+ throw new ProjectScopedReferenceException(
358
366
  `This ${data.subject || "request"} ${clauses.join(" It also ")}`,
359
367
  );
360
368
  }