@oneuptime/common 12.0.4 → 12.0.5

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 (374) hide show
  1. package/Models/DatabaseModels/AIRun.ts +38 -1
  2. package/Models/DatabaseModels/AlertFeed.ts +30 -0
  3. package/Models/DatabaseModels/Dashboard.ts +28 -0
  4. package/Models/DatabaseModels/Incident.ts +2 -0
  5. package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
  6. package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
  7. package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
  8. package/Models/DatabaseModels/IncidentFeed.ts +30 -0
  9. package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
  10. package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
  11. package/Models/DatabaseModels/LogSavedView.ts +33 -0
  12. package/Models/DatabaseModels/Project.ts +231 -9
  13. package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
  14. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
  15. package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
  16. package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.ts +4 -4
  17. package/Models/DatabaseModels/StatusPage.ts +28 -0
  18. package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
  19. package/Server/API/AIAgentDataAPI.ts +44 -55
  20. package/Server/API/AIInvestigationAPI.ts +175 -17
  21. package/Server/API/DashboardAPI.ts +10 -10
  22. package/Server/API/StatusPageAPI.ts +38 -19
  23. package/Server/EnvironmentConfig.ts +16 -0
  24. package/Server/Infrastructure/ClickhouseConfig.ts +15 -1
  25. package/Server/Infrastructure/ClickhouseDatabase.ts +1 -1
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.ts +27 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.ts +89 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.ts +27 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.ts +40 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.ts +26 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  32. package/Server/Services/AIRunService.ts +78 -10
  33. package/Server/Services/AIService.ts +94 -22
  34. package/Server/Services/AlertFeedService.ts +5 -0
  35. package/Server/Services/AnalyticsDatabaseService.ts +29 -0
  36. package/Server/Services/DatabaseService.ts +43 -2
  37. package/Server/Services/IncidentFeedService.ts +5 -0
  38. package/Server/Services/LlmLogService.ts +46 -2
  39. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +6 -0
  40. package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +4 -0
  41. package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +8 -5
  42. package/Server/Utils/AI/CodeFix/FixRunBudget.ts +90 -16
  43. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +2 -0
  44. package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +2 -0
  45. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +223 -22
  46. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +25 -24
  47. package/Server/Utils/AI/SRE/ConfidenceSignal.ts +182 -71
  48. package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +252 -43
  49. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +25 -24
  50. package/Server/Utils/AI/SRE/InstrumentationTaskTrigger.ts +47 -13
  51. package/Server/Utils/AI/SRE/InvestigationGrader.ts +9 -5
  52. package/Server/Utils/AI/SRE/InvestigationQueue.ts +141 -24
  53. package/Server/Utils/AI/SRE/InvestigationSubjectLock.ts +66 -0
  54. package/Server/Utils/AI/SRE/PostedRootCause.ts +94 -3
  55. package/Server/Utils/AI/SRE/README.md +1 -1
  56. package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +132 -10
  57. package/Server/Utils/AnalyticsDatabase/ClusterConfig.ts +24 -0
  58. package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +29 -0
  59. package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +56 -0
  60. package/Server/Utils/Monitor/MonitorMetricUtil.ts +46 -0
  61. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -0
  62. package/Server/Utils/PasswordHash.ts +28 -4
  63. package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +251 -0
  64. package/Tests/App/Dashboard/EventStatusPanel.test.tsx +747 -0
  65. package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +480 -0
  66. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1184 -0
  67. package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +500 -0
  68. package/Tests/App/Dashboard/PortMonitorCriteriaFilter.test.ts +93 -0
  69. package/Tests/App/StatusPage/PublicStatusPageAPIErrorHandling.test.ts +117 -0
  70. package/Tests/App/StatusPage/StatusPageModelAPIPolymorphism.test.ts +223 -0
  71. package/Tests/Models/DatabaseModels/PermissionCatalogueCoverage.test.ts +243 -0
  72. package/Tests/Server/API/AIAgentDataFixFromIncidentContext.test.ts +266 -0
  73. package/Tests/Server/API/AIInvestigationAPI.test.ts +594 -0
  74. package/Tests/Server/API/AIInvestigationCreateFixTask.test.ts +80 -0
  75. package/Tests/Server/API/DashboardMasterPasswordAPI.test.ts +172 -1
  76. package/Tests/Server/API/StatusPageMasterPasswordAPI.test.ts +335 -0
  77. package/Tests/Server/Services/AIRunCodeFixClaim.test.ts +59 -5
  78. package/Tests/Server/Services/AIRunHumanVerdict.test.ts +127 -58
  79. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +396 -20
  80. package/Tests/Server/Services/AddMasterPasswordSaltMigration.test.ts +283 -0
  81. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +25 -1
  82. package/Tests/Server/Services/DatabaseServicePerUserPasswordSalt.test.ts +45 -35
  83. package/Tests/Server/Services/DatabaseServiceUpdateColumnsWithoutHooks.test.ts +54 -0
  84. package/Tests/Server/Services/FeedAIRunAssociation.test.ts +125 -0
  85. package/Tests/Server/Services/FixFromIncidentTaskTrigger.test.ts +418 -57
  86. package/Tests/Server/Services/InstrumentationTaskTrigger.test.ts +173 -14
  87. package/Tests/Server/Services/MasterPasswordScrypt.test.ts +567 -0
  88. package/Tests/Server/Services/SeparateIncidentAlertAiSettingsMigration.test.ts +194 -0
  89. package/Tests/Server/Utils/AI/AIAlertGating.test.ts +37 -4
  90. package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +330 -29
  91. package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +25 -0
  92. package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +293 -5
  93. package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +59 -1
  94. package/Tests/Server/Utils/AI/FixFromIncidentAutoTrigger.test.ts +342 -19
  95. package/Tests/Server/Utils/AI/FixRunBudget.test.ts +214 -30
  96. package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +2 -0
  97. package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +65 -17
  98. package/Tests/Server/Utils/AI/InvestigationQueueRemediationExecution.test.ts +3 -0
  99. package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +313 -20
  100. package/Tests/Server/Utils/AI/PostedRootCause.test.ts +254 -0
  101. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +4 -0
  102. package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +2 -0
  103. package/Tests/Server/Utils/AI/SubjectCodeFixRunDedupe.test.ts +44 -0
  104. package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +30 -0
  105. package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +212 -0
  106. package/Tests/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.test.ts +401 -0
  107. package/Tests/Server/Utils/Monitor/MonitorMetricUtilPortTimings.test.ts +243 -0
  108. package/Tests/Server/Utils/PasswordHash.test.ts +30 -0
  109. package/Tests/Types/Dashboard/DashboardTemplates.test.ts +111 -0
  110. package/Tests/Types/Monitor/CephMetricCatalog.test.ts +104 -0
  111. package/Tests/Types/Monitor/CriteriaFilter.test.ts +4 -0
  112. package/Tests/Types/Monitor/DockerMetricCatalog.test.ts +109 -0
  113. package/Tests/Types/Monitor/DockerSwarmMetricCatalog.test.ts +118 -0
  114. package/Tests/Types/Monitor/HostMetricCatalog.test.ts +104 -0
  115. package/Tests/Types/Monitor/IotMetricCatalog.test.ts +104 -0
  116. package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +118 -0
  117. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +42 -0
  118. package/Tests/Types/Monitor/MonitorStep.test.ts +38 -0
  119. package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +75 -0
  120. package/Tests/Types/Monitor/PodmanMetricCatalog.test.ts +109 -0
  121. package/Tests/Types/Monitor/ProxmoxMetricCatalog.test.ts +107 -0
  122. package/Tests/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.test.ts +151 -0
  123. package/Tests/Types/Permission.test.ts +137 -0
  124. package/Tests/Types/Rum/SessionReplayMaskingMode.test.ts +101 -0
  125. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +5 -5
  126. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +3 -5
  127. package/Tests/UI/Components/ErrorBoundary.test.tsx +158 -0
  128. package/Tests/UI/Components/FeedItemSafeMode.test.tsx +74 -0
  129. package/Tests/UI/Components/MoreMenu.test.tsx +756 -0
  130. package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +62 -0
  131. package/Tests/UI/Monitor/PortMonitorView.test.tsx +237 -0
  132. package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +91 -0
  133. package/Tests/UI/Utils/DownloadFile.test.ts +103 -0
  134. package/Tests/UI/Utils/ErrorSupportBundle.test.ts +582 -0
  135. package/Tests/UI/Utils/Project.test.ts +31 -0
  136. package/Tests/UI/Utils/StatusPageModelAPIInjection.test.ts +245 -0
  137. package/Tests/UI/Utils/UseDashboardGridDnd.test.tsx +820 -0
  138. package/Tests/Utils/Dashboard/DashboardViewConfig.test.ts +329 -0
  139. package/Tests/Utils/Dashboard/GridLayout.test.ts +951 -0
  140. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +117 -0
  141. package/Tests/Utils/RecordingRuleExpression.test.ts +327 -0
  142. package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +186 -0
  143. package/Tests/Utils/StatusPage/GroupTree.test.ts +456 -0
  144. package/Tests/Utils/StatusPage/OverviewGroupHierarchyVisibility.test.ts +588 -0
  145. package/Tests/Utils/Telemetry/SavedViewTimeRange.test.ts +244 -0
  146. package/Tests/Utils/Telemetry/TelemetryQueryTimeRange.test.ts +825 -0
  147. package/Types/AI/AIRunCodeFixRecommendation.ts +17 -0
  148. package/Types/AI/CodeFixTaskContext.ts +63 -3
  149. package/Types/AI/CodeFixTaskType.ts +3 -3
  150. package/Types/HashedString.ts +4 -3
  151. package/Types/Monitor/CriteriaFilter.ts +4 -0
  152. package/Types/Monitor/DomainMonitor/DomainLookupMethod.ts +23 -0
  153. package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +7 -0
  154. package/Types/Monitor/MonitorCriteriaInstance.ts +24 -7
  155. package/Types/Monitor/MonitorMetricType.ts +8 -0
  156. package/Types/Monitor/MonitorStep.ts +10 -1
  157. package/Types/Monitor/MonitorStepDomainMonitor.ts +21 -0
  158. package/Types/Monitor/PortMonitor/PortMonitorTimings.ts +10 -0
  159. package/Types/Permission.ts +23 -175
  160. package/Types/Probe/ProbeMonitorResponse.ts +6 -0
  161. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +2 -3
  162. package/UI/Components/ErrorBoundary.tsx +138 -11
  163. package/UI/Components/Feed/FeedItem.tsx +9 -2
  164. package/UI/Components/ModelDetail/CardModelDetail.tsx +0 -12
  165. package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
  166. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +12 -2
  167. package/UI/Components/MoreMenu/MoreMenu.tsx +285 -97
  168. package/UI/Components/MoreMenu/MoreMenuItem.tsx +8 -5
  169. package/UI/Utils/DownloadFile.ts +16 -8
  170. package/UI/Utils/ErrorSupportBundle.ts +805 -0
  171. package/UI/Utils/ModelAPI/ModelAPI.ts +19 -8
  172. package/UI/Utils/Project.ts +4 -0
  173. package/UI/Utils/StatusPage.ts +8 -2
  174. package/UI/Utils/UseDashboardGridDnd.ts +917 -0
  175. package/Utils/Dashboard/DashboardViewConfig.ts +80 -36
  176. package/Utils/Dashboard/GridLayout.ts +523 -0
  177. package/Utils/Metrics/RecordingRuleExpression.ts +19 -17
  178. package/Utils/Monitor/MonitorMetricType.ts +44 -2
  179. package/Utils/StatusPage/GroupNestingLayout.ts +69 -0
  180. package/Utils/StatusPage/GroupTree.ts +157 -66
  181. package/Utils/StatusPage/ResourceUptime.ts +37 -2
  182. package/Utils/Telemetry/SavedViewTimeRange.ts +114 -0
  183. package/Utils/Telemetry/TelemetryQueryTimeRange.ts +334 -0
  184. package/build/dist/Models/DatabaseModels/AIRun.js +39 -1
  185. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  186. package/build/dist/Models/DatabaseModels/AlertFeed.js +32 -0
  187. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  188. package/build/dist/Models/DatabaseModels/Dashboard.js +29 -0
  189. package/build/dist/Models/DatabaseModels/Dashboard.js.map +1 -1
  190. package/build/dist/Models/DatabaseModels/Incident.js +2 -0
  191. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  192. package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
  193. package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
  194. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
  195. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
  196. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
  197. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
  198. package/build/dist/Models/DatabaseModels/IncidentFeed.js +32 -0
  199. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
  200. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
  201. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  202. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
  203. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/LogSavedView.js +33 -0
  205. package/build/dist/Models/DatabaseModels/LogSavedView.js.map +1 -1
  206. package/build/dist/Models/DatabaseModels/Project.js +241 -11
  207. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  208. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
  209. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
  211. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  212. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
  213. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
  214. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js +4 -4
  215. package/build/dist/Models/DatabaseModels/StatusPage.js +29 -0
  216. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  217. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
  218. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  219. package/build/dist/Server/API/AIAgentDataAPI.js +28 -46
  220. package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
  221. package/build/dist/Server/API/AIInvestigationAPI.js +111 -11
  222. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  223. package/build/dist/Server/API/DashboardAPI.js +8 -5
  224. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  225. package/build/dist/Server/API/StatusPageAPI.js +29 -11
  226. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  227. package/build/dist/Server/EnvironmentConfig.js +14 -0
  228. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  229. package/build/dist/Server/Infrastructure/ClickhouseConfig.js +12 -1
  230. package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
  231. package/build/dist/Server/Infrastructure/ClickhouseDatabase.js +1 -1
  232. package/build/dist/Server/Infrastructure/ClickhouseDatabase.js.map +1 -1
  233. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js +22 -0
  234. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js.map +1 -0
  235. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js +36 -0
  236. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js.map +1 -0
  237. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js +18 -0
  238. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js.map +1 -0
  239. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js +19 -0
  240. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js.map +1 -0
  241. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js +19 -0
  242. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js.map +1 -0
  243. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  244. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  245. package/build/dist/Server/Services/AIRunService.js +58 -12
  246. package/build/dist/Server/Services/AIRunService.js.map +1 -1
  247. package/build/dist/Server/Services/AIService.js +74 -21
  248. package/build/dist/Server/Services/AIService.js.map +1 -1
  249. package/build/dist/Server/Services/AlertFeedService.js +3 -0
  250. package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
  251. package/build/dist/Server/Services/AnalyticsDatabaseService.js +29 -1
  252. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  253. package/build/dist/Server/Services/DatabaseService.js +21 -2
  254. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  255. package/build/dist/Server/Services/IncidentFeedService.js +3 -0
  256. package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
  257. package/build/dist/Server/Services/LlmLogService.js +22 -1
  258. package/build/dist/Server/Services/LlmLogService.js.map +1 -1
  259. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +3 -0
  260. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  261. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +4 -0
  262. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
  263. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +8 -5
  264. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
  265. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +63 -24
  266. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
  267. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +2 -0
  268. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  269. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +2 -0
  270. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
  271. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +156 -28
  272. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  273. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +21 -19
  274. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  275. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +128 -49
  276. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -1
  277. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +170 -31
  278. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -1
  279. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +21 -19
  280. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  281. package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js +33 -9
  282. package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js.map +1 -1
  283. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +9 -5
  284. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
  285. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +121 -41
  286. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  287. package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js +46 -0
  288. package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js.map +1 -0
  289. package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js +61 -14
  290. package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js.map +1 -1
  291. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +79 -1
  292. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -1
  293. package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js +21 -0
  294. package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js.map +1 -1
  295. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +20 -3
  296. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
  297. package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +43 -0
  298. package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
  299. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
  300. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  301. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -0
  302. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  303. package/build/dist/Server/Utils/PasswordHash.js +25 -4
  304. package/build/dist/Server/Utils/PasswordHash.js.map +1 -1
  305. package/build/dist/Types/AI/AIRunCodeFixRecommendation.js +18 -0
  306. package/build/dist/Types/AI/AIRunCodeFixRecommendation.js.map +1 -0
  307. package/build/dist/Types/AI/CodeFixTaskContext.js +23 -3
  308. package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -1
  309. package/build/dist/Types/AI/CodeFixTaskType.js +3 -3
  310. package/build/dist/Types/HashedString.js +4 -3
  311. package/build/dist/Types/HashedString.js.map +1 -1
  312. package/build/dist/Types/Monitor/CriteriaFilter.js +4 -0
  313. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  314. package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js +24 -0
  315. package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js.map +1 -0
  316. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +24 -7
  317. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  318. package/build/dist/Types/Monitor/MonitorMetricType.js +7 -0
  319. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  320. package/build/dist/Types/Monitor/MonitorStep.js +6 -1
  321. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  322. package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js +15 -0
  323. package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
  324. package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js +2 -0
  325. package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js.map +1 -0
  326. package/build/dist/Types/Permission.js +23 -155
  327. package/build/dist/Types/Permission.js.map +1 -1
  328. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +2 -5
  329. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  330. package/build/dist/UI/Components/ErrorBoundary.js +67 -8
  331. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  332. package/build/dist/UI/Components/Feed/FeedItem.js +2 -2
  333. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  334. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +0 -12
  335. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  336. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
  337. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  338. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +12 -2
  339. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  340. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +193 -65
  341. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  342. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +1 -1
  343. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
  344. package/build/dist/UI/Utils/DownloadFile.js +15 -8
  345. package/build/dist/UI/Utils/DownloadFile.js.map +1 -1
  346. package/build/dist/UI/Utils/ErrorSupportBundle.js +476 -0
  347. package/build/dist/UI/Utils/ErrorSupportBundle.js.map +1 -0
  348. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -8
  349. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  350. package/build/dist/UI/Utils/Project.js +3 -0
  351. package/build/dist/UI/Utils/Project.js.map +1 -1
  352. package/build/dist/UI/Utils/StatusPage.js +4 -4
  353. package/build/dist/UI/Utils/StatusPage.js.map +1 -1
  354. package/build/dist/UI/Utils/UseDashboardGridDnd.js +551 -0
  355. package/build/dist/UI/Utils/UseDashboardGridDnd.js.map +1 -0
  356. package/build/dist/Utils/Dashboard/DashboardViewConfig.js +42 -26
  357. package/build/dist/Utils/Dashboard/DashboardViewConfig.js.map +1 -1
  358. package/build/dist/Utils/Dashboard/GridLayout.js +338 -0
  359. package/build/dist/Utils/Dashboard/GridLayout.js.map +1 -0
  360. package/build/dist/Utils/Metrics/RecordingRuleExpression.js +19 -17
  361. package/build/dist/Utils/Metrics/RecordingRuleExpression.js.map +1 -1
  362. package/build/dist/Utils/Monitor/MonitorMetricType.js +38 -6
  363. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  364. package/build/dist/Utils/StatusPage/GroupNestingLayout.js +46 -0
  365. package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -1
  366. package/build/dist/Utils/StatusPage/GroupTree.js +79 -34
  367. package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -1
  368. package/build/dist/Utils/StatusPage/ResourceUptime.js +22 -1
  369. package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
  370. package/build/dist/Utils/Telemetry/SavedViewTimeRange.js +79 -0
  371. package/build/dist/Utils/Telemetry/SavedViewTimeRange.js.map +1 -0
  372. package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js +236 -0
  373. package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js.map +1 -0
  374. package/package.json +1 -1
@@ -155,19 +155,32 @@ export const AI_REMEDIATION_EXECUTION_FEATURE: string =
155
155
  * (SQL `= ANY`, and an `.includes()` gate on the write path that no writer can
156
156
  * trip because no writer emits these strings any more).
157
157
  */
158
+ const LEGACY_SENTINEL_INCIDENT_INVESTIGATION_FEATURE: string =
159
+ "Sentinel Incident Investigation";
160
+ const LEGACY_SENTINEL_ALERT_INVESTIGATION_FEATURE: string =
161
+ "Sentinel Alert Investigation";
162
+ const LEGACY_SENTINEL_INVESTIGATION_GRADING_FEATURE: string =
163
+ "Sentinel Investigation Grading";
164
+ const LEGACY_SENTINEL_CONFIDENCE_CLASSIFICATION_FEATURE: string =
165
+ "Sentinel Confidence Classification";
166
+ const LEGACY_SENTINEL_CODE_FIX_FEATURE: string = "Sentinel Code Fix";
167
+ const LEGACY_SENTINEL_INSIGHT_TRIAGE_FEATURE: string =
168
+ "Sentinel Insight Triage";
169
+
158
170
  export const LEGACY_AUTONOMOUS_AI_FEATURES: Array<string> = [
159
- "Sentinel Incident Investigation",
160
- "Sentinel Alert Investigation",
161
- "Sentinel Investigation Grading",
162
- "Sentinel Confidence Classification",
163
- "Sentinel Code Fix",
164
- "Sentinel Insight Triage",
171
+ LEGACY_SENTINEL_INCIDENT_INVESTIGATION_FEATURE,
172
+ LEGACY_SENTINEL_ALERT_INVESTIGATION_FEATURE,
173
+ LEGACY_SENTINEL_INVESTIGATION_GRADING_FEATURE,
174
+ LEGACY_SENTINEL_CONFIDENCE_CLASSIFICATION_FEATURE,
175
+ LEGACY_SENTINEL_CODE_FIX_FEATURE,
176
+ LEGACY_SENTINEL_INSIGHT_TRIAGE_FEATURE,
165
177
  ];
166
178
 
167
179
  /*
168
- * Features that run WITHOUT a human in the loop. The per-project daily token
169
- * budget (Project.aiDailyAutonomousTokenLimit, G4) applies only to these
170
- * interactive chat and explicitly user-triggered AI are never budget-blocked.
180
+ * Features that run WITHOUT a human in the loop. Incident-linked and
181
+ * alert-linked calls use their respective daily token limits; subjectless
182
+ * calls use Project.aiDailyAutonomousTokenLimit. Interactive chat and
183
+ * explicitly user-triggered AI are never budget-blocked.
171
184
  * Auto-postmortem is deliberately excluded for now: it is one call per
172
185
  * resolved incident, not storm-shaped; include it when it moves to the queue.
173
186
  *
@@ -188,7 +201,7 @@ export const AUTONOMOUS_AI_FEATURES: Array<string> = [
188
201
  * user-triggered, but the tool loop then runs unattended for up to ~40
189
202
  * calls — storm-shaped enough that the daily budget must cover it. The
190
203
  * per-run loop budgets (CodeFixAgentCompletion) cap a single run; this
191
- * daily pool caps all of them together.
204
+ * daily subject lane caps all of them together.
192
205
  */
193
206
  AI_CODE_FIX_FEATURE,
194
207
  /*
@@ -215,7 +228,7 @@ export const AUTONOMOUS_AI_FEATURES: Array<string> = [
215
228
  /*
216
229
  * Auto-remediation command composition/execution
217
230
  * (RemediationExecutionRunner). Same trigger shape as planning, with a
218
- * larger per-run tool budget — the daily pool must cover it.
231
+ * larger per-run tool budget — the daily subject lane must cover it.
219
232
  */
220
233
  AI_REMEDIATION_EXECUTION_FEATURE,
221
234
  /*
@@ -226,6 +239,23 @@ export const AUTONOMOUS_AI_FEATURES: Array<string> = [
226
239
  ...LEGACY_AUTONOMOUS_AI_FEATURES,
227
240
  ];
228
241
 
242
+ /*
243
+ * Before subject-lane accounting shipped, the main investigation calls did
244
+ * not persist incidentId/alertId (or aiRunId). Their feature label is the only
245
+ * durable lane signal left on those rows. Keep these lists so a deployment
246
+ * does not reset today's incident/alert spend or charge it to background work.
247
+ */
248
+ const LEGACY_INCIDENT_LANE_FEATURES: Array<string> = [
249
+ AI_INCIDENT_INVESTIGATION_FEATURE,
250
+ AI_INVESTIGATION_GRADING_FEATURE,
251
+ LEGACY_SENTINEL_INCIDENT_INVESTIGATION_FEATURE,
252
+ LEGACY_SENTINEL_INVESTIGATION_GRADING_FEATURE,
253
+ ];
254
+ const LEGACY_ALERT_LANE_FEATURES: Array<string> = [
255
+ AI_ALERT_INVESTIGATION_FEATURE,
256
+ LEGACY_SENTINEL_ALERT_INVESTIGATION_FEATURE,
257
+ ];
258
+
229
259
  export interface AutonomousBudgetStatus {
230
260
  exhausted: boolean;
231
261
  // null when the project has no limit configured.
@@ -237,10 +267,10 @@ export interface AILogRequest {
237
267
  projectId: ObjectID;
238
268
  userId?: ObjectID | undefined;
239
269
  feature: string; // e.g., "IncidentPostmortem", "IncidentNote"
240
- incidentId?: ObjectID;
241
- alertId?: ObjectID;
242
- scheduledMaintenanceId?: ObjectID;
243
- aiRunId?: ObjectID;
270
+ incidentId?: ObjectID | undefined;
271
+ alertId?: ObjectID | undefined;
272
+ scheduledMaintenanceId?: ObjectID | undefined;
273
+ aiRunId?: ObjectID | undefined;
244
274
  /*
245
275
  * When set, use this specific provider (validated against the project) rather
246
276
  * than the project default. Powers the in-chat provider/model switcher.
@@ -337,23 +367,40 @@ export class Service extends BaseService {
337
367
  }
338
368
 
339
369
  /*
340
- * G4 daily budget: has this project consumed its daily autonomous-token
341
- * allowance (UTC day)? Counts only AUTONOMOUS_AI_FEATURES tokens, so chat
342
- * usage neither eats the autonomous budget nor is blocked by it.
370
+ * G4 daily budget: has this project consumed the selected subject lane's
371
+ * daily autonomous-token allowance (UTC day)? Counts only that lane's
372
+ * AUTONOMOUS_AI_FEATURES tokens, so chat usage neither eats the autonomous
373
+ * budget nor is blocked by it.
343
374
  */
344
375
  @CaptureSpan()
345
376
  public async getAutonomousDailyBudgetStatus(
346
377
  projectId: ObjectID,
378
+ subject?: {
379
+ incidentId?: ObjectID | undefined;
380
+ alertId?: ObjectID | undefined;
381
+ },
347
382
  ): Promise<AutonomousBudgetStatus> {
383
+ this.assertSingleSubject(subject);
384
+
348
385
  const project: Project | null = await ProjectService.findOneById({
349
386
  id: projectId,
350
- select: { aiDailyAutonomousTokenLimit: true },
387
+ select: {
388
+ aiDailyAutonomousTokenLimit: true,
389
+ incidentAiDailyAutonomousTokenLimit: true,
390
+ alertAiDailyAutonomousTokenLimit: true,
391
+ },
351
392
  props: { isRoot: true },
352
393
  });
353
394
 
354
- const limitInTokens: number | null =
395
+ let limitInTokens: number | null =
355
396
  project?.aiDailyAutonomousTokenLimit ?? null;
356
397
 
398
+ if (subject?.incidentId) {
399
+ limitInTokens = project?.incidentAiDailyAutonomousTokenLimit ?? null;
400
+ } else if (subject?.alertId) {
401
+ limitInTokens = project?.alertAiDailyAutonomousTokenLimit ?? null;
402
+ }
403
+
357
404
  if (limitInTokens === null) {
358
405
  return { exhausted: false, limitInTokens: null, usedTokensToday: 0 };
359
406
  }
@@ -374,6 +421,10 @@ export class Service extends BaseService {
374
421
  "UTC",
375
422
  ),
376
423
  features: AUTONOMOUS_AI_FEATURES,
424
+ incidentId: subject?.incidentId,
425
+ alertId: subject?.alertId,
426
+ legacyIncidentFeatures: LEGACY_INCIDENT_LANE_FEATURES,
427
+ legacyAlertFeatures: LEGACY_ALERT_LANE_FEATURES,
377
428
  },
378
429
  );
379
430
 
@@ -388,6 +439,8 @@ export class Service extends BaseService {
388
439
  public async executeWithLogging(
389
440
  request: AILogRequest,
390
441
  ): Promise<AILogResponse> {
442
+ this.assertSingleSubject(request);
443
+
391
444
  const startTime: Date = new Date();
392
445
 
393
446
  // Get LLM provider for the project (honoring an explicit per-chat choice).
@@ -503,10 +556,18 @@ export class Service extends BaseService {
503
556
  */
504
557
  if (AUTONOMOUS_AI_FEATURES.includes(request.feature)) {
505
558
  const budget: AutonomousBudgetStatus =
506
- await this.getAutonomousDailyBudgetStatus(request.projectId);
559
+ await this.getAutonomousDailyBudgetStatus(request.projectId, {
560
+ incidentId: request.incidentId,
561
+ alertId: request.alertId,
562
+ });
507
563
 
508
564
  if (budget.exhausted) {
509
- const budgetMessage: string = `Daily autonomous AI token budget exhausted (${budget.usedTokensToday.toLocaleString()} of ${budget.limitInTokens?.toLocaleString()} tokens used today). Autonomous AI requests resume tomorrow (UTC) — raise or unset the limit in the AI settings pages.`;
565
+ const settingsLocation: string = request.incidentId
566
+ ? "Incidents > Settings > AI"
567
+ : request.alertId
568
+ ? "Alerts > Settings > AI"
569
+ : "Project Settings > AI > AI Guardrails";
570
+ const budgetMessage: string = `Daily autonomous AI token budget exhausted (${budget.usedTokensToday.toLocaleString()} of ${budget.limitInTokens?.toLocaleString()} tokens used today). Autonomous AI requests resume tomorrow (UTC) — raise or unset the limit under ${settingsLocation}.`;
510
571
 
511
572
  logEntry.status = LlmLogStatus.BudgetExceeded;
512
573
  logEntry.statusMessage = budgetMessage.substring(0, 490);
@@ -658,6 +719,17 @@ export class Service extends BaseService {
658
719
  }
659
720
  }
660
721
 
722
+ private assertSingleSubject(subject?: {
723
+ incidentId?: ObjectID | undefined;
724
+ alertId?: ObjectID | undefined;
725
+ }): void {
726
+ if (subject?.incidentId && subject.alertId) {
727
+ throw new BadDataException(
728
+ "An AI request cannot belong to both an incident and an alert.",
729
+ );
730
+ }
731
+ }
732
+
661
733
  /*
662
734
  * Set gen_ai.* attributes (OpenTelemetry GenAI semantic conventions) on the
663
735
  * currently-active span. The @CaptureSpan()-wrapped caller owns that span, so
@@ -84,6 +84,7 @@ export class Service extends DatabaseService<Model> {
84
84
  displayColor?: Color | undefined;
85
85
  userId?: ObjectID | undefined;
86
86
  postedAt?: Date | undefined;
87
+ aiRunId?: ObjectID | undefined;
87
88
  workspaceNotification?:
88
89
  | {
89
90
  notifyUserId?: ObjectID | undefined; // this is oneuptime user id.
@@ -126,6 +127,10 @@ export class Service extends DatabaseService<Model> {
126
127
  alertFeed.alertFeedEventType = data.alertFeedEventType;
127
128
  alertFeed.projectId = data.projectId;
128
129
 
130
+ if (data.aiRunId) {
131
+ alertFeed.aiRunId = data.aiRunId;
132
+ }
133
+
129
134
  if (!data.postedAt) {
130
135
  alertFeed.postedAt = OneUptimeDate.getCurrentDate();
131
136
  }
@@ -34,6 +34,7 @@ import {
34
34
  TimeoutOverflowMode,
35
35
  } from "../Utils/AnalyticsDatabase/QuerySettingsHelper";
36
36
  import {
37
+ getDistributedDdlTaskTimeoutSeconds,
37
38
  getStorageTableName,
38
39
  onClusterClause,
39
40
  } from "../Utils/AnalyticsDatabase/ClusterConfig";
@@ -137,6 +138,34 @@ export const MigrationExecuteOptions: ClickhouseExecuteOptions = {
137
138
  * migration pool's 30-minute idle ceiling.
138
139
  */
139
140
  http_headers_progress_interval_ms: "10000",
141
+ /*
142
+ * ON CLUSTER DDL is queued in Keeper and executed by each host's DDLWorker
143
+ * sequentially, so on a busy or backlogged cluster a host can be healthy
144
+ * yet not reach the task within the wait window. The server default output
145
+ * mode (`throw`) turns that into TIMEOUT_EXCEEDED (code 159) and aborts
146
+ * the whole migrate run — even though the task stays queued and the hosts
147
+ * execute it in the background (until the DDL queue evicts it:
148
+ * task_max_lifetime, one week, or falling more than max_tasks_in_queue
149
+ * entries behind). `null_status_on_timeout` returns NULL for the hosts
150
+ * that haven't finished yet instead of throwing, while a real DDL failure
151
+ * on any host that did run it within the window still throws. Safe because
152
+ * every schema statement here is idempotent (IF NOT EXISTS / OR REPLACE)
153
+ * and, with the default `distributed_ddl.pool_size = 1`, later DDL queues
154
+ * strictly behind earlier DDL on each host. Migrate.ts additionally warns
155
+ * at end of run when the DDL queue still has unfinished tasks. Note these
156
+ * options are also reused by runtime ALTER ... DELETE mutations (session
157
+ * erasure / pin materialization); timeout-as-success is acceptable there
158
+ * too since a mutation is durable once enqueued. Requires ClickHouse >=
159
+ * 21.4 (older servers reject the setting as unknown).
160
+ */
161
+ distributed_ddl_output_mode: "null_status_on_timeout",
162
+ /*
163
+ * Int64 settings are typed as strings by @clickhouse/client. Read at
164
+ * module load; env is static for the life of the process. The migration
165
+ * pool's socket-idle ceiling scales with this value (ClickhouseConfig.ts)
166
+ * so a raised wait isn't killed client-side.
167
+ */
168
+ distributed_ddl_task_timeout: String(getDistributedDdlTaskTimeoutSeconds()),
140
169
  },
141
170
  };
142
171
 
@@ -334,7 +334,8 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
334
334
  * generated — session refresh tokens and the like. They keep the fast
335
335
  * SHA-256 hash, which is the right tool for them: there is nothing to guess,
336
336
  * and they have to stay searchable by hash because that is how they are
337
- * looked up.
337
+ * looked up. Every human-chosen credential, including dashboard and status
338
+ * page master passwords, declares a salt column and takes the scrypt path.
338
339
  *
339
340
  * The salt is written onto the SAME payload as the hash, so the pair can
340
341
  * never be persisted out of step with each other.
@@ -468,6 +469,10 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
468
469
  }),
469
470
  [saltColumnName]: newSalt,
470
471
  } as unknown as PartialEntity<TBaseModel>,
472
+ expectedData: {
473
+ [data.columnName]: storedHash,
474
+ [saltColumnName]: salt,
475
+ } as unknown as PartialEntity<TBaseModel>,
471
476
  skipUpdateDateColumn: true,
472
477
  });
473
478
  } catch (err) {
@@ -2502,6 +2507,14 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2502
2507
  public async updateColumnsByIdWithoutHooks(input: {
2503
2508
  id: ObjectID;
2504
2509
  data: PartialEntity<TBaseModel>;
2510
+ /*
2511
+ * Optional compare-and-set guard. Every supplied property is added to
2512
+ * the WHERE clause with null-safe equality, so the update is skipped if
2513
+ * another writer changed the row after the caller read it. Password-hash
2514
+ * upgrades use this to avoid overwriting a concurrently changed
2515
+ * credential with a re-hash of the old password.
2516
+ */
2517
+ expectedData?: PartialEntity<TBaseModel>;
2505
2518
  /*
2506
2519
  * Leave `updatedAt` untouched. For passive bookkeeping writes (liveness
2507
2520
  * timestamps, ingest health markers) where consumers key change
@@ -2576,9 +2589,37 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2576
2589
  metadata.primaryColumns[0]?.databaseName || "_id";
2577
2590
  params.push(input.id.toString());
2578
2591
 
2592
+ const whereClauses: Array<string> = [
2593
+ `"${primaryColumnName}" = $${params.length}`,
2594
+ ];
2595
+
2596
+ for (const [propertyName, value] of Object.entries(
2597
+ (input.expectedData || {}) as ObjectLiteral,
2598
+ )) {
2599
+ const column: ColumnMetadata | undefined =
2600
+ metadata.findColumnWithPropertyName(propertyName);
2601
+
2602
+ if (!column) {
2603
+ throw new BadDataException(
2604
+ `updateColumnsByIdWithoutHooks: unknown expected column "${propertyName}" on "${metadata.tableName}"`,
2605
+ );
2606
+ }
2607
+
2608
+ if (typeof value === "function") {
2609
+ throw new BadDataException(
2610
+ `updateColumnsByIdWithoutHooks: SQL-expression expected values are not supported (column "${propertyName}"); pass a literal value.`,
2611
+ );
2612
+ }
2613
+
2614
+ params.push(driver.preparePersistentValue(value, column));
2615
+ whereClauses.push(
2616
+ `"${column.databaseName}" IS NOT DISTINCT FROM $${params.length}`,
2617
+ );
2618
+ }
2619
+
2579
2620
  const sql: string = `UPDATE "${metadata.tableName}" SET ${setClauses.join(
2580
2621
  ", ",
2581
- )} WHERE "${primaryColumnName}" = $${params.length}`;
2622
+ )} WHERE ${whereClauses.join(" AND ")}`;
2582
2623
 
2583
2624
  await repository.manager.query(sql, params);
2584
2625
  }
@@ -84,6 +84,7 @@ export class Service extends DatabaseService<IncidentFeed> {
84
84
  displayColor?: Color | undefined;
85
85
  userId?: ObjectID | undefined;
86
86
  postedAt?: Date | undefined;
87
+ aiRunId?: ObjectID | undefined;
87
88
  // send notifificatin to slack and teams. This is optional
88
89
  workspaceNotification?:
89
90
  | {
@@ -131,6 +132,10 @@ export class Service extends DatabaseService<IncidentFeed> {
131
132
  incidentFeed.incidentFeedEventType = data.incidentFeedEventType;
132
133
  incidentFeed.projectId = data.projectId;
133
134
 
135
+ if (data.aiRunId) {
136
+ incidentFeed.aiRunId = data.aiRunId;
137
+ }
138
+
134
139
  if (!data.postedAt) {
135
140
  incidentFeed.postedAt = OneUptimeDate.getCurrentDate();
136
141
  }
@@ -2,6 +2,7 @@ import DatabaseService from "./DatabaseService";
2
2
  import Model from "../../Models/DatabaseModels/LlmLog";
3
3
  import { IsBillingEnabled } from "../EnvironmentConfig";
4
4
  import ObjectID from "../../Types/ObjectID";
5
+ import BadDataException from "../../Types/Exception/BadDataException";
5
6
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
6
7
 
7
8
  export class Service extends DatabaseService<Model> {
@@ -22,15 +23,58 @@ export class Service extends DatabaseService<Model> {
22
23
  projectId: ObjectID;
23
24
  since: Date;
24
25
  features: Array<string>;
26
+ /*
27
+ * Subject ids select a lane, not one particular subject: passing an
28
+ * incident id counts every incident-associated log for the project, and
29
+ * passing an alert id counts every alert-associated log. With neither id,
30
+ * only genuinely subjectless work is counted. The caller already has the
31
+ * concrete id, so using it as the discriminator keeps this API aligned
32
+ * with AIService's request shape without introducing a second subject enum.
33
+ */
34
+ incidentId?: ObjectID | undefined;
35
+ alertId?: ObjectID | undefined;
36
+ /*
37
+ * Feature-only fallbacks for rows written before subject identity was
38
+ * propagated. Shared features are recovered through aiRunId below.
39
+ */
40
+ legacyIncidentFeatures?: Array<string> | undefined;
41
+ legacyAlertFeatures?: Array<string> | undefined;
25
42
  }): Promise<number> {
43
+ if (data.incidentId && data.alertId) {
44
+ throw new BadDataException(
45
+ "An LLM usage query cannot select both the incident and alert lanes.",
46
+ );
47
+ }
48
+
26
49
  if (data.features.length === 0) {
27
50
  return 0;
28
51
  }
29
52
 
53
+ const legacyIncidentFeatures: Array<string> =
54
+ data.legacyIncidentFeatures || [];
55
+ const legacyAlertFeatures: Array<string> = data.legacyAlertFeatures || [];
56
+
57
+ const incidentRunMembership: string = `EXISTS (SELECT 1 FROM "AIRun" AS "run" WHERE "run"."_id" = "log"."aiRunId" AND "run"."triggeredByIncidentId" IS NOT NULL AND "run"."triggeredByAlertId" IS NULL)`;
58
+ const alertRunMembership: string = `EXISTS (SELECT 1 FROM "AIRun" AS "run" WHERE "run"."_id" = "log"."aiRunId" AND "run"."triggeredByIncidentId" IS NULL AND "run"."triggeredByAlertId" IS NOT NULL)`;
59
+
60
+ let subjectClause: string = `AND "log"."incidentId" IS NULL AND "log"."alertId" IS NULL AND NOT ("log"."feature" = ANY($4)) AND NOT ("log"."feature" = ANY($5)) AND NOT (${incidentRunMembership}) AND NOT (${alertRunMembership})`;
61
+
62
+ if (data.incidentId) {
63
+ subjectClause = `AND (("log"."incidentId" IS NOT NULL AND "log"."alertId" IS NULL) OR ("log"."incidentId" IS NULL AND "log"."alertId" IS NULL AND (("log"."feature" = ANY($4)) OR ${incidentRunMembership})))`;
64
+ } else if (data.alertId) {
65
+ subjectClause = `AND (("log"."incidentId" IS NULL AND "log"."alertId" IS NOT NULL) OR ("log"."incidentId" IS NULL AND "log"."alertId" IS NULL AND (("log"."feature" = ANY($5)) OR ${alertRunMembership})))`;
66
+ }
67
+
30
68
  const rows: Array<{ total: string | number | null }> =
31
69
  await this.getRepository().manager.query(
32
- `SELECT COALESCE(SUM("totalTokens"), 0) AS "total" FROM "LlmLog" WHERE "projectId" = $1 AND "createdAt" >= $2 AND "feature" = ANY($3) AND "deletedAt" IS NULL`,
33
- [data.projectId.toString(), data.since, data.features],
70
+ `SELECT COALESCE(SUM("log"."totalTokens"), 0) AS "total" FROM "LlmLog" AS "log" WHERE "log"."projectId" = $1 AND "log"."createdAt" >= $2 AND "log"."feature" = ANY($3) ${subjectClause} AND "log"."deletedAt" IS NULL`,
71
+ [
72
+ data.projectId.toString(),
73
+ data.since,
74
+ data.features,
75
+ legacyIncidentFeatures,
76
+ legacyAlertFeatures,
77
+ ],
34
78
  );
35
79
 
36
80
  return Number(rows[0]?.total || 0);
@@ -59,6 +59,9 @@ export interface ObservabilityAssistantStep {
59
59
  export interface ObservabilityAssistantRequest {
60
60
  projectId: ObjectID;
61
61
  userId?: ObjectID | undefined;
62
+ incidentId?: ObjectID | undefined;
63
+ alertId?: ObjectID | undefined;
64
+ aiRunId?: ObjectID | undefined;
62
65
  // The requesting user's real permission props — tools run under these.
63
66
  props: DatabaseCommonInteractionProps;
64
67
  question: string;
@@ -230,6 +233,9 @@ export default class ObservabilityAssistant {
230
233
  const response: AILogResponse = await AIService.executeWithLogging({
231
234
  projectId: request.projectId,
232
235
  userId: request.userId,
236
+ incidentId: request.incidentId,
237
+ alertId: request.alertId,
238
+ aiRunId: request.aiRunId,
233
239
  llmProviderId: request.llmProviderId,
234
240
  feature: request.feature,
235
241
  messages: messages,
@@ -130,6 +130,8 @@ export default class CodeFixAgentCompletion {
130
130
  runType: true,
131
131
  status: true,
132
132
  aiAgentId: true,
133
+ triggeredByIncidentId: true,
134
+ triggeredByAlertId: true,
133
135
  },
134
136
  props: {
135
137
  isRoot: true,
@@ -198,6 +200,8 @@ export default class CodeFixAgentCompletion {
198
200
  projectId: run.projectId,
199
201
  feature: AI_CODE_FIX_FEATURE,
200
202
  aiRunId: request.aiRunId,
203
+ incidentId: run.triggeredByIncidentId,
204
+ alertId: run.triggeredByAlertId,
201
205
  llmProviderId: llmProvider.id,
202
206
  messages: request.messages,
203
207
  tools: request.tools,
@@ -102,9 +102,12 @@ export default class CodeFixReadiness {
102
102
  * self-hosted too, where a project-owned provider makes the balance gate
103
103
  * moot and this becomes the ONLY thing that can kill a run.
104
104
  *
105
- * A limit of 0 is a documented kill-switch ("pause AI entirely"), i.e.
106
- * durable config so without this a paused project would read "ready"
107
- * forever while every run died at its first completion call.
105
+ * These readiness surfaces create subjectless exception/general tasks, so
106
+ * they use the "Other AI Workload" token lane. Incident/alert fix paths
107
+ * enforce their own lane when they are triggered and on every completion.
108
+ * A limit of 0 is a documented kill-switch for this lane, so without this
109
+ * a paused project would read "ready" forever while every subjectless run
110
+ * died at its first completion call.
108
111
  */
109
112
  const budget: AutonomousBudgetStatus =
110
113
  await AIService.getAutonomousDailyBudgetStatus(params.projectId);
@@ -116,8 +119,8 @@ export default class CodeFixReadiness {
116
119
  title: "LLM provider",
117
120
  detail:
118
121
  budget.limitInTokens !== null && budget.limitInTokens <= 0
119
- ? "AI is paused for this project: the daily autonomous AI token limit is set to 0. Raise or unset it in the AI settings pages to let fix tasks run."
120
- : `The daily autonomous AI token budget is exhausted (${budget.usedTokensToday.toLocaleString()} of ${budget.limitInTokens?.toLocaleString()} tokens used today). Fix tasks resume tomorrow (UTC) — raise or unset the limit in the AI settings pages.`,
122
+ ? "Other autonomous AI work is paused for this project: the daily background AI token limit is set to 0. Raise or unset it under Project Settings > AI > AI Guardrails to let subjectless fix tasks run."
123
+ : `The daily background AI token budget is exhausted (${budget.usedTokensToday.toLocaleString()} of ${budget.limitInTokens?.toLocaleString()} tokens used today). Subjectless fix tasks resume tomorrow (UTC) — raise or unset the limit under Project Settings > AI > AI Guardrails.`,
121
124
  };
122
125
  }
123
126
 
@@ -11,13 +11,10 @@ import CaptureSpan from "../../Telemetry/CaptureSpan";
11
11
  /*
12
12
  * Per-project daily fix-run budget (Preventive-lane X guardrail, G11).
13
13
  *
14
- * Every CodeFix AIRun regardless of recipe or trigger counts against
15
- * one per-project daily cap: `Project.aiDailyFixTaskLimit` fix runs per UTC
16
- * day (null/unset = the default below, 0 = fix tasks paused — the same
17
- * semantics as `aiDailyAutonomousTokenLimit`). The cap bounds the blast
18
- * radius of ANY runaway trigger: a click-happy user, a buggy automation, or
19
- * a future auto-created-fix fan-out can never open more than the budget's
20
- * worth of agent runs (and therefore PRs) in a day.
14
+ * Every CodeFix AIRun counts against the daily cap for its lane: incident,
15
+ * alert, or subjectless. Incident and alert runs use their independent
16
+ * settings; recipes with neither subject retain `Project.aiDailyFixTaskLimit`
17
+ * as a fallback. Null/unset means the default below and 0 pauses that lane.
21
18
  *
22
19
  * Enforced centrally at BOTH creation paths:
23
20
  * - TelemetryExceptionService.createCodeFixRunForException (the
@@ -43,6 +40,13 @@ export interface FixRunBudgetDecision {
43
40
  runsToday: number;
44
41
  }
45
42
 
43
+ export interface FixRunBudgetSubject {
44
+ incidentId?: ObjectID | undefined;
45
+ alertId?: ObjectID | undefined;
46
+ }
47
+
48
+ type FixRunBudgetLane = "incident" | "alert" | "other";
49
+
46
50
  export default class FixRunBudget {
47
51
  /*
48
52
  * The pure budget decision, separated from IO so it can be tested
@@ -85,14 +89,27 @@ export default class FixRunBudget {
85
89
  @CaptureSpan()
86
90
  public static async getBudgetStatus(
87
91
  projectId: ObjectID,
92
+ subject?: FixRunBudgetSubject | undefined,
88
93
  ): Promise<FixRunBudgetDecision> {
94
+ const lane: FixRunBudgetLane = this.getLane(subject);
95
+
89
96
  const project: Project | null = await ProjectService.findOneById({
90
97
  id: projectId,
91
- select: { aiDailyFixTaskLimit: true },
98
+ select:
99
+ lane === "incident"
100
+ ? { incidentAiDailyFixTaskLimit: true }
101
+ : lane === "alert"
102
+ ? { alertAiDailyFixTaskLimit: true }
103
+ : { aiDailyFixTaskLimit: true },
92
104
  props: { isRoot: true },
93
105
  });
94
106
 
95
- const configuredLimit: number | null = project?.aiDailyFixTaskLimit ?? null;
107
+ const configuredLimit: number | null =
108
+ lane === "incident"
109
+ ? project?.incidentAiDailyFixTaskLimit ?? null
110
+ : lane === "alert"
111
+ ? project?.alertAiDailyFixTaskLimit ?? null
112
+ : project?.aiDailyFixTaskLimit ?? null;
96
113
 
97
114
  // Paused short-circuits the count query (mirrors the token budget).
98
115
  const pausedCheck: FixRunBudgetDecision = this.evaluate({
@@ -109,6 +126,20 @@ export default class FixRunBudget {
109
126
  query: {
110
127
  projectId,
111
128
  runType: AIRunType.CodeFix,
129
+ ...(lane === "incident"
130
+ ? {
131
+ triggeredByIncidentId: QueryHelper.notNull(),
132
+ triggeredByAlertId: QueryHelper.isNull(),
133
+ }
134
+ : lane === "alert"
135
+ ? {
136
+ triggeredByIncidentId: QueryHelper.isNull(),
137
+ triggeredByAlertId: QueryHelper.notNull(),
138
+ }
139
+ : {
140
+ triggeredByIncidentId: QueryHelper.isNull(),
141
+ triggeredByAlertId: QueryHelper.isNull(),
142
+ }),
112
143
  createdAt: QueryHelper.greaterThanEqualTo(
113
144
  OneUptimeDate.getStartOfDay(OneUptimeDate.getCurrentDate(), "UTC"),
114
145
  ),
@@ -120,13 +151,51 @@ export default class FixRunBudget {
120
151
  return this.evaluate({ configuredLimit, runsToday });
121
152
  }
122
153
 
154
+ private static getLane(
155
+ subject?: FixRunBudgetSubject | undefined,
156
+ ): FixRunBudgetLane {
157
+ if (subject?.incidentId && subject.alertId) {
158
+ throw new BadDataException(
159
+ "A fix task cannot belong to both an incident and an alert.",
160
+ );
161
+ }
162
+
163
+ if (subject?.incidentId) {
164
+ return "incident";
165
+ }
166
+
167
+ if (subject?.alertId) {
168
+ return "alert";
169
+ }
170
+
171
+ return "other";
172
+ }
173
+
123
174
  // Human-readable rejection naming the cap and the setting that controls it.
124
- public static describeRejection(decision: FixRunBudgetDecision): string {
175
+ public static describeRejection(
176
+ decision: FixRunBudgetDecision,
177
+ subject?: FixRunBudgetSubject | undefined,
178
+ ): string {
179
+ const lane: FixRunBudgetLane = this.getLane(subject);
180
+ const settingTitle: string =
181
+ lane === "incident"
182
+ ? "Daily Incident AI Fix Task Limit"
183
+ : lane === "alert"
184
+ ? "Daily Alert AI Fix Task Limit"
185
+ : "Daily Other AI Fix Task Limit";
186
+ const settingsLocation: string =
187
+ lane === "incident"
188
+ ? "Incidents > Settings > AI"
189
+ : lane === "alert"
190
+ ? "Alerts > Settings > AI"
191
+ : "Project Settings > AI > AI Guardrails";
192
+ const laneLabel: string = lane === "other" ? "other AI" : `${lane} AI`;
193
+
125
194
  if (decision.paused) {
126
- return `AI fix tasks are paused for this project — the "Daily AI Fix Task Limit" is set to 0. Raise or unset the limit in the AI settings pages (Settings > Incidents/Alerts > AI) to resume.`;
195
+ return `${laneLabel} fix tasks are paused for this project — the "${settingTitle}" is set to 0. Raise or unset it under ${settingsLocation} to resume.`;
127
196
  }
128
197
 
129
- return `The project's daily AI fix task limit has been reached (${decision.runsToday} of ${decision.limit} fix tasks created today, UTC). New fix tasks can be created tomorrow — or raise the "Daily AI Fix Task Limit" in the AI settings pages (unset means the default of ${DEFAULT_DAILY_FIX_RUN_LIMIT}/day).`;
198
+ return `The project's ${laneLabel} fix task limit has been reached (${decision.runsToday} of ${decision.limit} fix tasks created today, UTC). New fix tasks can be created tomorrow — or raise the "${settingTitle}" under ${settingsLocation} (unset means the default of ${DEFAULT_DAILY_FIX_RUN_LIMIT}/day).`;
130
199
  }
131
200
 
132
201
  /*
@@ -135,14 +204,19 @@ export default class FixRunBudget {
135
204
  * a CodeFix AIRun row is written.
136
205
  */
137
206
  @CaptureSpan()
138
- public static async assertWithinBudget(projectId: ObjectID): Promise<void> {
139
- const decision: FixRunBudgetDecision =
140
- await this.getBudgetStatus(projectId);
207
+ public static async assertWithinBudget(
208
+ projectId: ObjectID,
209
+ subject?: FixRunBudgetSubject | undefined,
210
+ ): Promise<void> {
211
+ const decision: FixRunBudgetDecision = await this.getBudgetStatus(
212
+ projectId,
213
+ subject,
214
+ );
141
215
 
142
216
  if (decision.allowed) {
143
217
  return;
144
218
  }
145
219
 
146
- throw new BadDataException(this.describeRejection(decision));
220
+ throw new BadDataException(this.describeRejection(decision, subject));
147
221
  }
148
222
  }
@@ -321,6 +321,8 @@ export default class RemediationExecutionRunner {
321
321
  attemptCount,
322
322
  request: {
323
323
  feature: AI_REMEDIATION_EXECUTION_FEATURE,
324
+ incidentId: suggestion!.incidentId,
325
+ alertId: suggestion!.alertId,
324
326
  contextSummary,
325
327
  personaOverride:
326
328
  resolvedMode === "FullAuto" ? FULLAUTO_PERSONA : SUGGEST_PERSONA,