@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
@@ -0,0 +1,67 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class AddMonitorDependency1786449497966 implements MigrationInterface {
4
+ public name = "AddMonitorDependency1786449497966";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `CREATE TABLE "MonitorDependency" ("monitorId" uuid NOT NULL, "dependsOnMonitorId" uuid NOT NULL, CONSTRAINT "PK_26790391f134c5a87b2aa70a902" PRIMARY KEY ("monitorId", "dependsOnMonitorId"))`,
9
+ );
10
+ await queryRunner.query(
11
+ `CREATE INDEX "IDX_953533a93dba2f345283474c60" ON "MonitorDependency" ("monitorId") `,
12
+ );
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_43f849731e1bda0ada73b3d887" ON "MonitorDependency" ("dependsOnMonitorId") `,
15
+ );
16
+ await queryRunner.query(
17
+ `CREATE TABLE "MonitorDependencySuppressionStatus" ("monitorId" uuid NOT NULL, "monitorStatusId" uuid NOT NULL, CONSTRAINT "PK_2889f58c301e8a07d46dd82382c" PRIMARY KEY ("monitorId", "monitorStatusId"))`,
18
+ );
19
+ await queryRunner.query(
20
+ `CREATE INDEX "IDX_747378c59669e4639c4209adc7" ON "MonitorDependencySuppressionStatus" ("monitorId") `,
21
+ );
22
+ await queryRunner.query(
23
+ `CREATE INDEX "IDX_354bf0c679a6dfd64910eb6441" ON "MonitorDependencySuppressionStatus" ("monitorStatusId") `,
24
+ );
25
+ await queryRunner.query(
26
+ `ALTER TABLE "MonitorDependency" ADD CONSTRAINT "FK_953533a93dba2f345283474c60f" FOREIGN KEY ("monitorId") REFERENCES "Monitor"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
27
+ );
28
+ await queryRunner.query(
29
+ `ALTER TABLE "MonitorDependency" ADD CONSTRAINT "FK_43f849731e1bda0ada73b3d8874" FOREIGN KEY ("dependsOnMonitorId") REFERENCES "Monitor"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
30
+ );
31
+ await queryRunner.query(
32
+ `ALTER TABLE "MonitorDependencySuppressionStatus" ADD CONSTRAINT "FK_747378c59669e4639c4209adc78" FOREIGN KEY ("monitorId") REFERENCES "Monitor"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
33
+ );
34
+ await queryRunner.query(
35
+ `ALTER TABLE "MonitorDependencySuppressionStatus" ADD CONSTRAINT "FK_354bf0c679a6dfd64910eb64418" FOREIGN KEY ("monitorStatusId") REFERENCES "MonitorStatus"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
36
+ );
37
+ }
38
+
39
+ public async down(queryRunner: QueryRunner): Promise<void> {
40
+ await queryRunner.query(
41
+ `ALTER TABLE "MonitorDependencySuppressionStatus" DROP CONSTRAINT "FK_354bf0c679a6dfd64910eb64418"`,
42
+ );
43
+ await queryRunner.query(
44
+ `ALTER TABLE "MonitorDependencySuppressionStatus" DROP CONSTRAINT "FK_747378c59669e4639c4209adc78"`,
45
+ );
46
+ await queryRunner.query(
47
+ `ALTER TABLE "MonitorDependency" DROP CONSTRAINT "FK_43f849731e1bda0ada73b3d8874"`,
48
+ );
49
+ await queryRunner.query(
50
+ `ALTER TABLE "MonitorDependency" DROP CONSTRAINT "FK_953533a93dba2f345283474c60f"`,
51
+ );
52
+ await queryRunner.query(
53
+ `DROP INDEX "public"."IDX_354bf0c679a6dfd64910eb6441"`,
54
+ );
55
+ await queryRunner.query(
56
+ `DROP INDEX "public"."IDX_747378c59669e4639c4209adc7"`,
57
+ );
58
+ await queryRunner.query(`DROP TABLE "MonitorDependencySuppressionStatus"`);
59
+ await queryRunner.query(
60
+ `DROP INDEX "public"."IDX_43f849731e1bda0ada73b3d887"`,
61
+ );
62
+ await queryRunner.query(
63
+ `DROP INDEX "public"."IDX_953533a93dba2f345283474c60"`,
64
+ );
65
+ await queryRunner.query(`DROP TABLE "MonitorDependency"`);
66
+ }
67
+ }
@@ -0,0 +1,39 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class AddDeletedProjectTable1786461136170 implements MigrationInterface {
4
+ public name: string = "AddDeletedProjectTable1786461136170";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `CREATE TABLE "DeletedProject" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "projectName" character varying(100) NOT NULL, "projectSlug" character varying(100), "projectCreatedAt" TIMESTAMP WITH TIME ZONE, "projectDeletedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "deletionReason" text, "projectDeletedByUserId" uuid, "projectDeletedByUserName" character varying(50), "projectDeletedByUserEmail" character varying(100), "projectCreatedByUserId" uuid, "projectCreatedByUserName" character varying(50), "projectCreatedByUserEmail" character varying(100), "companyName" character varying(100), "companyPhoneNumber" character varying(30), "companySize" character varying(100), "jobRole" character varying(100), "planName" character varying(100), "paymentProviderPlanId" character varying(100), "paymentProviderCustomerId" character varying(100), "paymentProviderSubscriptionId" character varying(100), "paymentProviderSubscriptionStatus" character varying(100), "paymentProviderSubscriptionSeats" integer, "trialEndsAt" TIMESTAMP WITH TIME ZONE, "activeMonitorCount" integer, "wasProjectBlocked" boolean, CONSTRAINT "PK_bd397da7b51a8649b38c3c8b272" PRIMARY KEY ("_id"))`,
9
+ );
10
+ await queryRunner.query(
11
+ `CREATE INDEX "idx_deleted_project_project_id" ON "DeletedProject" ("projectId") `,
12
+ );
13
+ await queryRunner.query(
14
+ `CREATE INDEX "idx_deleted_project_project_deleted_at" ON "DeletedProject" ("projectDeletedAt") `,
15
+ );
16
+ await queryRunner.query(
17
+ `ALTER TABLE "DeletedProject" ADD CONSTRAINT "FK_bb76f7ebe3ee418ffd79346f203" FOREIGN KEY ("projectDeletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
18
+ );
19
+ await queryRunner.query(
20
+ `ALTER TABLE "DeletedProject" ADD CONSTRAINT "FK_084492367421031e80cd0fdbf1e" FOREIGN KEY ("projectCreatedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
21
+ );
22
+ }
23
+
24
+ public async down(queryRunner: QueryRunner): Promise<void> {
25
+ await queryRunner.query(
26
+ `ALTER TABLE "DeletedProject" DROP CONSTRAINT "FK_084492367421031e80cd0fdbf1e"`,
27
+ );
28
+ await queryRunner.query(
29
+ `ALTER TABLE "DeletedProject" DROP CONSTRAINT "FK_bb76f7ebe3ee418ffd79346f203"`,
30
+ );
31
+ await queryRunner.query(
32
+ `DROP INDEX "public"."idx_deleted_project_project_deleted_at"`,
33
+ );
34
+ await queryRunner.query(
35
+ `DROP INDEX "public"."idx_deleted_project_project_id"`,
36
+ );
37
+ await queryRunner.query(`DROP TABLE "DeletedProject"`);
38
+ }
39
+ }
@@ -512,6 +512,9 @@ import { AddInvestigationCodeFixRecommendation1786500000000 } from "./1786500000
512
512
  import { AddInvestigationAnalysisTldr1786600000000 } from "./1786600000000-AddInvestigationAnalysisTldr";
513
513
  import { DropProjectCallSMSConfigCredentialUniques1786700000000 } from "./1786700000000-DropProjectCallSMSConfigCredentialUniques";
514
514
  import { AddDataSourceTable1786303472848 } from "./1786303472848-AddDataSourceTable";
515
+ import { MigrationName1786446545142 } from "./1786446545142-MigrationName";
516
+ import { AddMonitorDependency1786449497966 } from "./1786449497966-AddMonitorDependency";
517
+ import { AddDeletedProjectTable1786461136170 } from "./1786461136170-AddDeletedProjectTable";
515
518
 
516
519
  export default [
517
520
  InitialMigration,
@@ -1028,4 +1031,7 @@ export default [
1028
1031
  AddInvestigationAnalysisTldr1786600000000,
1029
1032
  DropProjectCallSMSConfigCredentialUniques1786700000000,
1030
1033
  AddDataSourceTable1786303472848,
1034
+ MigrationName1786446545142,
1035
+ AddMonitorDependency1786449497966,
1036
+ AddDeletedProjectTable1786461136170,
1031
1037
  ];
@@ -15,6 +15,7 @@ import AIAgentOwnerTeamService from "./AIAgentOwnerTeamService";
15
15
  import TeamMemberService from "./TeamMemberService";
16
16
  import BadDataException from "../../Types/Exception/BadDataException";
17
17
  import ProjectService from "./ProjectService";
18
+ import FileService from "./FileService";
18
19
  import Dictionary from "../../Types/Dictionary";
19
20
  import OneUptimeDate from "../../Types/Date";
20
21
  import UserNotificationSettingService from "./UserNotificationSettingService";
@@ -174,6 +175,21 @@ export class Service extends DatabaseService<Model> {
174
175
  return { createBy: createBy, carryForward: [] };
175
176
  }
176
177
 
178
+ /*
179
+ * An AI agent icon is rendered by the id-based image route, which
180
+ * serves only public files. The file picker uploads it private, so
181
+ * attaching it to an agent is the point at which it becomes public.
182
+ */
183
+ @CaptureSpan()
184
+ protected override async onCreateSuccess(
185
+ _onCreate: OnCreate<Model>,
186
+ createdItem: Model,
187
+ ): Promise<Model> {
188
+ await FileService.makeFilePublic(createdItem.iconFileId);
189
+
190
+ return createdItem;
191
+ }
192
+
177
193
  @CaptureSpan()
178
194
  public async getOwners(aiAgentId: ObjectID): Promise<Array<User>> {
179
195
  if (!aiAgentId) {
@@ -339,6 +355,10 @@ export class Service extends DatabaseService<Model> {
339
355
  onUpdate: OnUpdate<Model>,
340
356
  _updatedItemIds: Array<ObjectID>,
341
357
  ): Promise<OnUpdate<Model>> {
358
+ await FileService.makeFilePublic(
359
+ onUpdate.updateBy.data.iconFileId as ObjectID | undefined,
360
+ );
361
+
342
362
  if (
343
363
  onUpdate.carryForward &&
344
364
  onUpdate.carryForward.aiAgentsToNotifyOwners.length > 0
@@ -1,18 +1,17 @@
1
1
  import CreateBy from "../Types/Database/CreateBy";
2
2
  import DeleteBy from "../Types/Database/DeleteBy";
3
- import { OnCreate, OnDelete } from "../Types/Database/Hooks";
3
+ import UpdateBy from "../Types/Database/UpdateBy";
4
+ import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
4
5
  import GreenlockUtil from "../Utils/Greenlock/Greenlock";
5
6
  import logger, { LogAttributes } from "../Utils/Logger";
6
7
  import DatabaseService from "./DatabaseService";
7
8
  import DomainService from "./DomainService";
8
9
  import HTTPErrorResponse from "../../Types/API/HTTPErrorResponse";
9
10
  import HTTPResponse from "../../Types/API/HTTPResponse";
10
- import URL from "../../Types/API/URL";
11
11
  import LIMIT_MAX from "../../Types/Database/LimitMax";
12
12
  import BadDataException from "../../Types/Exception/BadDataException";
13
13
  import { JSONObject } from "../../Types/JSON";
14
14
  import ObjectID from "../../Types/ObjectID";
15
- import API from "../../Utils/API";
16
15
  import AcmeCertificate from "../../Models/DatabaseModels/AcmeCertificate";
17
16
  import DomainModel from "../../Models/DatabaseModels/Domain";
18
17
  import DashboardDomain from "../../Models/DatabaseModels/DashboardDomain";
@@ -22,11 +21,60 @@ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
22
21
  import { DashboardCNameRecord } from "../EnvironmentConfig";
23
22
  import Domain from "../Types/Domain";
24
23
 
24
+ const DASHBOARD_DOMAIN_EGRESS_LABEL: string = "Dashboard domain";
25
+
25
26
  export class Service extends DatabaseService<DashboardDomain> {
26
27
  public constructor() {
27
28
  super(DashboardDomain);
28
29
  }
29
30
 
31
+ /*
32
+ * Normalize a submitted subdomain and reject anything that is not a plain
33
+ * DNS label chain.
34
+ *
35
+ * fullDomain is built as `${subdomain}.${baseDomain}` and then interpolated
36
+ * into "https://" + fullDomain + "/dashboard-api/..." — and URL parsing
37
+ * treats everything before the first "/" as the host. Without this check a
38
+ * subdomain of "169.254.169.254/latest/meta-data/#" hands an attacker the
39
+ * host, the port and the path of a request the certificate cron then makes
40
+ * unattended, every 15 minutes, from inside the cluster.
41
+ */
42
+ private static normalizeAndValidateSubdomain(
43
+ subdomain: string | undefined,
44
+ ): string {
45
+ const normalized: string = subdomain?.trim().toLowerCase() || "";
46
+
47
+ // "@" is the documented way to ask for the root domain.
48
+ if (normalized === "" || normalized === "@") {
49
+ return "";
50
+ }
51
+
52
+ if (!Domain.isValidSubdomain(normalized)) {
53
+ throw new BadDataException(
54
+ `Subdomain ${normalized} is not valid. Use a plain subdomain such as "dashboard" — schemes, ports, paths and "/" are not allowed.`,
55
+ );
56
+ }
57
+
58
+ return normalized;
59
+ }
60
+
61
+ @CaptureSpan()
62
+ protected override async onBeforeUpdate(
63
+ updateBy: UpdateBy<DashboardDomain>,
64
+ ): Promise<OnUpdate<DashboardDomain>> {
65
+ /*
66
+ * Create-time validation alone leaves the value editable afterwards —
67
+ * subdomain is ProjectMember-updatable.
68
+ */
69
+ if (updateBy.data.subdomain !== undefined) {
70
+ updateBy.data.subdomain = Service.normalizeAndValidateSubdomain(
71
+ updateBy.data.subdomain as string,
72
+ );
73
+ }
74
+
75
+ return { updateBy, carryForward: null };
76
+ }
77
+
30
78
  @CaptureSpan()
31
79
  protected override async onBeforeCreate(
32
80
  createBy: CreateBy<DashboardDomain>,
@@ -48,14 +96,11 @@ export class Service extends DatabaseService<DashboardDomain> {
48
96
  );
49
97
  }
50
98
 
51
- let normalizedSubdomain: string =
52
- createBy.data.subdomain?.trim().toLowerCase() || "";
53
-
54
- if (normalizedSubdomain === "@") {
55
- normalizedSubdomain = "";
56
- }
99
+ createBy.data.subdomain = Service.normalizeAndValidateSubdomain(
100
+ createBy.data.subdomain,
101
+ );
57
102
 
58
- createBy.data.subdomain = normalizedSubdomain;
103
+ const normalizedSubdomain: string = createBy.data.subdomain;
59
104
 
60
105
  if (domain) {
61
106
  const baseDomain: string =
@@ -230,13 +275,13 @@ export class Service extends DatabaseService<DashboardDomain> {
230
275
  ): Promise<boolean> {
231
276
  try {
232
277
  const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
233
- await API.get({
234
- url: URL.fromString(
278
+ await Domain.getForDomainVerification({
279
+ url:
235
280
  "https://" +
236
- fulldomain +
237
- "/dashboard-api/cname-verification/" +
238
- token,
239
- ),
281
+ fulldomain +
282
+ "/dashboard-api/cname-verification/" +
283
+ token,
284
+ targetLabel: DASHBOARD_DOMAIN_EGRESS_LABEL,
240
285
  });
241
286
 
242
287
  if (result.isFailure()) {
@@ -317,13 +362,13 @@ export class Service extends DatabaseService<DashboardDomain> {
317
362
 
318
363
  try {
319
364
  const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
320
- await API.get({
321
- url: URL.fromString(
365
+ await Domain.getForDomainVerification({
366
+ url:
322
367
  "http://" +
323
- fullDomain +
324
- "/dashboard-api/cname-verification/" +
325
- token,
326
- ),
368
+ fullDomain +
369
+ "/dashboard-api/cname-verification/" +
370
+ token,
371
+ targetLabel: DASHBOARD_DOMAIN_EGRESS_LABEL,
327
372
  });
328
373
 
329
374
  logger.debug("CNAME verification result", {
@@ -348,13 +393,13 @@ export class Service extends DatabaseService<DashboardDomain> {
348
393
 
349
394
  try {
350
395
  const resultHttps: HTTPErrorResponse | HTTPResponse<JSONObject> =
351
- await API.get({
352
- url: URL.fromString(
396
+ await Domain.getForDomainVerification({
397
+ url:
353
398
  "https://" +
354
- fullDomain +
355
- "/dashboard-api/cname-verification/" +
356
- token,
357
- ),
399
+ fullDomain +
400
+ "/dashboard-api/cname-verification/" +
401
+ token,
402
+ targetLabel: DASHBOARD_DOMAIN_EGRESS_LABEL,
358
403
  });
359
404
 
360
405
  logger.debug("CNAME verification result for https", {
@@ -1489,6 +1489,7 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
1489
1489
  _id: deleteById.id.toString(),
1490
1490
  } as any,
1491
1491
  deletedByUser: deleteById.deletedByUser,
1492
+ deletionReason: deleteById.deletionReason,
1492
1493
  props: deleteById.props,
1493
1494
  });
1494
1495
  }
@@ -0,0 +1,138 @@
1
+ import { IsBillingEnabled } from "../EnvironmentConfig";
2
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
3
+ import DatabaseService from "./DatabaseService";
4
+ import UserService from "./UserService";
5
+ import Model from "../../Models/DatabaseModels/DeletedProject";
6
+ import Project from "../../Models/DatabaseModels/Project";
7
+ import User from "../../Models/DatabaseModels/User";
8
+ import OneUptimeDate from "../../Types/Date";
9
+ import ObjectID from "../../Types/ObjectID";
10
+ import Phone from "../../Types/Phone";
11
+
12
+ export class Service extends DatabaseService<Model> {
13
+ public constructor() {
14
+ super(Model);
15
+ }
16
+
17
+ /*
18
+ * Records a project that has just been deleted so the team can follow up with
19
+ * the customer. The project row is already gone by the time this runs, so
20
+ * everything written here has to come from the snapshot the caller took
21
+ * before the delete (ProjectService.onBeforeDelete).
22
+ *
23
+ * SaaS only. Self-hosted installs have no one to reach out to, and the
24
+ * gate lives here rather than at the call site so every caller gets it.
25
+ *
26
+ * Returns the row it wrote, or null when logging was skipped.
27
+ */
28
+ @CaptureSpan()
29
+ public async logProjectDeletion(data: {
30
+ project: Project;
31
+ deletedByUserId?: ObjectID | undefined;
32
+ deletionReason?: string | undefined;
33
+ }): Promise<Model | null> {
34
+ if (!IsBillingEnabled) {
35
+ return null;
36
+ }
37
+
38
+ const project: Project = data.project;
39
+
40
+ if (!project.id) {
41
+ return null;
42
+ }
43
+
44
+ /*
45
+ * Who to reach out to. The user who deleted the project is usually also
46
+ * the one who created it - reuse the snapshot in that case instead of
47
+ * spending a query on it.
48
+ */
49
+ let deletedByUser: User | null = null;
50
+
51
+ if (data.deletedByUserId) {
52
+ if (
53
+ project.createdByUser &&
54
+ project.createdByUserId?.toString() === data.deletedByUserId.toString()
55
+ ) {
56
+ deletedByUser = project.createdByUser;
57
+ } else {
58
+ deletedByUser = await UserService.findOneById({
59
+ id: data.deletedByUserId,
60
+ select: {
61
+ _id: true,
62
+ name: true,
63
+ email: true,
64
+ companyName: true,
65
+ companyPhoneNumber: true,
66
+ companySize: true,
67
+ jobRole: true,
68
+ },
69
+ props: {
70
+ isRoot: true,
71
+ },
72
+ });
73
+ }
74
+ }
75
+
76
+ const createdByUser: User | undefined = project.createdByUser;
77
+
78
+ const deletedProject: Model = new Model();
79
+
80
+ deletedProject.projectId = project.id;
81
+ deletedProject.projectName = project.name || "";
82
+ deletedProject.projectSlug = project.slug;
83
+ deletedProject.projectCreatedAt = project.createdAt;
84
+ deletedProject.projectDeletedAt = OneUptimeDate.getCurrentDate();
85
+ deletedProject.deletionReason = data.deletionReason;
86
+
87
+ deletedProject.projectDeletedByUserId = data.deletedByUserId;
88
+ deletedProject.projectDeletedByUserName = deletedByUser?.name?.toString();
89
+ deletedProject.projectDeletedByUserEmail = deletedByUser?.email;
90
+
91
+ deletedProject.projectCreatedByUserId = project.createdByUserId;
92
+ deletedProject.projectCreatedByUserName = createdByUser?.name?.toString();
93
+ deletedProject.projectCreatedByUserEmail = createdByUser?.email;
94
+
95
+ /*
96
+ * Company details are collected at signup and hang off the User, so take
97
+ * them from whoever created the project and fall back to whoever deleted
98
+ * it - between the two there is usually one filled-in answer.
99
+ */
100
+ const companyName: string | undefined =
101
+ createdByUser?.companyName || deletedByUser?.companyName;
102
+ const companyPhoneNumber: Phone | undefined =
103
+ createdByUser?.companyPhoneNumber || deletedByUser?.companyPhoneNumber;
104
+ const companySize: string | undefined =
105
+ createdByUser?.companySize || deletedByUser?.companySize;
106
+ const jobRole: string | undefined =
107
+ createdByUser?.jobRole || deletedByUser?.jobRole;
108
+
109
+ deletedProject.companyName = companyName;
110
+ deletedProject.companyPhoneNumber = companyPhoneNumber;
111
+ deletedProject.companySize = companySize;
112
+ deletedProject.jobRole = jobRole;
113
+
114
+ deletedProject.planName = project.planName;
115
+ deletedProject.paymentProviderPlanId = project.paymentProviderPlanId;
116
+ deletedProject.paymentProviderCustomerId =
117
+ project.paymentProviderCustomerId;
118
+ deletedProject.paymentProviderSubscriptionId =
119
+ project.paymentProviderSubscriptionId;
120
+ deletedProject.paymentProviderSubscriptionStatus =
121
+ project.paymentProviderSubscriptionStatus;
122
+ deletedProject.paymentProviderSubscriptionSeats =
123
+ project.paymentProviderSubscriptionSeats;
124
+ deletedProject.trialEndsAt = project.trialEndsAt;
125
+
126
+ deletedProject.activeMonitorCount = project.currentActiveMonitorsCount;
127
+ deletedProject.wasProjectBlocked = project.isBlocked ?? false;
128
+
129
+ return await this.create({
130
+ data: deletedProject,
131
+ props: {
132
+ isRoot: true,
133
+ },
134
+ });
135
+ }
136
+ }
137
+
138
+ export default new Service();
@@ -4,15 +4,30 @@ import FindBy from "../Types/Database/FindBy";
4
4
  import { OnCreate, OnDelete, OnFind, OnUpdate } from "../Types/Database/Hooks";
5
5
  import UpdateBy from "../Types/Database/UpdateBy";
6
6
  import DatabaseService from "./DatabaseService";
7
+ import BadDataException from "../../Types/Exception/BadDataException";
7
8
  import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
8
9
  import File from "../../Models/DatabaseModels/File";
10
+ import MimeType from "../../Types/File/MimeType";
11
+ import ObjectID from "../../Types/ObjectID";
9
12
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
13
+ import logger from "../Utils/Logger";
10
14
  import crypto from "crypto";
11
15
 
12
16
  const generateImageAccessToken: () => string = (): string => {
13
17
  return crypto.randomBytes(32).toString("hex");
14
18
  };
15
19
 
20
+ /*
21
+ * fileType is declared as MimeType but persisted as a varchar, so the enum
22
+ * buys nothing at runtime - the API will happily store "text/html" if a client
23
+ * asks for it. Response.sendFileResponse refuses to echo an unknown type back,
24
+ * but keeping junk out of the column in the first place means the stored row
25
+ * matches what we are willing to serve.
26
+ */
27
+ const ALLOWED_MIME_TYPES: Set<string> = new Set<string>(
28
+ Object.values(MimeType),
29
+ );
30
+
16
31
  export class Service extends DatabaseService<File> {
17
32
  public constructor() {
18
33
  super(File);
@@ -22,6 +37,18 @@ export class Service extends DatabaseService<File> {
22
37
  protected override async onBeforeCreate(
23
38
  createBy: CreateBy<File>,
24
39
  ): Promise<OnCreate<File>> {
40
+ const fileType: string = (createBy.data.fileType || "")
41
+ .trim()
42
+ .toLowerCase();
43
+
44
+ if (!ALLOWED_MIME_TYPES.has(fileType)) {
45
+ throw new BadDataException(
46
+ "This file type is not supported. Please upload a supported file type.",
47
+ );
48
+ }
49
+
50
+ createBy.data.fileType = fileType as MimeType;
51
+
25
52
  /*
26
53
  * Always generate an unguessable access token server-side. The token
27
54
  * is the only safe way to address an inline-uploaded image in
@@ -56,6 +83,40 @@ export class Service extends DatabaseService<File> {
56
83
  return { deleteBy, carryForward: null };
57
84
  }
58
85
 
86
+ /*
87
+ * Marks a file as anonymously readable. Uploads from the file picker
88
+ * arrive private, so attaching one as an intentionally public asset
89
+ * (probe icon, AI agent icon) is the point at which it becomes public
90
+ * — those are served by the id-based image route, which serves only
91
+ * public files. Best-effort: a visibility sync failure must never fail
92
+ * the write the user actually asked for.
93
+ */
94
+ @CaptureSpan()
95
+ public async makeFilePublic(
96
+ fileId: ObjectID | undefined | null,
97
+ ): Promise<void> {
98
+ if (!fileId) {
99
+ return;
100
+ }
101
+
102
+ try {
103
+ await this.updateOneById({
104
+ id: fileId,
105
+ data: {
106
+ isPublic: true,
107
+ },
108
+ props: {
109
+ isRoot: true,
110
+ ignoreHooks: true,
111
+ },
112
+ });
113
+ } catch (err) {
114
+ logger.error(
115
+ `Failed to mark file ${fileId.toString()} public: ${String(err)}`,
116
+ );
117
+ }
118
+ }
119
+
59
120
  @CaptureSpan()
60
121
  protected override async onBeforeFind(
61
122
  findBy: FindBy<File>,
@@ -14,6 +14,7 @@ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
14
14
  import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
15
15
  import File from "../../Models/DatabaseModels/File";
16
16
  import FileAttachmentMarkdownUtil from "../Utils/FileAttachmentMarkdownUtil";
17
+ import { syncIsPublicForMarkdownImages } from "../Utils/InlineImageAccessTokenSync";
17
18
 
18
19
  export class Service extends DatabaseService<Model> {
19
20
  public constructor() {
@@ -116,6 +117,17 @@ export class Service extends DatabaseService<Model> {
116
117
  const userId: ObjectID | null | undefined =
117
118
  createdItem.createdByUserId || createdItem.createdByUser?.id;
118
119
 
120
+ /*
121
+ * A public note is always rendered on the status page, so any inline
122
+ * image the markdown editor uploaded as private must flip to public
123
+ * for anonymous status page viewers to be able to render it.
124
+ */
125
+ await syncIsPublicForMarkdownImages(
126
+ createdItem.note,
127
+ true,
128
+ `incident episode public note ${createdItem.id?.toString()}`,
129
+ );
130
+
119
131
  const incidentEpisodeId: ObjectID = createdItem.incidentEpisodeId!;
120
132
  const projectId: ObjectID = createdItem.projectId!;
121
133
  const episodeNumberResult: {
@@ -185,6 +197,12 @@ ${(createdItem.note || "") + attachmentsMarkdown}
185
197
  for (const updatedItem of updatedItems) {
186
198
  const episode: IncidentEpisode = updatedItem.incidentEpisode!;
187
199
 
200
+ await syncIsPublicForMarkdownImages(
201
+ updatedItem.note,
202
+ true,
203
+ `incident episode public note ${updatedItem.id?.toString()}`,
204
+ );
205
+
188
206
  const attachmentsMarkdown: string = await this.getAttachmentsMarkdown(
189
207
  updatedItem.id!,
190
208
  "/incident-episode-public-note/attachment",
@@ -14,6 +14,7 @@ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
14
14
  import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
15
15
  import File from "../../Models/DatabaseModels/File";
16
16
  import FileAttachmentMarkdownUtil from "../Utils/FileAttachmentMarkdownUtil";
17
+ import { syncIsPublicForMarkdownImages } from "../Utils/InlineImageAccessTokenSync";
17
18
 
18
19
  export class Service extends DatabaseService<Model> {
19
20
  public constructor() {
@@ -116,6 +117,17 @@ export class Service extends DatabaseService<Model> {
116
117
  const userId: ObjectID | null | undefined =
117
118
  createdItem.createdByUserId || createdItem.createdByUser?.id;
118
119
 
120
+ /*
121
+ * A public note is always rendered on the status page, so any inline
122
+ * image the markdown editor uploaded as private must flip to public
123
+ * for anonymous status page viewers to be able to render it.
124
+ */
125
+ await syncIsPublicForMarkdownImages(
126
+ createdItem.note,
127
+ true,
128
+ `incident public note ${createdItem.id?.toString()}`,
129
+ );
130
+
119
131
  const incidentId: ObjectID = createdItem.incidentId!;
120
132
  const projectId: ObjectID = createdItem.projectId!;
121
133
  const incidentNumberResult: {
@@ -187,6 +199,12 @@ ${(createdItem.note || "") + attachmentsMarkdown}
187
199
  for (const updatedItem of updatedItems) {
188
200
  const incident: Incident = updatedItem.incident!;
189
201
 
202
+ await syncIsPublicForMarkdownImages(
203
+ updatedItem.note,
204
+ true,
205
+ `incident public note ${updatedItem.id?.toString()}`,
206
+ );
207
+
190
208
  const attachmentsMarkdown: string = await this.getAttachmentsMarkdown(
191
209
  updatedItem.id!,
192
210
  "/incident-public-note/attachment",
@@ -283,10 +283,12 @@ import NetworkFlowService from "./NetworkFlowService";
283
283
  import OnCallDutyPolicyTimeLogService from "./OnCallDutyPolicyTimeLogService";
284
284
  import ProjectSCIMLogService from "./ProjectSCIMLogService";
285
285
  import StatusPageSCIMLogService from "./StatusPageSCIMLogService";
286
+ import DeletedProjectService from "./DeletedProjectService";
286
287
 
287
288
  const services: Array<BaseService> = [
288
289
  OnCallDutyPolicyTimeLogService,
289
290
  AcmeCertificateService,
291
+ DeletedProjectService,
290
292
  PromoCodeService,
291
293
  EnterpriseLicenseService,
292
294
  EnterpriseLicenseInstanceService,