@oneuptime/common 12.0.6 → 12.0.7

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 (424) hide show
  1. package/Models/DatabaseModels/AIInsight.ts +1 -1
  2. package/Models/DatabaseModels/DatabaseBaseModel/FileModel.ts +2 -3
  3. package/Models/DatabaseModels/DeletedProject.ts +595 -0
  4. package/Models/DatabaseModels/Index.ts +2 -0
  5. package/Models/DatabaseModels/Monitor.ts +111 -0
  6. package/Models/DatabaseModels/Project.ts +3 -3
  7. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -1
  8. package/Server/API/FileAPI.ts +15 -2
  9. package/Server/API/MicrosoftTeamsAPI.ts +6 -1
  10. package/Server/API/ProjectAPI.ts +214 -0
  11. package/Server/API/StatusPageAPI.ts +39 -6
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.ts +50 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.ts +67 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.ts +39 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  16. package/Server/Services/AIAgentService.ts +20 -0
  17. package/Server/Services/DashboardDomainService.ts +73 -28
  18. package/Server/Services/DatabaseService.ts +1 -0
  19. package/Server/Services/DeletedProjectService.ts +138 -0
  20. package/Server/Services/FileService.ts +61 -0
  21. package/Server/Services/IncidentEpisodePublicNoteService.ts +18 -0
  22. package/Server/Services/IncidentPublicNoteService.ts +18 -0
  23. package/Server/Services/Index.ts +2 -0
  24. package/Server/Services/MonitorService.ts +311 -0
  25. package/Server/Services/ProbeService.ts +20 -0
  26. package/Server/Services/ProjectService.ts +297 -1
  27. package/Server/Services/PushNotificationService.ts +71 -0
  28. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +18 -0
  29. package/Server/Services/StatusPageAnnouncementService.ts +53 -0
  30. package/Server/Services/StatusPageDomainService.ts +73 -28
  31. package/Server/Services/TeamMemberService.ts +117 -12
  32. package/Server/Services/TelemetryIngestionKeyService.ts +1 -0
  33. package/Server/Services/UserWebhookService.ts +34 -109
  34. package/Server/Services/WorkspaceNotificationRuleService.ts +69 -0
  35. package/Server/Services/WorkspaceProjectAuthTokenService.ts +37 -1
  36. package/Server/Types/Database/DeleteById.ts +2 -0
  37. package/Server/Types/Database/DeleteOneBy.ts +6 -0
  38. package/Server/Types/Domain.ts +41 -0
  39. package/Server/Types/Workflow/Components/API/Delete.ts +2 -1
  40. package/Server/Types/Workflow/Components/API/Get.ts +2 -1
  41. package/Server/Types/Workflow/Components/API/Patch.ts +2 -1
  42. package/Server/Types/Workflow/Components/API/Post.ts +2 -1
  43. package/Server/Types/Workflow/Components/API/Put.ts +2 -1
  44. package/Server/Types/Workflow/Components/API/Utils.ts +41 -2
  45. package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +25 -19
  46. package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +6 -5
  47. package/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.ts +32 -14
  48. package/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts +31 -13
  49. package/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts +29 -20
  50. package/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts +28 -21
  51. package/Server/Types/Workflow/Components/BaseModel/LogComponentError.ts +89 -0
  52. package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +208 -0
  53. package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +11 -0
  54. package/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts +41 -18
  55. package/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts +45 -19
  56. package/Server/Types/Workflow/Components/Discord/SendMessageToChannel.ts +16 -9
  57. package/Server/Types/Workflow/Components/IncomingWebhookUtils.ts +66 -0
  58. package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +15 -9
  59. package/Server/Types/Workflow/Components/Slack/SendMessageToChannel.ts +17 -0
  60. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
  61. package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +171 -0
  62. package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +3 -3
  63. package/Server/Utils/AI/SRE/Insights/FixRouting.ts +3 -2
  64. package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +1 -1
  65. package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +6 -6
  66. package/Server/Utils/CodeRepository/GitHub/GitHub.ts +43 -5
  67. package/Server/Utils/DataSource/EgressGuard.ts +176 -16
  68. package/Server/Utils/DataSource/HttpFetch.ts +6 -45
  69. package/Server/Utils/Execute.ts +8 -0
  70. package/Server/Utils/InlineImageAccessTokenSync.ts +23 -0
  71. package/Server/Utils/LLM/LLMService.ts +57 -12
  72. package/Server/Utils/Monitor/MonitorAlert.ts +40 -0
  73. package/Server/Utils/Monitor/MonitorDependencySuppression.ts +192 -0
  74. package/Server/Utils/Monitor/MonitorIncident.ts +40 -0
  75. package/Server/Utils/Monitor/MonitorResource.ts +36 -0
  76. package/Server/Utils/Response.ts +142 -6
  77. package/Server/Utils/SSRFProtection.ts +273 -60
  78. package/Server/Utils/StartServer.ts +8 -0
  79. package/Server/Utils/VM/VMRunner.ts +88 -1
  80. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +555 -49
  81. package/Server/Utils/Workspace/Slack/Slack.ts +25 -2
  82. package/Server/Utils/Workspace/WorkspaceBase.ts +6 -0
  83. package/Tests/App/Dashboard/DangerZone.test.tsx +334 -0
  84. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +539 -0
  85. package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +678 -0
  86. package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +706 -0
  87. package/Tests/App/Dashboard/DashboardVariablesModal.test.tsx +508 -0
  88. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +470 -0
  89. package/Tests/App/StatusPage/StatusPageDetailPagesNotFound.test.tsx +308 -0
  90. package/Tests/Models/DatabaseModels/DeletedProjectModel.test.ts +251 -0
  91. package/Tests/Models/DatabaseModels/SavedViewJSONColumnTuples.test.ts +115 -0
  92. package/Tests/Server/API/FileAPIAccessControl.test.ts +316 -0
  93. package/Tests/Server/API/ProjectAPI.test.ts +299 -1
  94. package/Tests/Server/API/ProjectAPIAdjustBalance.test.ts +459 -0
  95. package/Tests/Server/API/ProjectAPIAdjustBalanceBillingDisabled.test.ts +177 -0
  96. package/Tests/Server/Services/DatabaseServiceDeletionReason.test.ts +123 -0
  97. package/Tests/Server/Services/DeletedProjectService.test.ts +415 -0
  98. package/Tests/Server/Services/DeletedProjectServiceSelfHosted.test.ts +70 -0
  99. package/Tests/Server/Services/DomainSubdomainHooks.test.ts +94 -0
  100. package/Tests/Server/Services/FileIsPublicBooleanMigration.test.ts +244 -0
  101. package/Tests/Server/Services/FileServiceMimeType.test.ts +89 -0
  102. package/Tests/Server/Services/MonitorServiceDependencyValidation.test.ts +702 -0
  103. package/Tests/Server/Services/ProjectServiceAdjustBalance.test.ts +615 -0
  104. package/Tests/Server/Services/ProjectServiceDeleteAudit.test.ts +406 -0
  105. package/Tests/Server/Services/PublishTimeImageVisibility.test.ts +450 -0
  106. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +669 -0
  107. package/Tests/Server/Services/UserWebhookSSRF.test.ts +174 -0
  108. package/Tests/Server/Services/WebPushEndpointAllowlist.test.ts +133 -0
  109. package/Tests/Server/Services/WorkspaceProjectAuthTokenRepoint.test.ts +618 -0
  110. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +26 -1
  111. package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +215 -0
  112. package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +742 -0
  113. package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +256 -0
  114. package/Tests/Server/Types/Workflow/Components/ModelArguments.test.ts +371 -0
  115. package/Tests/Server/Utils/AI/CodeAgentCommandGuard.test.ts +204 -0
  116. package/Tests/Server/Utils/AI/CodeAgentWriteLimits.test.ts +213 -0
  117. package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +52 -5
  118. package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +3 -0
  119. package/Tests/Server/Utils/AI/LLMServiceEgressGuard.test.ts +315 -0
  120. package/Tests/Server/Utils/AI/LLMServiceModelCompatibility.test.ts +3 -0
  121. package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +17 -5
  122. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +14 -1
  123. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +35 -0
  124. package/Tests/Server/Utils/AI/StubLLMEgressGuard.ts +25 -0
  125. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +62 -7
  126. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +69 -0
  127. package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +330 -0
  128. package/Tests/Server/Utils/GitHubCreatePullRequestWithToken.test.ts +393 -0
  129. package/Tests/Server/Utils/InlineImageAccessTokenSync.test.ts +202 -0
  130. package/Tests/Server/Utils/Monitor/MonitorDependencySuppression.test.ts +811 -0
  131. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +604 -0
  132. package/Tests/Server/Utils/ResponseSendFileResponse.test.ts +192 -0
  133. package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +406 -0
  134. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +194 -0
  135. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +1169 -0
  136. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +2 -0
  137. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +1605 -0
  138. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTenantResolution.test.ts +1218 -0
  139. package/Tests/Types/AI/AIChatMessageStatus.test.ts +79 -0
  140. package/Tests/Types/AI/AIInsightStatus.test.ts +40 -0
  141. package/Tests/Types/API/HostnameAuthorityParsing.test.ts +157 -0
  142. package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +27 -0
  143. package/Tests/Types/DataSource/DataSourceLimits.test.ts +71 -0
  144. package/Tests/Types/DataSource/DataSourceType.test.ts +181 -0
  145. package/Tests/Types/DomainSubdomainValidation.test.ts +90 -0
  146. package/Tests/Types/JSONFunctions.test.ts +252 -1
  147. package/Tests/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.test.ts +61 -0
  148. package/Tests/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.test.ts +62 -0
  149. package/Tests/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.test.ts +68 -0
  150. package/Tests/Types/Monitor/SnmpMonitor/SnmpVersion.test.ts +51 -0
  151. package/Tests/UI/Components/404.test.tsx +1 -1
  152. package/Tests/UI/Components/Alert.test.tsx +1 -1
  153. package/Tests/UI/Components/Badge.test.tsx +1 -1
  154. package/Tests/UI/Components/BasicForm.test.tsx +39 -10
  155. package/Tests/UI/Components/Button.test.tsx +1 -1
  156. package/Tests/UI/Components/Card.test.tsx +1 -1
  157. package/Tests/UI/Components/Charts/AxisTickColor.test.tsx +1 -1
  158. package/Tests/UI/Components/ColorViewer.test.tsx +1 -1
  159. package/Tests/UI/Components/ComponentsModal.test.tsx +7 -1
  160. package/Tests/UI/Components/DictionaryOfStrings.test.tsx +1 -1
  161. package/Tests/UI/Components/Dropdown.test.tsx +1 -1
  162. package/Tests/UI/Components/FilePicker.test.tsx +1 -1
  163. package/Tests/UI/Components/HiddenText.test.tsx +1 -1
  164. package/Tests/UI/Components/Input.test.tsx +1 -1
  165. package/Tests/UI/Components/Loader.test.tsx +1 -1
  166. package/Tests/UI/Components/LogTimeRangePicker.test.tsx +1 -1
  167. package/Tests/UI/Components/MasterPage.test.tsx +1 -1
  168. package/Tests/UI/Components/ModalPortalDismissal.test.tsx +489 -0
  169. package/Tests/UI/Components/ModelDelete.test.tsx +214 -0
  170. package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1 -1
  171. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +1 -1
  172. package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +1 -1
  173. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +1 -1
  174. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1 -1
  175. package/Tests/UI/Components/NavBar.test.tsx +1 -1
  176. package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +1 -1
  177. package/Tests/UI/Components/Pagination.test.tsx +1 -1
  178. package/Tests/UI/Components/Pill.test.tsx +1 -1
  179. package/Tests/UI/Components/Probe.test.tsx +1 -1
  180. package/Tests/UI/Components/ProgressBar.test.tsx +1 -1
  181. package/Tests/UI/Components/RadioButtons.test.tsx +1 -1
  182. package/Tests/UI/Components/SideMenuItem.test.tsx +1 -1
  183. package/Tests/UI/Components/SideOver.test.tsx +500 -6
  184. package/Tests/UI/Components/Tabs.test.tsx +1 -1
  185. package/Tests/UI/Components/TelemetrySearchBar.test.tsx +1 -1
  186. package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +1 -1
  187. package/Tests/UI/Components/TextArea.test.tsx +1 -1
  188. package/Tests/UI/Components/Toast.test.tsx +1 -1
  189. package/Tests/UI/Components/Toggle.test.tsx +1 -1
  190. package/Tests/UI/Components/TopSection.test.tsx +1 -1
  191. package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +1 -1
  192. package/Tests/UI/Rum/ReplayScrubber.test.tsx +1 -1
  193. package/Tests/UI/Rum/ReplayStage.test.tsx +1 -1
  194. package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +1 -1
  195. package/Tests/UI/Utils/LocalStorageArrayRoundTrip.test.ts +72 -0
  196. package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +19 -2
  197. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +44 -0
  198. package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +288 -5
  199. package/Tests/Utils/Dashboard/VariableUrlState.test.ts +42 -0
  200. package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +27 -0
  201. package/Tests/Utils/LegacySerializedArray.test.ts +139 -0
  202. package/Tests/Utils/Monitor/MonitorDependencyRule.test.ts +190 -0
  203. package/Tests/Utils/Realtime.test.ts +78 -0
  204. package/Tests/Utils/Telemetry/SavedViewFilters.test.ts +246 -0
  205. package/Tests/__mocks__/i18next-browser-languagedetector.js +21 -0
  206. package/Types/AI/FixPullRequestCiStatus.ts +1 -1
  207. package/Types/AI/FixVerificationStatus.ts +2 -2
  208. package/Types/API/Hostname.ts +92 -4
  209. package/Types/API/URL.ts +43 -25
  210. package/Types/Billing/BalanceAdjustmentType.ts +14 -0
  211. package/Types/Billing/ProjectBalanceType.ts +13 -0
  212. package/Types/Domain.ts +26 -0
  213. package/Types/File/MimeType.ts +11 -0
  214. package/Types/JSONFunctions.ts +15 -0
  215. package/Types/Telemetry/TelemetrySavedViewState.ts +9 -1
  216. package/Types/Workflow/Components/BaseModel.ts +92 -28
  217. package/Typings/Index.d.ts +12 -0
  218. package/UI/Components/GanttChart/ChartContainer.tsx +4 -3
  219. package/UI/Components/Modal/ConfirmModal.tsx +10 -5
  220. package/UI/Components/Modal/Modal.tsx +27 -47
  221. package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
  222. package/UI/Components/SideOver/SideOver.tsx +195 -68
  223. package/UI/Utils/PageScrollLock.ts +66 -0
  224. package/Utils/Dashboard/HtmlWidgetDocument.ts +4 -2
  225. package/Utils/Dashboard/VariableInterpolation.ts +19 -1
  226. package/Utils/LegacySerializedArray.ts +60 -0
  227. package/Utils/Monitor/MonitorDependencyRule.ts +88 -0
  228. package/Utils/Telemetry/SavedViewFilters.ts +88 -0
  229. package/build/dist/Models/DatabaseModels/AIInsight.js +1 -1
  230. package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
  231. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js +2 -3
  232. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js.map +1 -1
  233. package/build/dist/Models/DatabaseModels/DeletedProject.js +640 -0
  234. package/build/dist/Models/DatabaseModels/DeletedProject.js.map +1 -0
  235. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  236. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  237. package/build/dist/Models/DatabaseModels/Monitor.js +106 -0
  238. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  239. package/build/dist/Models/DatabaseModels/Project.js +3 -3
  240. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  241. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  242. package/build/dist/Server/API/FileAPI.js +14 -2
  243. package/build/dist/Server/API/FileAPI.js.map +1 -1
  244. package/build/dist/Server/API/MicrosoftTeamsAPI.js +6 -1
  245. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  246. package/build/dist/Server/API/ProjectAPI.js +157 -4
  247. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  248. package/build/dist/Server/API/StatusPageAPI.js +27 -3
  249. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js +34 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js.map +1 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js +30 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js.map +1 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js +20 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js.map +1 -0
  256. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  257. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  258. package/build/dist/Server/Services/AIAgentService.js +17 -0
  259. package/build/dist/Server/Services/AIAgentService.js.map +1 -1
  260. package/build/dist/Server/Services/DashboardDomainService.js +55 -18
  261. package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
  262. package/build/dist/Server/Services/DatabaseService.js +1 -0
  263. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  264. package/build/dist/Server/Services/DeletedProjectService.js +124 -0
  265. package/build/dist/Server/Services/DeletedProjectService.js.map +1 -0
  266. package/build/dist/Server/Services/FileService.js +52 -0
  267. package/build/dist/Server/Services/FileService.js.map +1 -1
  268. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +10 -1
  269. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  270. package/build/dist/Server/Services/IncidentPublicNoteService.js +10 -1
  271. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  272. package/build/dist/Server/Services/Index.js +2 -0
  273. package/build/dist/Server/Services/Index.js.map +1 -1
  274. package/build/dist/Server/Services/MonitorService.js +232 -0
  275. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  276. package/build/dist/Server/Services/ProbeService.js +17 -0
  277. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  278. package/build/dist/Server/Services/ProjectService.js +228 -6
  279. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  280. package/build/dist/Server/Services/PushNotificationService.js +56 -0
  281. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  282. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +10 -1
  283. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  284. package/build/dist/Server/Services/StatusPageAnnouncementService.js +54 -0
  285. package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
  286. package/build/dist/Server/Services/StatusPageDomainService.js +55 -18
  287. package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
  288. package/build/dist/Server/Services/TeamMemberService.js +97 -6
  289. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  290. package/build/dist/Server/Services/TelemetryIngestionKeyService.js +1 -0
  291. package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
  292. package/build/dist/Server/Services/UserWebhookService.js +31 -87
  293. package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
  294. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +65 -0
  295. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  296. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +23 -0
  297. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
  298. package/build/dist/Server/Types/Domain.js +37 -0
  299. package/build/dist/Server/Types/Domain.js.map +1 -1
  300. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +2 -1
  301. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  302. package/build/dist/Server/Types/Workflow/Components/API/Get.js +2 -1
  303. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  304. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +2 -1
  305. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  306. package/build/dist/Server/Types/Workflow/Components/API/Post.js +2 -1
  307. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  308. package/build/dist/Server/Types/Workflow/Components/API/Put.js +2 -1
  309. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  310. package/build/dist/Server/Types/Workflow/Components/API/Utils.js +35 -2
  311. package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
  312. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +15 -11
  313. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
  314. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +2 -3
  315. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
  316. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js +21 -10
  317. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js.map +1 -1
  318. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js +21 -10
  319. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js.map +1 -1
  320. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js +18 -13
  321. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js.map +1 -1
  322. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js +18 -13
  323. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js.map +1 -1
  324. package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js +43 -0
  325. package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js.map +1 -0
  326. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +116 -0
  327. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -0
  328. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +7 -0
  329. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
  330. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js +24 -13
  331. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js.map +1 -1
  332. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js +27 -13
  333. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js.map +1 -1
  334. package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js +14 -6
  335. package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js.map +1 -1
  336. package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js +42 -0
  337. package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js.map +1 -0
  338. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +15 -6
  339. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
  340. package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js +10 -2
  341. package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js.map +1 -1
  342. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
  343. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +141 -0
  344. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -1
  345. package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -1
  346. package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +1 -1
  347. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +6 -6
  348. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js.map +1 -1
  349. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +39 -5
  350. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
  351. package/build/dist/Server/Utils/DataSource/EgressGuard.js +94 -10
  352. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
  353. package/build/dist/Server/Utils/DataSource/HttpFetch.js +1 -19
  354. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  355. package/build/dist/Server/Utils/Execute.js +2 -2
  356. package/build/dist/Server/Utils/Execute.js.map +1 -1
  357. package/build/dist/Server/Utils/InlineImageAccessTokenSync.js +13 -0
  358. package/build/dist/Server/Utils/InlineImageAccessTokenSync.js.map +1 -1
  359. package/build/dist/Server/Utils/LLM/LLMService.js +43 -12
  360. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  361. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +44 -24
  362. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  363. package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js +158 -0
  364. package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js.map +1 -0
  365. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +50 -30
  366. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  367. package/build/dist/Server/Utils/Monitor/MonitorResource.js +32 -0
  368. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  369. package/build/dist/Server/Utils/Response.js +112 -5
  370. package/build/dist/Server/Utils/Response.js.map +1 -1
  371. package/build/dist/Server/Utils/SSRFProtection.js +219 -53
  372. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  373. package/build/dist/Server/Utils/StartServer.js +7 -0
  374. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  375. package/build/dist/Server/Utils/VM/VMRunner.js +73 -1
  376. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  377. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +445 -43
  378. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  379. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +18 -1
  380. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  381. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  382. package/build/dist/Types/AI/FixPullRequestCiStatus.js +1 -1
  383. package/build/dist/Types/AI/FixVerificationStatus.js +2 -2
  384. package/build/dist/Types/API/Hostname.js +73 -4
  385. package/build/dist/Types/API/Hostname.js.map +1 -1
  386. package/build/dist/Types/API/URL.js +42 -24
  387. package/build/dist/Types/API/URL.js.map +1 -1
  388. package/build/dist/Types/Billing/BalanceAdjustmentType.js +15 -0
  389. package/build/dist/Types/Billing/BalanceAdjustmentType.js.map +1 -0
  390. package/build/dist/Types/Billing/ProjectBalanceType.js +14 -0
  391. package/build/dist/Types/Billing/ProjectBalanceType.js.map +1 -0
  392. package/build/dist/Types/Domain.js +22 -0
  393. package/build/dist/Types/Domain.js.map +1 -1
  394. package/build/dist/Types/File/MimeType.js +11 -0
  395. package/build/dist/Types/File/MimeType.js.map +1 -1
  396. package/build/dist/Types/JSONFunctions.js +14 -0
  397. package/build/dist/Types/JSONFunctions.js.map +1 -1
  398. package/build/dist/Types/Workflow/Components/BaseModel.js +83 -28
  399. package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
  400. package/build/dist/UI/Components/GanttChart/ChartContainer.js +4 -3
  401. package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +1 -1
  402. package/build/dist/UI/Components/Modal/ConfirmModal.js +3 -1
  403. package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
  404. package/build/dist/UI/Components/Modal/Modal.js +24 -34
  405. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  406. package/build/dist/UI/Components/ModelDelete/ModelDelete.js +11 -6
  407. package/build/dist/UI/Components/ModelDelete/ModelDelete.js.map +1 -1
  408. package/build/dist/UI/Components/SideOver/SideOver.js +105 -30
  409. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  410. package/build/dist/UI/Utils/PageScrollLock.js +52 -0
  411. package/build/dist/UI/Utils/PageScrollLock.js.map +1 -0
  412. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +4 -2
  413. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -1
  414. package/build/dist/Utils/Dashboard/VariableInterpolation.js +19 -1
  415. package/build/dist/Utils/Dashboard/VariableInterpolation.js.map +1 -1
  416. package/build/dist/Utils/LegacySerializedArray.js +51 -0
  417. package/build/dist/Utils/LegacySerializedArray.js.map +1 -0
  418. package/build/dist/Utils/Monitor/MonitorDependencyRule.js +47 -0
  419. package/build/dist/Utils/Monitor/MonitorDependencyRule.js.map +1 -0
  420. package/build/dist/Utils/Telemetry/SavedViewFilters.js +52 -0
  421. package/build/dist/Utils/Telemetry/SavedViewFilters.js.map +1 -0
  422. package/jest.config.json +3 -0
  423. package/package.json +1 -1
  424. package/tsconfig.json +3 -1
@@ -1,5 +1,3 @@
1
- import http from "http";
2
- import https from "https";
3
1
  import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
4
2
  import API from "../../../Utils/API";
5
3
  import Dictionary from "../../../Types/Dictionary";
@@ -8,10 +6,7 @@ import {
8
6
  DATA_SOURCE_MAX_RESPONSE_SIZE_IN_BYTES,
9
7
  DATA_SOURCE_QUERY_TIMEOUT_IN_MS,
10
8
  } from "../../../Types/DataSource/DataSourceLimits";
11
- import DataSourceEgressGuard, {
12
- EgressGuardOptions,
13
- ResolvedAddress,
14
- } from "./EgressGuard";
9
+ import DataSourceEgressGuard, { EgressGuardOptions } from "./EgressGuard";
15
10
  import { DataSourceConnectionSettings } from "./Types";
16
11
 
17
12
  /*
@@ -54,12 +49,6 @@ export interface DataSourceHttpResponse {
54
49
  bodyJson: unknown;
55
50
  }
56
51
 
57
- type LookupCallback = (
58
- error: NodeJS.ErrnoException | null,
59
- address: string | Array<{ address: string; family: number }>,
60
- family?: number,
61
- ) => void;
62
-
63
52
  export default class DataSourceHttpFetch {
64
53
  /*
65
54
  * Standard auth headers for a data source: Bearer token wins, else HTTP
@@ -92,44 +81,16 @@ export default class DataSourceHttpFetch {
92
81
  public static async fetch(
93
82
  request: DataSourceHttpRequest,
94
83
  ): Promise<DataSourceHttpResponse> {
95
- const { url, addresses } = await DataSourceEgressGuard.assertUrlAllowed(
96
- request.url,
97
- request.egressOptions,
98
- );
99
-
100
84
  /*
101
85
  * Pin the validated addresses: whatever getaddrinfo said at validation
102
86
  * time is what the socket dials, even if DNS answers differently a
103
87
  * millisecond later.
104
88
  */
105
- const pinnedLookup: (
106
- hostname: string,
107
- options: { all?: boolean },
108
- callback: LookupCallback,
109
- ) => void = (
110
- _hostname: string,
111
- options: { all?: boolean },
112
- callback: LookupCallback,
113
- ): void => {
114
- const first: ResolvedAddress = addresses[0]!;
115
- if (options && options.all) {
116
- callback(
117
- null,
118
- addresses.map((resolved: ResolvedAddress) => {
119
- return { address: resolved.address, family: resolved.family };
120
- }),
121
- );
122
- return;
123
- }
124
- callback(null, first.address, first.family);
125
- };
126
-
127
- const httpAgent: http.Agent = new http.Agent({
128
- lookup: pinnedLookup as never,
129
- });
130
- const httpsAgent: https.Agent = new https.Agent({
131
- lookup: pinnedLookup as never,
132
- });
89
+ const { url, httpAgent, httpsAgent } =
90
+ await DataSourceEgressGuard.assertUrlAllowedAndPin(
91
+ request.url,
92
+ request.egressOptions,
93
+ );
133
94
 
134
95
  const headers: Dictionary<string> = { ...(request.headers || {}) };
135
96
 
@@ -74,6 +74,13 @@ export default class Execute {
74
74
  * (e.g. `git log` over a huge full-history repo) can never hang the caller.
75
75
  */
76
76
  timeoutInMS?: number | undefined;
77
+ /*
78
+ * Environment for the child. Replaces this process's environment entirely
79
+ * when given, so a caller can hand a secret to ONE child (a git askpass
80
+ * token) without putting it in process.env, where every other child —
81
+ * including an AI agent's shell commands — would inherit it.
82
+ */
83
+ env?: NodeJS.ProcessEnv | undefined;
77
84
  }): Promise<string> {
78
85
  return new Promise(
79
86
  (
@@ -89,6 +96,7 @@ export default class Execute {
89
96
  ...(data.timeoutInMS
90
97
  ? { timeout: data.timeoutInMS, killSignal: "SIGKILL" }
91
98
  : {}),
99
+ ...(data.env ? { env: data.env } : {}),
92
100
  },
93
101
  (
94
102
  err: ExecFileException | null,
@@ -81,3 +81,26 @@ export const setIsPublicForMarkdownImages: (
81
81
  }
82
82
  }
83
83
  };
84
+
85
+ /*
86
+ * Best-effort variant used by the publish paths (public notes,
87
+ * announcements). Failing to flip an inline image must never fail the
88
+ * write the user actually asked for, so errors are logged and swallowed.
89
+ */
90
+ export const syncIsPublicForMarkdownImages: (
91
+ markdown: string | null | undefined,
92
+ isPublic: boolean,
93
+ context: string,
94
+ ) => Promise<void> = async (
95
+ markdown: string | null | undefined,
96
+ isPublic: boolean,
97
+ context: string,
98
+ ): Promise<void> => {
99
+ try {
100
+ await setIsPublicForMarkdownImages(markdown, isPublic);
101
+ } catch (err) {
102
+ logger.error(
103
+ `Failed to sync inline image visibility for ${context}: ${String(err)}`,
104
+ );
105
+ }
106
+ };
@@ -4,11 +4,12 @@ import Headers from "../../../Types/API/Headers";
4
4
  import URL from "../../../Types/API/URL";
5
5
  import { JSONArray, JSONObject } from "../../../Types/JSON";
6
6
  import JSONFunctions from "../../../Types/JSONFunctions";
7
- import API from "../../../Utils/API";
7
+ import API, { RequestOptions } from "../../../Utils/API";
8
8
  import LlmType from "../../../Types/LLM/LlmType";
9
9
  import BadDataException from "../../../Types/Exception/BadDataException";
10
10
  import logger, { LogAttributes } from "../Logger";
11
11
  import CaptureSpan from "../Telemetry/CaptureSpan";
12
+ import DataSourceEgressGuard from "../DataSource/EgressGuard";
12
13
 
13
14
  export interface LLMToolDefinition {
14
15
  name: string;
@@ -653,6 +654,38 @@ export default class LLMService {
653
654
  * the offending parameter in the 400 — one parameter per response, hence the
654
655
  * loop.
655
656
  */
657
+ /*
658
+ * Request options for a call to a tenant-configured LLM endpoint.
659
+ *
660
+ * LlmProvider.baseUrl is writable by any project member while reading the
661
+ * apiKey is Owner/Admin-only, so an unguarded request lets a member repoint
662
+ * a provider at a host they control and collect the decrypted key out of the
663
+ * auth header — and, because provider error bodies are reflected back
664
+ * through the LLM provider API, use the same lever as a blind-free read
665
+ * primitive against the internal network.
666
+ *
667
+ * The address the guard checked is pinned into the socket, and redirects are
668
+ * refused: pinning covers only the validated host, so a 3xx would walk
669
+ * around it. Private ranges stay reachable on self-hosted installs, because
670
+ * a self-hosted Ollama on 10.x is the documented deployment.
671
+ */
672
+ private static async buildGuardedRequestOptions(
673
+ requestUrl: string,
674
+ options: RequestOptions,
675
+ ): Promise<RequestOptions> {
676
+ const { httpAgent, httpsAgent } =
677
+ await DataSourceEgressGuard.assertUrlAllowedAndPin(requestUrl, {
678
+ targetLabel: "LLM provider",
679
+ });
680
+
681
+ return {
682
+ ...options,
683
+ doNotFollowRedirects: true,
684
+ httpAgent,
685
+ httpsAgent,
686
+ };
687
+ }
688
+
656
689
  private static async postOpenAIChatCompletion(data: {
657
690
  requestUrl: string;
658
691
  headers: Headers;
@@ -674,6 +707,18 @@ export default class LLMService {
674
707
  */
675
708
  const attemptedTokenLimitParams: Set<TokenLimitParam> = new Set();
676
709
 
710
+ /*
711
+ * Validated once, before the first request: the adaptation loop below
712
+ * re-posts to the same URL, so re-resolving per attempt would only add
713
+ * DNS round trips (and a rebind window between them).
714
+ */
715
+ const requestOptions: RequestOptions =
716
+ await this.buildGuardedRequestOptions(data.requestUrl, {
717
+ retries: data.request.requestRetries ?? 2,
718
+ exponentialBackoff: true,
719
+ timeout: data.request.requestTimeoutInMs ?? 120000,
720
+ });
721
+
677
722
  const post: () => Promise<
678
723
  HTTPResponse<JSONObject> | HTTPErrorResponse
679
724
  > = (): Promise<HTTPResponse<JSONObject> | HTTPErrorResponse> => {
@@ -693,11 +738,7 @@ export default class LLMService {
693
738
  url: URL.fromString(data.requestUrl),
694
739
  data: body,
695
740
  headers: data.headers,
696
- options: {
697
- retries: data.request.requestRetries ?? 2,
698
- exponentialBackoff: true,
699
- timeout: data.request.requestTimeoutInMs ?? 120000,
700
- },
741
+ options: requestOptions,
701
742
  });
702
743
  };
703
744
 
@@ -1214,20 +1255,22 @@ export default class LLMService {
1214
1255
  requestData["tools"] = anthropicTools;
1215
1256
  }
1216
1257
 
1258
+ const anthropicRequestUrl: string = `${baseUrl}/messages`;
1259
+
1217
1260
  const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
1218
1261
  await API.post<JSONObject>({
1219
- url: URL.fromString(`${baseUrl}/messages`),
1262
+ url: URL.fromString(anthropicRequestUrl),
1220
1263
  data: requestData,
1221
1264
  headers: {
1222
1265
  "x-api-key": config.apiKey,
1223
1266
  "anthropic-version": "2023-06-01",
1224
1267
  "Content-Type": "application/json",
1225
1268
  },
1226
- options: {
1269
+ options: await this.buildGuardedRequestOptions(anthropicRequestUrl, {
1227
1270
  retries: request.requestRetries ?? 2,
1228
1271
  exponentialBackoff: true,
1229
1272
  timeout: request.requestTimeoutInMs ?? 120000,
1230
- },
1273
+ }),
1231
1274
  });
1232
1275
 
1233
1276
  const anthropicLogAttributes: LogAttributes = {
@@ -1355,18 +1398,20 @@ export default class LLMService {
1355
1398
  requestData["tools"] = this.toOpenAITools(request.tools);
1356
1399
  }
1357
1400
 
1401
+ const ollamaRequestUrl: string = `${config.baseUrl}/api/chat`;
1402
+
1358
1403
  const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
1359
1404
  await API.post<JSONObject>({
1360
- url: URL.fromString(`${config.baseUrl}/api/chat`),
1405
+ url: URL.fromString(ollamaRequestUrl),
1361
1406
  data: requestData,
1362
1407
  headers: {
1363
1408
  "Content-Type": "application/json",
1364
1409
  },
1365
- options: {
1410
+ options: await this.buildGuardedRequestOptions(ollamaRequestUrl, {
1366
1411
  retries: request.requestRetries ?? 2,
1367
1412
  exponentialBackoff: true,
1368
1413
  timeout: request.requestTimeoutInMs ?? 300000, // Ollama may be slower
1369
- },
1414
+ }),
1370
1415
  });
1371
1416
 
1372
1417
  const ollamaLogAttributes: LogAttributes = {
@@ -36,6 +36,9 @@ import MonitorClusterContextUtil, {
36
36
  MonitorClusterContext,
37
37
  } from "./MonitorClusterContext";
38
38
  import MonitorTemplateUtil from "./MonitorTemplateUtil";
39
+ import MonitorDependencySuppression, {
40
+ DependencySuppressionResult,
41
+ } from "./MonitorDependencySuppression";
39
42
  import { JSONObject } from "../../../Types/JSON";
40
43
  import OneUptimeDate from "../../../Types/Date";
41
44
  import MonitorEvaluationSummary from "../../../Types/Monitor/MonitorEvaluationSummary";
@@ -240,6 +243,14 @@ export default class MonitorAlert {
240
243
  * evaluating. See MonitorMaintenanceSuppression.
241
244
  */
242
245
  suppressedSeriesFingerprints?: Set<string> | undefined;
246
+ /**
247
+ * Alert-dependency suppression: when set and isSuppressed, a parent
248
+ * monitor this monitor depends on is currently in a suppressing
249
+ * status, so ALL alert creation for this evaluation is skipped. Only
250
+ * creation — already-open alerts still follow the normal resolve
251
+ * path above. See MonitorDependencySuppression.
252
+ */
253
+ dependencySuppression?: DependencySuppressionResult | undefined;
243
254
  /**
244
255
  * Event-driven monitors (incoming-request / webhook fan-out) must not
245
256
  * use the metric snapshot model where a series absent from this tick's
@@ -288,6 +299,35 @@ export default class MonitorAlert {
288
299
  return;
289
300
  }
290
301
 
302
+ /*
303
+ * Alert-dependency suppression: a parent monitor is in a suppressing
304
+ * status (offline by default), so skip creating any alert for this
305
+ * evaluation. Placed after the open-alert resolve pass above on
306
+ * purpose — an alert raised before the parent went down must still
307
+ * resolve normally; only new creation is silenced.
308
+ */
309
+ if (input.dependencySuppression?.isSuppressed) {
310
+ const suppressionReason: string =
311
+ MonitorDependencySuppression.buildSuppressionReason(
312
+ input.dependencySuppression.suppressingParents,
313
+ );
314
+
315
+ logger.debug(
316
+ `${input.monitor.id?.toString()} - Skipping alert creation: ${suppressionReason}.`,
317
+ alertLogAttributes,
318
+ );
319
+
320
+ input.evaluationSummary?.events.push({
321
+ type: "alert-skipped",
322
+ title: "Alert suppressed by monitor dependency",
323
+ message: `Skipped creating alerts because ${suppressionReason}. This monitor's status still updates normally; open alerts still auto-resolve.`,
324
+ relatedCriteriaId: input.criteriaInstance.data?.id,
325
+ at: OneUptimeDate.getCurrentDate(),
326
+ });
327
+
328
+ return;
329
+ }
330
+
291
331
  /*
292
332
  * Proxmox/Ceph monitors: resolve the monitored cluster once per
293
333
  * evaluation (lookup-only, from the step config's clusterIdentifier)
@@ -0,0 +1,192 @@
1
+ import Monitor from "../../../Models/DatabaseModels/Monitor";
2
+ import MonitorStatus from "../../../Models/DatabaseModels/MonitorStatus";
3
+ import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
4
+ import ObjectID from "../../../Types/ObjectID";
5
+ import MonitorDependencyRule, {
6
+ DependencySuppressionResult,
7
+ ParentMonitorStatusRef,
8
+ SuppressingParent,
9
+ } from "../../../Utils/Monitor/MonitorDependencyRule";
10
+ import MonitorService from "../../Services/MonitorService";
11
+ import QueryHelper from "../../Types/Database/QueryHelper";
12
+ import logger from "../Logger";
13
+ import CaptureSpan from "../Telemetry/CaptureSpan";
14
+
15
+ /*
16
+ * Re-exported so server-side callers (and the existing tests) keep a
17
+ * single import site; the rule itself lives in
18
+ * Common/Utils/Monitor/MonitorDependencyRule so the dashboard can share
19
+ * it without importing server modules.
20
+ */
21
+ export type {
22
+ DependencySuppressionResult,
23
+ ParentMonitorStatusRef,
24
+ SuppressingParent,
25
+ };
26
+
27
+ /*
28
+ * Alert-dependency suppression (the per-monitor counterpart of the
29
+ * per-series MonitorMaintenanceSuppression): when a monitor declares
30
+ * `dependsOnMonitors` and any of those parents is currently in a
31
+ * suppressing status, alert/incident *creation* for this monitor is
32
+ * skipped for the evaluation. The monitor itself keeps evaluating — its
33
+ * status timeline, metrics, and the resolve path for already-open
34
+ * alerts/incidents are untouched. That keeps the child visibly Offline on
35
+ * status pages (and lets grand-children observe the outage through the
36
+ * child's real status, which is what makes one-hop checks transitive)
37
+ * while silencing the redundant paging.
38
+ *
39
+ * Which parent statuses suppress: the monitor's
40
+ * `suppressAlertsWhenParentMonitorStatuses` list when configured,
41
+ * otherwise any status flagged `isOfflineState`. The decision itself is
42
+ * MonitorDependencyRule.getSuppressingParents, shared with the dashboard
43
+ * banner.
44
+ */
45
+ export default class MonitorDependencySuppression {
46
+ /*
47
+ * Resolve the suppression decision for one evaluation. Zero queries on
48
+ * the common path — a monitor with no dependencies returns immediately —
49
+ * and exactly one query (the parents' current statuses) otherwise. This
50
+ * sits on the hottest Postgres path in the product, so the monitor's
51
+ * dependency ids must arrive pre-selected on the monitor row rather than
52
+ * being re-read here.
53
+ */
54
+ @CaptureSpan()
55
+ public static async getDependencySuppression(input: {
56
+ monitor: Monitor;
57
+ }): Promise<DependencySuppressionResult> {
58
+ const monitorId: string = (
59
+ input.monitor.id ||
60
+ input.monitor._id ||
61
+ ""
62
+ ).toString();
63
+
64
+ const parentIds: Array<ObjectID> = (input.monitor.dependsOnMonitors || [])
65
+ .map((parent: Monitor) => {
66
+ return (parent.id || parent._id)?.toString() || "";
67
+ })
68
+ .filter((id: string) => {
69
+ /*
70
+ * A self-edge should never exist (validation rejects it, uuids
71
+ * compared case-insensitively), but if one was persisted through
72
+ * an older payload shape it must not let a monitor suppress its
73
+ * own offline alerts — that would silence exactly the outage the
74
+ * monitor exists to report.
75
+ */
76
+ return id.length > 0 && id.toLowerCase() !== monitorId.toLowerCase();
77
+ })
78
+ .map((id: string) => {
79
+ return new ObjectID(id);
80
+ });
81
+
82
+ if (parentIds.length === 0) {
83
+ return { isSuppressed: false, suppressingParents: [] };
84
+ }
85
+
86
+ const parents: Array<Monitor> = await MonitorService.findBy({
87
+ query: {
88
+ _id: QueryHelper.any(parentIds),
89
+ },
90
+ select: {
91
+ _id: true,
92
+ name: true,
93
+ currentMonitorStatus: {
94
+ _id: true,
95
+ name: true,
96
+ isOfflineState: true,
97
+ },
98
+ /*
99
+ * The parents' own parent ids, for the runtime mutual-cycle guard
100
+ * below. Selected here so the guard costs no extra query.
101
+ */
102
+ dependsOnMonitors: {
103
+ _id: true,
104
+ },
105
+ },
106
+ skip: 0,
107
+ limit: LIMIT_PER_PROJECT,
108
+ props: {
109
+ isRoot: true,
110
+ },
111
+ });
112
+
113
+ const parentRefs: Array<ParentMonitorStatusRef> = [];
114
+
115
+ for (const parent of parents) {
116
+ /*
117
+ * Runtime mutual-cycle guard: write-time validation walks the graph
118
+ * before persisting, but two concurrent updates can each pass
119
+ * validation and jointly commit a cycle (A depends on B, B depends
120
+ * on A). If that cycle suppressed, a shared outage would take both
121
+ * monitors offline and page NOBODY. Fail open instead: a parent
122
+ * that itself depends on this monitor is ignored for suppression,
123
+ * so a raced-in cycle degrades to normal (noisy) paging rather than
124
+ * a silent blackout.
125
+ */
126
+ const isMutualCycle: boolean = (parent.dependsOnMonitors || []).some(
127
+ (grandParent: Monitor) => {
128
+ const grandParentId: string = (
129
+ grandParent.id ||
130
+ grandParent._id ||
131
+ ""
132
+ ).toString();
133
+
134
+ return (
135
+ grandParentId.length > 0 &&
136
+ grandParentId.toLowerCase() === monitorId.toLowerCase()
137
+ );
138
+ },
139
+ );
140
+
141
+ if (isMutualCycle) {
142
+ logger.warn(
143
+ `${monitorId} - Monitor dependency cycle detected at evaluation time with parent ${parent.id?.toString()} ("${parent.name}"). The parent is ignored for suppression so alerts still fire. Remove one side of the cycle.`,
144
+ );
145
+ continue;
146
+ }
147
+
148
+ parentRefs.push({
149
+ monitorId: parent.id?.toString() || "",
150
+ monitorName: parent.name || "Unnamed monitor",
151
+ statusId: parent.currentMonitorStatus?.id?.toString(),
152
+ statusName: parent.currentMonitorStatus?.name,
153
+ isOfflineState: Boolean(parent.currentMonitorStatus?.isOfflineState),
154
+ });
155
+ }
156
+
157
+ const configuredSuppressionStatusIds: Set<string> = new Set<string>(
158
+ (input.monitor.suppressAlertsWhenParentMonitorStatuses || [])
159
+ .map((status: MonitorStatus) => {
160
+ return (status.id || status._id)?.toString() || "";
161
+ })
162
+ .filter((id: string) => {
163
+ return id.length > 0;
164
+ }),
165
+ );
166
+
167
+ const suppressingParents: Array<SuppressingParent> =
168
+ this.getSuppressingParents({
169
+ parents: parentRefs,
170
+ configuredSuppressionStatusIds,
171
+ });
172
+
173
+ return {
174
+ isSuppressed: suppressingParents.length > 0,
175
+ suppressingParents,
176
+ };
177
+ }
178
+
179
+ // Delegates kept so callers and tests have one server-side entry point.
180
+ public static getSuppressingParents(input: {
181
+ parents: Array<ParentMonitorStatusRef>;
182
+ configuredSuppressionStatusIds: Set<string>;
183
+ }): Array<SuppressingParent> {
184
+ return MonitorDependencyRule.getSuppressingParents(input);
185
+ }
186
+
187
+ public static buildSuppressionReason(
188
+ suppressingParents: Array<SuppressingParent>,
189
+ ): string {
190
+ return MonitorDependencyRule.buildSuppressionReason(suppressingParents);
191
+ }
192
+ }
@@ -44,6 +44,9 @@ import logger, { LogAttributes } from "../Logger";
44
44
  import CaptureSpan from "../Telemetry/CaptureSpan";
45
45
  import DataToProcess from "./DataToProcess";
46
46
  import MonitorTemplateUtil from "./MonitorTemplateUtil";
47
+ import MonitorDependencySuppression, {
48
+ DependencySuppressionResult,
49
+ } from "./MonitorDependencySuppression";
47
50
  import { JSONObject } from "../../../Types/JSON";
48
51
  import OneUptimeDate from "../../../Types/Date";
49
52
  import MonitorEvaluationSummary from "../../../Types/Monitor/MonitorEvaluationSummary";
@@ -288,6 +291,14 @@ export default class MonitorIncident {
288
291
  * are suppressed at creation time. See MonitorMaintenanceSuppression.
289
292
  */
290
293
  suppressedSeriesFingerprints?: Set<string> | undefined;
294
+ /**
295
+ * Alert-dependency suppression: when set and isSuppressed, a parent
296
+ * monitor this monitor depends on is currently in a suppressing
297
+ * status, so ALL incident creation for this evaluation is skipped.
298
+ * Only creation — already-open incidents still follow the normal
299
+ * resolve path above. See MonitorDependencySuppression.
300
+ */
301
+ dependencySuppression?: DependencySuppressionResult | undefined;
291
302
  /**
292
303
  * Event-driven monitors (incoming-request / webhook fan-out) must not
293
304
  * use the metric snapshot model where a series absent from this tick's
@@ -342,6 +353,35 @@ export default class MonitorIncident {
342
353
  return;
343
354
  }
344
355
 
356
+ /*
357
+ * Alert-dependency suppression: a parent monitor is in a suppressing
358
+ * status (offline by default), so skip creating any incident for this
359
+ * evaluation. Placed after the open-incident resolve pass above on
360
+ * purpose — an incident raised before the parent went down must still
361
+ * resolve normally; only new creation is silenced.
362
+ */
363
+ if (input.dependencySuppression?.isSuppressed) {
364
+ const suppressionReason: string =
365
+ MonitorDependencySuppression.buildSuppressionReason(
366
+ input.dependencySuppression.suppressingParents,
367
+ );
368
+
369
+ logger.debug(
370
+ `${input.monitor.id?.toString()} - Skipping incident creation: ${suppressionReason}.`,
371
+ incidentLogAttributes,
372
+ );
373
+
374
+ input.evaluationSummary?.events.push({
375
+ type: "incident-skipped",
376
+ title: "Incident suppressed by monitor dependency",
377
+ message: `Skipped creating incidents because ${suppressionReason}. This monitor's status still updates normally; open incidents still auto-resolve.`,
378
+ relatedCriteriaId: input.criteriaInstance.data?.id,
379
+ at: OneUptimeDate.getCurrentDate(),
380
+ });
381
+
382
+ return;
383
+ }
384
+
345
385
  /*
346
386
  * Proxmox/Ceph monitors: resolve the monitored cluster once per
347
387
  * evaluation (lookup-only, from the step config's clusterIdentifier)
@@ -45,6 +45,9 @@ import MonitorSummaryCapture from "./MonitorSummaryCapture";
45
45
  import MonitorSummarySnapshot from "../../../Types/Monitor/MonitorSummarySnapshot";
46
46
  import IncomingRequestIncidentGrouping from "./IncomingRequestIncidentGrouping";
47
47
  import MonitorMaintenanceSuppression from "./MonitorMaintenanceSuppression";
48
+ import MonitorDependencySuppression, {
49
+ DependencySuppressionResult,
50
+ } from "./MonitorDependencySuppression";
48
51
  import MonitorStatusTimelineUtil from "./MonitorStatusTimeline";
49
52
  import CaptureSpan from "../Telemetry/CaptureSpan";
50
53
  import ExceptionMessages from "../../../Types/Exception/ExceptionMessages";
@@ -150,6 +153,21 @@ export default class MonitorResourceUtil {
150
153
  name: true,
151
154
  },
152
155
  customFields: true,
156
+ /*
157
+ * Alert-dependency suppression inputs. Selected here for the same
158
+ * reason as labels: this query already loads the monitor on the
159
+ * hottest path, and both lists are empty for the overwhelming
160
+ * majority of monitors, in which case suppression costs nothing.
161
+ * Ids only — names are fetched by the suppression util's own
162
+ * parents query, so selecting them here would just duplicate the
163
+ * joined row payload on every evaluation.
164
+ */
165
+ dependsOnMonitors: {
166
+ _id: true,
167
+ },
168
+ suppressAlertsWhenParentMonitorStatuses: {
169
+ _id: true,
170
+ },
153
171
  },
154
172
  props: {
155
173
  isRoot: true,
@@ -917,6 +935,22 @@ export default class MonitorResourceUtil {
917
935
  matchesPerSeries: response.perSeriesMatches,
918
936
  });
919
937
 
938
+ /*
939
+ * Alert-dependency suppression: if any parent monitor this monitor
940
+ * depends on is currently in a suppressing status (offline by
941
+ * default), skip creating incidents/alerts for this evaluation.
942
+ * Deliberately computed AFTER the status timeline update above —
943
+ * the child's own status must keep tracking reality (status pages,
944
+ * transitive dependency checks); only the redundant paging is
945
+ * silenced. The resolve path for already-open incidents/alerts is
946
+ * likewise untouched. Zero queries when the monitor has no
947
+ * dependencies configured.
948
+ */
949
+ const dependencySuppression: DependencySuppressionResult =
950
+ await MonitorDependencySuppression.getDependencySuppression({
951
+ monitor: monitor,
952
+ });
953
+
920
954
  /*
921
955
  * Freeze the Monitor Summary as it stands right now, before any
922
956
  * incident or alert is created from it. Both creators store the
@@ -945,6 +979,7 @@ export default class MonitorResourceUtil {
945
979
  },
946
980
  matchesPerSeries: response.perSeriesMatches,
947
981
  suppressedSeriesFingerprints,
982
+ dependencySuppression,
948
983
  /*
949
984
  * Incoming-request grouping is event-driven: a webhook describes
950
985
  * only the keys in its payload, so absence from this tick is not
@@ -969,6 +1004,7 @@ export default class MonitorResourceUtil {
969
1004
  },
970
1005
  matchesPerSeries: response.perSeriesMatches,
971
1006
  suppressedSeriesFingerprints,
1007
+ dependencySuppression,
972
1008
  /*
973
1009
  * Incoming-request grouping is event-driven (see the incident
974
1010
  * create call above): skip the snapshot absence-resolve pass for