@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
@@ -0,0 +1,659 @@
1
+ import { AddResourceAiAgents1796300000000 } from "../../../../Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents";
2
+ import SchemaMigrations from "../../../../Server/Infrastructure/Postgres/SchemaMigrations/Index";
3
+ import AutoRemediationSuggestion from "../../../../Models/DatabaseModels/AutoRemediationSuggestion";
4
+ import CephCluster from "../../../../Models/DatabaseModels/CephCluster";
5
+ import DatabaseServer from "../../../../Models/DatabaseModels/DatabaseServer";
6
+ import DockerHost from "../../../../Models/DatabaseModels/DockerHost";
7
+ import DockerSwarmCluster from "../../../../Models/DatabaseModels/DockerSwarmCluster";
8
+ import Host from "../../../../Models/DatabaseModels/Host";
9
+ import KubernetesAiAgent from "../../../../Models/DatabaseModels/KubernetesAiAgent";
10
+ import KubernetesCluster from "../../../../Models/DatabaseModels/KubernetesCluster";
11
+ import PodmanHost from "../../../../Models/DatabaseModels/PodmanHost";
12
+ import Project from "../../../../Models/DatabaseModels/Project";
13
+ import ProxmoxCluster from "../../../../Models/DatabaseModels/ProxmoxCluster";
14
+ import ResourceAiAgent from "../../../../Models/DatabaseModels/ResourceAiAgent";
15
+ import RunnerJob from "../../../../Models/DatabaseModels/RunnerJob";
16
+ import VMwareVCenter from "../../../../Models/DatabaseModels/VMwareVCenter";
17
+ import AiResourceType, {
18
+ ALL_AI_RESOURCE_TYPES,
19
+ } from "../../../../Types/ResourceAiAgent/AiResourceType";
20
+ import { ResourceAiRemediationMode } from "../../../../Types/ResourceAiAgent/ResourceAiAccess";
21
+ import { describe, expect, test } from "@jest/globals";
22
+ import fs from "fs";
23
+ import path from "path";
24
+ import {
25
+ DefaultNamingStrategy,
26
+ QueryRunner,
27
+ getMetadataArgsStorage,
28
+ } from "typeorm";
29
+ import type { ColumnMetadataArgs } from "typeorm/metadata-args/ColumnMetadataArgs";
30
+ import type { RelationMetadataArgs } from "typeorm/metadata-args/RelationMetadataArgs";
31
+
32
+ /*
33
+ * The resource AI agents' schema: the ResourceAiAgent table, the RunnerJob
34
+ * and AutoRemediationSuggestion resource columns, and the AI access columns
35
+ * of the eight resource models — the resource twin of
36
+ * AddKubernetesAiAgentAndAiDefaultsMigration.test.ts.
37
+ *
38
+ * Pinned here, each a silent regression if it moves on its own:
39
+ *
40
+ * 1. REGISTRATION. The migration is registered once, last, with a
41
+ * timestamp above everything before it, and its class name matches its
42
+ * file.
43
+ * 2. THE SCHEMA IS THE ENTITIES'. Every table, column, index and foreign
44
+ * key is created exactly as the models declare it, with TypeORM's own
45
+ * index and foreign key names (a mismatch is a green deploy and a red
46
+ * Schema Drift job). resourceId has NO foreign key anywhere: it points
47
+ * into a different table for every resourceType.
48
+ * 3. THE DEFAULTS AND THE ENTITIES AGREE. Every resource starts with AI
49
+ * investigation off and remediation Disabled, in the model and in the
50
+ * DDL; the drift job does not reliably catch a DEFAULT that disagrees.
51
+ * 4. NOTHING BUT SCHEMA. No data is rewritten: no resource is switched on
52
+ * for anybody, and no Kubernetes table or column is touched (the
53
+ * Kubernetes AI agent's stack is unchanged).
54
+ * 5. down() REVERSES up() EXACTLY, in reverse order.
55
+ *
56
+ * Fake QueryRunner only.
57
+ */
58
+
59
+ const OWN_CLASS_NAME: string = "AddResourceAiAgents1796300000000";
60
+
61
+ // The last migration registered before this one.
62
+ const REGISTERED_BEFORE_IT: string =
63
+ "AddKubernetesAiAgentAndAiDefaults1796100000000";
64
+
65
+ const MIGRATION_PATH: string = path.join(
66
+ __dirname,
67
+ "../../../../Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.ts",
68
+ );
69
+
70
+ type ModelType = { new (): unknown; name: string };
71
+
72
+ const RESOURCE_MODELS: Record<AiResourceType, ModelType> = {
73
+ [AiResourceType.DockerHost]: DockerHost,
74
+ [AiResourceType.PodmanHost]: PodmanHost,
75
+ [AiResourceType.DockerSwarmCluster]: DockerSwarmCluster,
76
+ [AiResourceType.ProxmoxCluster]: ProxmoxCluster,
77
+ [AiResourceType.VMwareVCenter]: VMwareVCenter,
78
+ [AiResourceType.CephCluster]: CephCluster,
79
+ [AiResourceType.DatabaseServer]: DatabaseServer,
80
+ [AiResourceType.Host]: Host,
81
+ };
82
+
83
+ // The DDL TypeORM emits for each AI access column of a resource model.
84
+ const RESOURCE_AI_COLUMN_DDL: Array<[string, string]> = [
85
+ ["isAiInvestigationEnabled", `boolean NOT NULL DEFAULT false`],
86
+ [
87
+ "aiRemediationMode",
88
+ `character varying(100) NOT NULL DEFAULT '${ResourceAiRemediationMode.Disabled}'`,
89
+ ],
90
+ ["aiCommandAllowlist", `jsonb`],
91
+ ["aiAccessLastVerifiedAt", `TIMESTAMP WITH TIME ZONE`],
92
+ ["aiAccessLastError", `character varying`],
93
+ ["aiAccessConfiguredAt", `TIMESTAMP WITH TIME ZONE`],
94
+ ];
95
+
96
+ const UNIQUE_INDEX: string = `CREATE UNIQUE INDEX "IDX_ResourceAiAgent_projectId_resourceType_resourceId" ON "ResourceAiAgent" ("projectId", "resourceType", "resourceId") WHERE "deletedAt" IS NULL`;
97
+
98
+ const namingStrategy: DefaultNamingStrategy = new DefaultNamingStrategy();
99
+
100
+ const registeredNames: Array<string> = (
101
+ SchemaMigrations as unknown as Array<{ name: string }>
102
+ ).map((migration: { name: string }): string => {
103
+ return migration.name;
104
+ });
105
+
106
+ function timestampOfClassName(className: string): number | null {
107
+ const match: RegExpMatchArray | null = className.match(/(\d{13})$/);
108
+ return match ? Number(match[1]) : null;
109
+ }
110
+
111
+ async function recordQueries(direction: "up" | "down"): Promise<Array<string>> {
112
+ const statements: Array<string> = [];
113
+
114
+ const queryRunner: QueryRunner = {
115
+ query: async (statement: string): Promise<void> => {
116
+ statements.push(statement);
117
+ },
118
+ } as unknown as QueryRunner;
119
+
120
+ await new AddResourceAiAgents1796300000000()[direction](queryRunner);
121
+
122
+ return statements;
123
+ }
124
+
125
+ function declaredColumn(
126
+ model: ModelType,
127
+ property: string,
128
+ ): ColumnMetadataArgs {
129
+ const declared: ColumnMetadataArgs | undefined =
130
+ getMetadataArgsStorage().columns.find(
131
+ (column: ColumnMetadataArgs): boolean => {
132
+ return column.target === model && column.propertyName === property;
133
+ },
134
+ );
135
+
136
+ if (!declared) {
137
+ throw new Error(`${model.name} declares no column ${property}`);
138
+ }
139
+
140
+ return declared;
141
+ }
142
+
143
+ function declaredRelation(
144
+ model: ModelType,
145
+ property: string,
146
+ ): RelationMetadataArgs {
147
+ const declared: RelationMetadataArgs | undefined =
148
+ getMetadataArgsStorage().relations.find(
149
+ (relation: RelationMetadataArgs): boolean => {
150
+ return relation.target === model && relation.propertyName === property;
151
+ },
152
+ );
153
+
154
+ if (!declared) {
155
+ throw new Error(`${model.name} declares no relation ${property}`);
156
+ }
157
+
158
+ return declared;
159
+ }
160
+
161
+ function createIndex(table: string, column: string): string {
162
+ return `CREATE INDEX "${namingStrategy.indexName(table, [
163
+ column,
164
+ ])}" ON "${table}" ("${column}") `;
165
+ }
166
+
167
+ async function createTable(): Promise<string> {
168
+ const statement: string | undefined = (await recordQueries("up")).find(
169
+ (candidate: string): boolean => {
170
+ return candidate.startsWith(`CREATE TABLE "ResourceAiAgent"`);
171
+ },
172
+ );
173
+
174
+ expect(statement).toBeDefined();
175
+
176
+ return statement!;
177
+ }
178
+
179
+ describe("AddResourceAiAgents migration - identity and registration", () => {
180
+ test("its class name and name carry its stamp, matching its file", () => {
181
+ const source: string = fs.readFileSync(MIGRATION_PATH, "utf8");
182
+
183
+ expect(source).toContain(`export class ${OWN_CLASS_NAME}`);
184
+ expect(source).toContain(`public name: string = "${OWN_CLASS_NAME}";`);
185
+ expect(new AddResourceAiAgents1796300000000().name).toBe(OWN_CLASS_NAME);
186
+ });
187
+
188
+ test("its stamp is at least 1796300000000", () => {
189
+ expect(timestampOfClassName(OWN_CLASS_NAME)).toBeGreaterThanOrEqual(
190
+ 1796300000000,
191
+ );
192
+ });
193
+
194
+ test("is registered exactly once", () => {
195
+ expect(SchemaMigrations).toContain(AddResourceAiAgents1796300000000);
196
+ expect(
197
+ registeredNames.filter((name: string): boolean => {
198
+ return name === OWN_CLASS_NAME;
199
+ }),
200
+ ).toHaveLength(1);
201
+ });
202
+
203
+ test("sorts after every migration registered before it", () => {
204
+ const ownIndex: number = registeredNames.indexOf(OWN_CLASS_NAME);
205
+ const ownTimestamp: number = timestampOfClassName(OWN_CLASS_NAME)!;
206
+
207
+ expect(ownIndex).toBeGreaterThan(
208
+ registeredNames.indexOf(REGISTERED_BEFORE_IT),
209
+ );
210
+ expect(registeredNames.indexOf(REGISTERED_BEFORE_IT)).toBeGreaterThan(0);
211
+ expect(
212
+ registeredNames.slice(0, ownIndex).filter((className: string) => {
213
+ const timestamp: number | null = timestampOfClassName(className);
214
+ return timestamp !== null && timestamp >= ownTimestamp;
215
+ }),
216
+ ).toEqual([]);
217
+ });
218
+ });
219
+
220
+ describe("AddResourceAiAgents migration - the ResourceAiAgent table", () => {
221
+ const ownColumns: Array<ColumnMetadataArgs> =
222
+ getMetadataArgsStorage().columns.filter(
223
+ (column: ColumnMetadataArgs): boolean => {
224
+ return column.target === ResourceAiAgent;
225
+ },
226
+ );
227
+
228
+ test("the model declares the columns the design names", () => {
229
+ expect(
230
+ ownColumns
231
+ .map((column: ColumnMetadataArgs): string => {
232
+ return column.propertyName;
233
+ })
234
+ .sort(),
235
+ ).toEqual(
236
+ [
237
+ "projectId",
238
+ "resourceType",
239
+ "resourceId",
240
+ "resourceIdentifier",
241
+ "keyHash",
242
+ "agentVersion",
243
+ "posture",
244
+ "lastAliveAt",
245
+ "connectionStatus",
246
+ "lastRegisteredAt",
247
+ "registeredWithIngestionKeyId",
248
+ "lastRefusedRegistrationAt",
249
+ "lastRefusedRegistrationReason",
250
+ ].sort(),
251
+ );
252
+ });
253
+
254
+ test.each([
255
+ ["projectId", `"projectId" uuid NOT NULL`],
256
+ ["resourceType", `"resourceType" character varying(100) NOT NULL`],
257
+ ["resourceId", `"resourceId" uuid NOT NULL`],
258
+ ["resourceIdentifier", `"resourceIdentifier" character varying(500),`],
259
+ ["keyHash", `"keyHash" character varying(100),`],
260
+ ["agentVersion", `"agentVersion" character varying(100),`],
261
+ ["posture", `"posture" jsonb,`],
262
+ ["lastAliveAt", `"lastAliveAt" TIMESTAMP WITH TIME ZONE,`],
263
+ [
264
+ "connectionStatus",
265
+ `"connectionStatus" character varying(100) NOT NULL DEFAULT 'disconnected'`,
266
+ ],
267
+ ["lastRegisteredAt", `"lastRegisteredAt" TIMESTAMP WITH TIME ZONE,`],
268
+ ["registeredWithIngestionKeyId", `"registeredWithIngestionKeyId" uuid,`],
269
+ [
270
+ "lastRefusedRegistrationAt",
271
+ `"lastRefusedRegistrationAt" TIMESTAMP WITH TIME ZONE,`,
272
+ ],
273
+ [
274
+ "lastRefusedRegistrationReason",
275
+ `"lastRefusedRegistrationReason" character varying(100),`,
276
+ ],
277
+ ])(
278
+ "creates %s as the model declares it",
279
+ async (property: string, ddl: string) => {
280
+ const declared: ColumnMetadataArgs = declaredColumn(
281
+ ResourceAiAgent,
282
+ property,
283
+ );
284
+
285
+ expect(await createTable()).toContain(ddl);
286
+
287
+ if (declared.options.nullable === false) {
288
+ expect(ddl).toContain("NOT NULL");
289
+ } else {
290
+ expect(ddl).not.toContain("NOT NULL");
291
+ }
292
+
293
+ if (declared.options.default !== undefined) {
294
+ expect(ddl).toContain(`DEFAULT '${String(declared.options.default)}'`);
295
+ } else {
296
+ expect(ddl).not.toContain("DEFAULT");
297
+ }
298
+ },
299
+ );
300
+
301
+ /*
302
+ * Column for column the Kubernetes AI agent's table: every column the two
303
+ * share has the same DDL in both migrations' CREATE TABLE.
304
+ */
305
+ test("shares the Kubernetes AI agent's DDL for every column the two tables have in common", async () => {
306
+ const kubernetesMigrationPath: string = path.join(
307
+ __dirname,
308
+ "../../../../Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.ts",
309
+ );
310
+ const kubernetesSource: string = fs.readFileSync(
311
+ kubernetesMigrationPath,
312
+ "utf8",
313
+ );
314
+ const ours: string = await createTable();
315
+ const kubernetesTableAt: number = kubernetesSource.indexOf(
316
+ `CREATE TABLE "KubernetesAiAgent"`,
317
+ );
318
+ expect(kubernetesTableAt).toBeGreaterThan(0);
319
+ const theirs: string = kubernetesSource.slice(
320
+ kubernetesTableAt,
321
+ kubernetesSource.indexOf("\n", kubernetesTableAt),
322
+ );
323
+
324
+ const shared: Array<string> = getMetadataArgsStorage()
325
+ .columns.filter((column: ColumnMetadataArgs): boolean => {
326
+ return column.target === KubernetesAiAgent;
327
+ })
328
+ .map((column: ColumnMetadataArgs): string => {
329
+ return column.propertyName;
330
+ })
331
+ .filter((property: string): boolean => {
332
+ return property !== "kubernetesClusterId";
333
+ });
334
+
335
+ expect(shared.length).toBeGreaterThan(8);
336
+
337
+ const ddlOf: (statement: string, column: string) => string = (
338
+ statement: string,
339
+ column: string,
340
+ ): string => {
341
+ const match: RegExpMatchArray | null = statement.match(
342
+ new RegExp(`"${column}" [^,]*,`),
343
+ );
344
+ expect(match).not.toBeNull();
345
+ return match![0];
346
+ };
347
+
348
+ for (const column of [
349
+ "_id",
350
+ "createdAt",
351
+ "updatedAt",
352
+ "deletedAt",
353
+ "version",
354
+ ...shared,
355
+ ]) {
356
+ expect({ column, ddl: ddlOf(ours, column) }).toEqual({
357
+ column,
358
+ ddl: ddlOf(theirs, column),
359
+ });
360
+ }
361
+ });
362
+
363
+ test("enforces one agent per live resource with the unique index the model names", async () => {
364
+ expect(await recordQueries("up")).toContain(UNIQUE_INDEX);
365
+ });
366
+
367
+ test.each(["projectId", "resourceType", "resourceId"])(
368
+ "indexes %s under TypeORM's name",
369
+ async (column: string) => {
370
+ expect(await recordQueries("up")).toContain(
371
+ createIndex("ResourceAiAgent", column),
372
+ );
373
+ },
374
+ );
375
+
376
+ test("ResourceAiAgent.project goes when its Project row goes (ON DELETE CASCADE)", async () => {
377
+ const declared: RelationMetadataArgs = declaredRelation(
378
+ ResourceAiAgent,
379
+ "project",
380
+ );
381
+
382
+ expect(declared.relationType).toBe("many-to-one");
383
+ expect(declared.options.onDelete).toBe("CASCADE");
384
+ expect((declared.type as () => unknown)()).toBe(Project);
385
+
386
+ expect(await recordQueries("up")).toContain(
387
+ `ALTER TABLE "ResourceAiAgent" ADD CONSTRAINT "${namingStrategy.foreignKeyName(
388
+ "ResourceAiAgent",
389
+ ["projectId"],
390
+ )}" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
391
+ );
392
+ });
393
+
394
+ test("gives resourceId no foreign key: it points into a different table per resource type", async () => {
395
+ for (const statement of await recordQueries("up")) {
396
+ expect(statement).not.toMatch(/FOREIGN KEY \("resourceId"\)/);
397
+ }
398
+ });
399
+
400
+ test("the only foreign key on the new table is its project's", async () => {
401
+ const constraints: Array<string> = (await recordQueries("up")).filter(
402
+ (statement: string): boolean => {
403
+ return statement.startsWith(
404
+ `ALTER TABLE "ResourceAiAgent" ADD CONSTRAINT`,
405
+ );
406
+ },
407
+ );
408
+
409
+ expect(constraints).toHaveLength(1);
410
+ expect(constraints[0]).toContain(`FOREIGN KEY ("projectId")`);
411
+ });
412
+ });
413
+
414
+ describe("AddResourceAiAgents migration - RunnerJob", () => {
415
+ test.each([
416
+ ["targetResourceAiAgentId", "uuid"],
417
+ ["resourceType", "character varying(100)"],
418
+ ["resourceId", "uuid"],
419
+ ])(
420
+ "adds the nullable column %s the model declares",
421
+ async (column: string, ddl: string) => {
422
+ expect(declaredColumn(RunnerJob, column).options.nullable).toBe(true);
423
+ expect(await recordQueries("up")).toContain(
424
+ `ALTER TABLE "RunnerJob" ADD "${column}" ${ddl}`,
425
+ );
426
+ },
427
+ );
428
+
429
+ test.each(["targetResourceAiAgentId", "resourceType", "resourceId"])(
430
+ "indexes %s under TypeORM's name",
431
+ async (column: string) => {
432
+ expect(await recordQueries("up")).toContain(
433
+ createIndex("RunnerJob", column),
434
+ );
435
+ },
436
+ );
437
+
438
+ test("targetResourceAiAgentId references ResourceAiAgent and is nulled, never cascaded, when the agent row goes", async () => {
439
+ const declared: RelationMetadataArgs = declaredRelation(
440
+ RunnerJob,
441
+ "targetResourceAiAgent",
442
+ );
443
+
444
+ expect(declared.relationType).toBe("many-to-one");
445
+ expect(declared.options.onDelete).toBe("SET NULL");
446
+ expect((declared.type as () => unknown)()).toBe(ResourceAiAgent);
447
+
448
+ expect(await recordQueries("up")).toContain(
449
+ `ALTER TABLE "RunnerJob" ADD CONSTRAINT "${namingStrategy.foreignKeyName(
450
+ "RunnerJob",
451
+ ["targetResourceAiAgentId"],
452
+ )}" FOREIGN KEY ("targetResourceAiAgentId") REFERENCES "ResourceAiAgent"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
453
+ );
454
+ });
455
+ });
456
+
457
+ describe("AddResourceAiAgents migration - AutoRemediationSuggestion", () => {
458
+ test.each([
459
+ ["resourceType", "character varying(100)"],
460
+ ["resourceId", "uuid"],
461
+ ])(
462
+ "adds the nullable column %s the model declares, indexed",
463
+ async (column: string, ddl: string) => {
464
+ const up: Array<string> = await recordQueries("up");
465
+
466
+ expect(
467
+ declaredColumn(AutoRemediationSuggestion, column).options.nullable,
468
+ ).toBe(true);
469
+ expect(up).toContain(
470
+ `ALTER TABLE "AutoRemediationSuggestion" ADD "${column}" ${ddl}`,
471
+ );
472
+ expect(up).toContain(createIndex("AutoRemediationSuggestion", column));
473
+ },
474
+ );
475
+ });
476
+
477
+ describe("AddResourceAiAgents migration - the resource models' AI access columns", () => {
478
+ const cases: Array<[string, ModelType, string, string]> =
479
+ ALL_AI_RESOURCE_TYPES.flatMap(
480
+ (type: AiResourceType): Array<[string, ModelType, string, string]> => {
481
+ return RESOURCE_AI_COLUMN_DDL.map(
482
+ ([column, ddl]: [string, string]): [
483
+ string,
484
+ ModelType,
485
+ string,
486
+ string,
487
+ ] => {
488
+ return [type, RESOURCE_MODELS[type], column, ddl];
489
+ },
490
+ );
491
+ },
492
+ );
493
+
494
+ test.each(cases)(
495
+ "%s gains %p as the model declares it",
496
+ async (
497
+ type: string,
498
+ model: ModelType,
499
+ column: string,
500
+ ddl: string,
501
+ ): Promise<void> => {
502
+ const declared: ColumnMetadataArgs = declaredColumn(model, column);
503
+
504
+ expect(await recordQueries("up")).toContain(
505
+ `ALTER TABLE "${type}" ADD "${column}" ${ddl}`,
506
+ );
507
+
508
+ if (declared.options.nullable === false) {
509
+ expect(ddl).toContain("NOT NULL");
510
+ } else {
511
+ expect(ddl).not.toContain("NOT NULL");
512
+ }
513
+
514
+ if (typeof declared.options.default === "string") {
515
+ expect(ddl).toContain(`DEFAULT '${declared.options.default}'`);
516
+ } else if (declared.options.default !== undefined) {
517
+ expect(ddl).toContain(`DEFAULT ${String(declared.options.default)}`);
518
+ } else {
519
+ expect(ddl).not.toContain("DEFAULT");
520
+ }
521
+ },
522
+ );
523
+
524
+ test("every resource starts with investigation off and remediation Disabled", async () => {
525
+ const up: Array<string> = await recordQueries("up");
526
+
527
+ for (const type of ALL_AI_RESOURCE_TYPES) {
528
+ expect(up).toContain(
529
+ `ALTER TABLE "${type}" ADD "isAiInvestigationEnabled" boolean NOT NULL DEFAULT false`,
530
+ );
531
+ expect(up).toContain(
532
+ `ALTER TABLE "${type}" ADD "aiRemediationMode" character varying(100) NOT NULL DEFAULT 'Disabled'`,
533
+ );
534
+ }
535
+ });
536
+
537
+ test("adds nothing else to the resource tables", async () => {
538
+ const up: Array<string> = await recordQueries("up");
539
+
540
+ for (const type of ALL_AI_RESOURCE_TYPES) {
541
+ const touching: Array<string> = up.filter(
542
+ (statement: string): boolean => {
543
+ return statement.includes(`"${type}"`);
544
+ },
545
+ );
546
+
547
+ expect(touching).toHaveLength(RESOURCE_AI_COLUMN_DDL.length);
548
+ }
549
+ });
550
+ });
551
+
552
+ describe("AddResourceAiAgents migration - scope", () => {
553
+ test("only changes the schema: no data is rewritten", async () => {
554
+ for (const statement of await recordQueries("up")) {
555
+ expect(statement).not.toMatch(/^(UPDATE|INSERT|DELETE) /);
556
+ }
557
+ });
558
+
559
+ test("leaves the Kubernetes AI agent's tables and columns alone", async () => {
560
+ const kubernetesTables: Array<string> = [
561
+ new KubernetesAiAgent() as unknown as { tableName: string },
562
+ new KubernetesCluster() as unknown as { tableName: string },
563
+ ].map((model: { tableName: string }): string => {
564
+ return model.tableName;
565
+ });
566
+
567
+ for (const statement of [
568
+ ...(await recordQueries("up")),
569
+ ...(await recordQueries("down")),
570
+ ]) {
571
+ for (const table of kubernetesTables) {
572
+ expect(statement).not.toContain(`"${table}"`);
573
+ }
574
+ expect(statement).not.toMatch(
575
+ /"(targetKubernetesAiAgentId|kubernetesClusterId)"/,
576
+ );
577
+ }
578
+ });
579
+
580
+ test("touches exactly the tables the design names", async () => {
581
+ const tables: Set<string> = new Set<string>();
582
+
583
+ for (const statement of await recordQueries("up")) {
584
+ const match: RegExpMatchArray | null = statement.match(
585
+ /^(?:CREATE TABLE|ALTER TABLE|CREATE (?:UNIQUE )?INDEX "[^"]+" ON) "([^"]+)"/,
586
+ );
587
+ expect(match).not.toBeNull();
588
+ tables.add(match![1]!);
589
+ }
590
+
591
+ expect([...tables].sort()).toEqual(
592
+ [
593
+ "ResourceAiAgent",
594
+ "RunnerJob",
595
+ "AutoRemediationSuggestion",
596
+ ...ALL_AI_RESOURCE_TYPES,
597
+ ].sort(),
598
+ );
599
+ });
600
+ });
601
+
602
+ describe("AddResourceAiAgents migration - down()", () => {
603
+ // The inverse of every statement of up(), in reverse order.
604
+ test("undoes exactly what up() did, in reverse order", async () => {
605
+ const up: Array<string> = await recordQueries("up");
606
+
607
+ const inverse: Array<string> = up
608
+ .map((statement: string): string => {
609
+ const constraint: RegExpMatchArray | null = statement.match(
610
+ /^ALTER TABLE "([^"]+)" ADD CONSTRAINT "([^"]+)"/,
611
+ );
612
+ if (constraint) {
613
+ return `ALTER TABLE "${constraint[1]}" DROP CONSTRAINT "${constraint[2]}"`;
614
+ }
615
+
616
+ const index: RegExpMatchArray | null = statement.match(
617
+ /^CREATE (?:UNIQUE )?INDEX "([^"]+)"/,
618
+ );
619
+ if (index) {
620
+ return `DROP INDEX "public"."${index[1]}"`;
621
+ }
622
+
623
+ const column: RegExpMatchArray | null = statement.match(
624
+ /^ALTER TABLE "([^"]+)" ADD "([^"]+)"/,
625
+ );
626
+ if (column) {
627
+ return `ALTER TABLE "${column[1]}" DROP COLUMN "${column[2]}"`;
628
+ }
629
+
630
+ const table: RegExpMatchArray | null = statement.match(
631
+ /^CREATE TABLE "([^"]+)"/,
632
+ );
633
+ if (table) {
634
+ return `DROP TABLE "${table[1]}"`;
635
+ }
636
+
637
+ throw new Error(
638
+ `up() ran a statement with no known inverse: ${statement}`,
639
+ );
640
+ })
641
+ .reverse();
642
+
643
+ expect(await recordQueries("down")).toEqual(inverse);
644
+ });
645
+
646
+ test("drops the table last, after everything that references it", async () => {
647
+ const down: Array<string> = await recordQueries("down");
648
+
649
+ expect(down[down.length - 1]).toBe(`DROP TABLE "ResourceAiAgent"`);
650
+ expect(
651
+ down.indexOf(
652
+ `ALTER TABLE "RunnerJob" DROP CONSTRAINT "${namingStrategy.foreignKeyName(
653
+ "RunnerJob",
654
+ ["targetResourceAiAgentId"],
655
+ )}"`,
656
+ ),
657
+ ).toBe(0);
658
+ });
659
+ });
@@ -90,6 +90,37 @@ describe("Semaphore exclusive mutex", () => {
90
90
  expect(mutex).toBe(lastMockMutex());
91
91
  });
92
92
 
93
+ /*
94
+ * A long sweep that polls mutex.isAcquired between pages needs both: a
95
+ * refresh interval short enough for the flag to be current (it only turns
96
+ * false when a refresh finds the lock gone), and a lock-lost handler, or
97
+ * redis-semaphore throws from its refresh timer where nothing can catch it.
98
+ */
99
+ test("forwards refreshInterval and onLockLost when the caller sets them", async () => {
100
+ const client: ClientType = mockRedisClient();
101
+ const onLockLost: (err: Error) => void = (): void => {};
102
+
103
+ await Semaphore.lock({
104
+ key: "Rum:PublishSessionReplayBudgetMetrics",
105
+ namespace: "Workers.Cron",
106
+ lockTimeout: 240_000,
107
+ acquireAttemptsLimit: 1,
108
+ refreshInterval: 30_000,
109
+ onLockLost: onLockLost,
110
+ });
111
+
112
+ expect(redisMutexConstructor).toHaveBeenCalledWith(
113
+ client,
114
+ "Workers.Cron-Rum:PublishSessionReplayBudgetMetrics",
115
+ {
116
+ lockTimeout: 240_000,
117
+ acquireAttemptsLimit: 1,
118
+ refreshInterval: 30_000,
119
+ onLockLost: onLockLost,
120
+ },
121
+ );
122
+ });
123
+
93
124
  test("composes the Redis key as namespace-key", async () => {
94
125
  mockRedisClient();
95
126