@oneuptime/common 12.0.5 → 12.0.6

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 (528) hide show
  1. package/Models/DatabaseModels/AIRun.ts +33 -0
  2. package/Models/DatabaseModels/DataSource.ts +744 -0
  3. package/Models/DatabaseModels/Index.ts +3 -0
  4. package/Models/DatabaseModels/ProjectCallSMSConfig.ts +10 -2
  5. package/Models/DatabaseModels/User.ts +2 -0
  6. package/Models/DatabaseModels/UserOnCallLog.ts +2 -0
  7. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +2 -0
  8. package/Models/DatabaseModels/UserSession.ts +2 -0
  9. package/Models/DatabaseModels/UserTotpAuth.ts +6 -4
  10. package/Models/DatabaseModels/UserWebAuthn.ts +5 -3
  11. package/Server/API/AIInsightAPI.ts +47 -4
  12. package/Server/API/AIInvestigationAPI.ts +25 -0
  13. package/Server/API/DashboardAPI.ts +176 -492
  14. package/Server/API/DataSourceAPI.ts +268 -0
  15. package/Server/API/StatusPageAPI.ts +11 -1
  16. package/Server/API/UserAPI.ts +119 -0
  17. package/Server/Infrastructure/ClickhouseConfig.ts +59 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.ts +39 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.ts +24 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.ts +76 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  22. package/Server/Infrastructure/Queue.ts +26 -0
  23. package/Server/Infrastructure/QueueWorker.ts +17 -0
  24. package/Server/Middleware/TelemetryIngest.ts +8 -3
  25. package/Server/Services/AIInsightService.ts +132 -12
  26. package/Server/Services/AIRunService.ts +34 -0
  27. package/Server/Services/AIService.ts +17 -2
  28. package/Server/Services/AlertService.ts +38 -32
  29. package/Server/Services/AnalyticsDatabaseService.ts +8 -4
  30. package/Server/Services/DataSourceService.ts +200 -0
  31. package/Server/Services/HostService.ts +92 -0
  32. package/Server/Services/IncidentService.ts +45 -0
  33. package/Server/Services/Index.ts +2 -0
  34. package/Server/Services/MonitorService.ts +49 -0
  35. package/Server/Services/MonitorStatusService.ts +166 -0
  36. package/Server/Services/OpenTelemetryIngestService.ts +255 -184
  37. package/Server/Services/RumSessionPinService.ts +7 -21
  38. package/Server/Services/StatusPageSubscriberService.ts +13 -0
  39. package/Server/Services/UserService.ts +280 -9
  40. package/Server/Static/Vendor/README.md +62 -0
  41. package/Server/Static/Vendor/fonts/InterVariable.woff2 +0 -0
  42. package/Server/Static/Vendor/highlight/highlight.min.js +1244 -0
  43. package/Server/Static/Vendor/highlight/languages/apache.min.js +15 -0
  44. package/Server/Static/Vendor/highlight/languages/bash.min.js +21 -0
  45. package/Server/Static/Vendor/highlight/languages/c.min.js +41 -0
  46. package/Server/Static/Vendor/highlight/languages/cpp.min.js +47 -0
  47. package/Server/Static/Vendor/highlight/languages/csharp.min.js +49 -0
  48. package/Server/Static/Vendor/highlight/languages/css.min.js +31 -0
  49. package/Server/Static/Vendor/highlight/languages/diff.min.js +9 -0
  50. package/Server/Static/Vendor/highlight/languages/dns.min.js +11 -0
  51. package/Server/Static/Vendor/highlight/languages/dockerfile.min.js +8 -0
  52. package/Server/Static/Vendor/highlight/languages/go.min.js +20 -0
  53. package/Server/Static/Vendor/highlight/languages/graphql.min.js +12 -0
  54. package/Server/Static/Vendor/highlight/languages/http.min.js +14 -0
  55. package/Server/Static/Vendor/highlight/languages/ini.min.js +15 -0
  56. package/Server/Static/Vendor/highlight/languages/java.min.js +38 -0
  57. package/Server/Static/Vendor/highlight/languages/javascript.min.js +81 -0
  58. package/Server/Static/Vendor/highlight/languages/json.min.js +8 -0
  59. package/Server/Static/Vendor/highlight/languages/kotlin.min.js +46 -0
  60. package/Server/Static/Vendor/highlight/languages/lua.min.js +15 -0
  61. package/Server/Static/Vendor/highlight/languages/makefile.min.js +14 -0
  62. package/Server/Static/Vendor/highlight/languages/nginx.min.js +21 -0
  63. package/Server/Static/Vendor/highlight/languages/perl.min.js +41 -0
  64. package/Server/Static/Vendor/highlight/languages/php.min.js +59 -0
  65. package/Server/Static/Vendor/highlight/languages/powershell.min.js +39 -0
  66. package/Server/Static/Vendor/highlight/languages/python.min.js +42 -0
  67. package/Server/Static/Vendor/highlight/languages/r.min.js +26 -0
  68. package/Server/Static/Vendor/highlight/languages/ruby.min.js +54 -0
  69. package/Server/Static/Vendor/highlight/languages/rust.min.js +27 -0
  70. package/Server/Static/Vendor/highlight/languages/scala.min.js +28 -0
  71. package/Server/Static/Vendor/highlight/languages/sql.min.js +21 -0
  72. package/Server/Static/Vendor/highlight/languages/swift.min.js +68 -0
  73. package/Server/Static/Vendor/highlight/languages/typescript.min.js +99 -0
  74. package/Server/Static/Vendor/highlight/languages/xml.min.js +29 -0
  75. package/Server/Static/Vendor/highlight/languages/yaml.min.js +28 -0
  76. package/Server/Static/Vendor/highlight/styles/github-dark.min.css +10 -0
  77. package/Server/Static/Vendor/highlight/styles/vs2015.min.css +1 -0
  78. package/Server/Static/Vendor/tailwind/tailwind-3.4.5.js +21028 -0
  79. package/Server/Types/Database/Permissions/BasePermission.ts +7 -0
  80. package/Server/Types/Database/Permissions/DeletePermission.ts +2 -0
  81. package/Server/Types/Database/Permissions/ReadPermission.ts +3 -0
  82. package/Server/Types/Database/Permissions/TenantPermission.ts +101 -16
  83. package/Server/Utils/AI/CodeFix/FixRunBudget.ts +2 -2
  84. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +90 -11
  85. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +1 -0
  86. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +1 -0
  87. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.ts +125 -0
  88. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +25 -15
  89. package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +256 -57
  90. package/Server/Utils/AI/SRE/Insights/InsightStore.ts +76 -18
  91. package/Server/Utils/AI/SRE/InvestigationTldr.ts +352 -0
  92. package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +7 -2
  93. package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +1793 -0
  94. package/Server/Utils/Dashboard/PublicDashboardViewConfig.ts +65 -0
  95. package/Server/Utils/DataSource/ConnectorRegistry.ts +53 -0
  96. package/Server/Utils/DataSource/Connectors/ClickHouseConnector.ts +338 -0
  97. package/Server/Utils/DataSource/Connectors/ElasticsearchConnector.ts +717 -0
  98. package/Server/Utils/DataSource/Connectors/LokiConnector.ts +606 -0
  99. package/Server/Utils/DataSource/Connectors/MySqlConnector.ts +307 -0
  100. package/Server/Utils/DataSource/Connectors/PostgresConnector.ts +260 -0
  101. package/Server/Utils/DataSource/Connectors/PrometheusConnector.ts +555 -0
  102. package/Server/Utils/DataSource/Connectors/RestApiConnector.ts +597 -0
  103. package/Server/Utils/DataSource/Connectors/SqlServerConnector.ts +318 -0
  104. package/Server/Utils/DataSource/EgressGuard.ts +446 -0
  105. package/Server/Utils/DataSource/HttpFetch.ts +221 -0
  106. package/Server/Utils/DataSource/SqlQueryGuard.ts +383 -0
  107. package/Server/Utils/DataSource/SqlResultShaper.ts +372 -0
  108. package/Server/Utils/DataSource/Types.ts +93 -0
  109. package/Server/Utils/Database/PostgresErrorTranslator.ts +172 -17
  110. package/Server/Utils/InProcessMemo.ts +141 -0
  111. package/Server/Utils/InstanceHealth/TelemetryIngestion.ts +628 -0
  112. package/Server/Utils/Monitor/MonitorMetricUtil.ts +58 -0
  113. package/Server/Utils/Monitor/MonitorResource.ts +14 -0
  114. package/Server/Utils/Response.ts +12 -1
  115. package/Server/Utils/SSRFProtection.ts +237 -0
  116. package/Server/Utils/StartServer.ts +8 -0
  117. package/Server/Utils/StatusPageSubscriberWebhook.ts +30 -0
  118. package/Server/Utils/Telemetry/CaptureSpan.ts +30 -18
  119. package/Server/Utils/Telemetry/IngestionTimestamp.ts +75 -0
  120. package/Server/Utils/Telemetry/ResourceHeartbeat.ts +99 -7
  121. package/Server/Utils/Telemetry/Telemetry.ts +112 -1
  122. package/Server/Utils/Telemetry.ts +104 -3
  123. package/Server/Utils/VendorAssets.ts +165 -0
  124. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +28 -5
  125. package/Server/Utils/Workspace/Slack/Slack.ts +5 -0
  126. package/Server/Views/Partials/Head.ejs +21 -7
  127. package/Tests/App/AdminDashboard/AdminProjectsIdFilter.test.tsx +207 -0
  128. package/Tests/App/AdminDashboard/AdminUsersIdFilter.test.tsx +216 -0
  129. package/Tests/App/Dashboard/AIInsightViewActions.test.tsx +422 -0
  130. package/Tests/App/Dashboard/AddWidgetModal.test.tsx +10 -3
  131. package/Tests/App/Dashboard/AlertsSideMenu.test.tsx +387 -0
  132. package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +199 -0
  133. package/Tests/App/Dashboard/DataSourceChartSyntheticConfig.test.tsx +736 -0
  134. package/Tests/App/Dashboard/DataSourceQueryEditor.test.tsx +868 -0
  135. package/Tests/App/Dashboard/DataSourceWidgetCatalog.test.ts +440 -0
  136. package/Tests/App/Dashboard/DataSourceWidgetFetching.test.tsx +2109 -0
  137. package/Tests/App/Dashboard/DataSourceWidgetViews.test.tsx +726 -0
  138. package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +447 -0
  139. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +514 -3
  140. package/Tests/App/Dashboard/ProductMenuBreadcrumbs.test.tsx +391 -0
  141. package/Tests/App/Dashboard/ScheduledMaintenanceSideMenu.test.tsx +326 -0
  142. package/Tests/App/Dashboard/SideMenuHarness.tsx +187 -0
  143. package/Tests/App/Dashboard/WidgetCatalog.test.ts +6 -1
  144. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +1858 -0
  145. package/Tests/Models/DatabaseModels/DataSourceModelSecrets.test.ts +70 -0
  146. package/Tests/Server/API/AIInvestigationAPI.test.ts +187 -0
  147. package/Tests/Server/API/DashboardPublicDataSourceStrip.test.ts +686 -0
  148. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +585 -823
  149. package/Tests/Server/API/DataSourceAPIRoutes.test.ts +486 -0
  150. package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +291 -0
  151. package/Tests/Server/API/UserAuthenticationAPI.test.ts +641 -0
  152. package/Tests/Server/Infrastructure/ClickhouseKeepAliveOptions.test.ts +441 -0
  153. package/Tests/Server/Middleware/TelemetryIngestTokenLog.test.ts +140 -0
  154. package/Tests/Server/Services/AIInsightService.test.ts +266 -11
  155. package/Tests/Server/Services/AIRunAnalysisTldrPersistence.test.ts +160 -0
  156. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +4 -0
  157. package/Tests/Server/Services/AlertMetricResourceAttributes.test.ts +352 -0
  158. package/Tests/Server/Services/DataSourceServiceSettings.test.ts +244 -0
  159. package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +397 -0
  160. package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +41 -2
  161. package/Tests/Server/Services/IncidentMetricResourceAttributes.test.ts +408 -0
  162. package/Tests/Server/Services/MonitorStatusServiceDeleteReferenceCleanup.test.ts +351 -0
  163. package/Tests/Server/Services/MonitorStatusServiceValidation.test.ts +171 -0
  164. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +398 -0
  165. package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +19 -0
  166. package/Tests/Server/Services/ProjectCallSMSConfigCredentialUniqueness.test.ts +305 -0
  167. package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +36 -1
  168. package/Tests/Server/Services/RumSessionPinUniqueViolationRecovery.test.ts +163 -0
  169. package/Tests/Server/Services/UserAuthenticationService.test.ts +973 -0
  170. package/Tests/Server/Types/Database/ObjectIdColumnQuery.test.ts +262 -0
  171. package/Tests/Server/Types/Database/Permissions/TenantPermission.test.ts +358 -0
  172. package/Tests/Server/Utils/AI/FixRunBudget.test.ts +2 -2
  173. package/Tests/Server/Utils/AI/Insights/ExceptionSpikeDetector.test.ts +6 -1
  174. package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +121 -4
  175. package/Tests/Server/Utils/AI/Insights/NewExceptionDetector.test.ts +361 -10
  176. package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +292 -0
  177. package/Tests/Server/Utils/AI/InvestigationTldr.test.ts +623 -0
  178. package/Tests/Server/Utils/AI/InvestigationTldrWiring.test.ts +98 -0
  179. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +857 -0
  180. package/Tests/Server/Utils/Dashboard/PublicDashboardViewConfig.test.ts +480 -0
  181. package/Tests/Server/Utils/DataSource/ClickHouseConnector.test.ts +759 -0
  182. package/Tests/Server/Utils/DataSource/ConnectorRegistry.test.ts +37 -0
  183. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +645 -0
  184. package/Tests/Server/Utils/DataSource/ElasticsearchConnector.test.ts +1206 -0
  185. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +616 -0
  186. package/Tests/Server/Utils/DataSource/LokiConnector.test.ts +970 -0
  187. package/Tests/Server/Utils/DataSource/MySqlConnector.test.ts +935 -0
  188. package/Tests/Server/Utils/DataSource/PostgresConnector.test.ts +854 -0
  189. package/Tests/Server/Utils/DataSource/PrometheusConnector.test.ts +881 -0
  190. package/Tests/Server/Utils/DataSource/RestApiConnector.test.ts +1020 -0
  191. package/Tests/Server/Utils/DataSource/SqlQueryGuard.test.ts +425 -0
  192. package/Tests/Server/Utils/DataSource/SqlResultShaper.test.ts +555 -0
  193. package/Tests/Server/Utils/DataSource/SqlServerConnector.test.ts +934 -0
  194. package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +228 -7
  195. package/Tests/Server/Utils/InProcessMemo.test.ts +292 -0
  196. package/Tests/Server/Utils/InstanceHealth/TelemetryIngestion.test.ts +960 -0
  197. package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +103 -0
  198. package/Tests/Server/Utils/Monitor/MonitorMetricResourceAttributes.test.ts +336 -0
  199. package/Tests/Server/Utils/OfflineAssetHygiene.test.ts +521 -0
  200. package/Tests/Server/Utils/ResponseRenderAnalytics.test.ts +143 -0
  201. package/Tests/Server/Utils/SSRFProtection.test.ts +193 -0
  202. package/Tests/Server/Utils/StatusPageSubscriberWebhook.test.ts +101 -0
  203. package/Tests/Server/Utils/TailwindBuildCopy.test.ts +225 -0
  204. package/Tests/Server/Utils/Telemetry/ResourceHeartbeatL1Memo.test.ts +355 -0
  205. package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +128 -0
  206. package/Tests/Server/Utils/Telemetry/TelemetryUtilAttributeKeys.test.ts +381 -0
  207. package/Tests/Server/Utils/Telemetry.test.ts +87 -0
  208. package/Tests/Server/Utils/VendorAssetIntegrity.test.ts +343 -0
  209. package/Tests/Server/Utils/VendorAssets.test.ts +671 -0
  210. package/Tests/Server/Views/OfflineRender.test.ts +297 -0
  211. package/Tests/Types/Dashboard/DataSourceComponentTypes.test.ts +618 -0
  212. package/Tests/Types/DateClickhouseFormat.test.ts +192 -0
  213. package/Tests/Types/Password.test.ts +363 -0
  214. package/Tests/UI/Components/ConfirmModal.test.tsx +7 -0
  215. package/Tests/UI/Components/ErrorBoundary.test.tsx +53 -0
  216. package/Tests/UI/Components/Modal.test.tsx +281 -1
  217. package/Tests/UI/Components/ObjectIdFilterPipeline.test.tsx +396 -0
  218. package/Tests/UI/Components/StatusPage/ResourceGroupNavigator.test.tsx +1147 -0
  219. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +116 -1
  220. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  221. package/Tests/Utils/Analytics.test.ts +23 -0
  222. package/Tests/Utils/Dashboard/Components/DashboardDataSourceComponents.test.ts +640 -0
  223. package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +138 -0
  224. package/Tests/Utils/DataSource/DataSourceValueReducer.test.ts +526 -0
  225. package/Tests/Utils/Metrics/MetricResourceAttributeUtil.test.ts +691 -0
  226. package/Tests/Utils/StatusPage/GroupHierarchyView.test.ts +1452 -0
  227. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +931 -0
  228. package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +288 -0
  229. package/Tests/Utils/Telemetry/IngestionTimestamp.test.ts +170 -0
  230. package/Types/AI/AIInsightEvidence.ts +6 -0
  231. package/Types/Analytics/RevenueEvent.ts +31 -0
  232. package/Types/Dashboard/DashboardComponentType.ts +31 -0
  233. package/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.ts +27 -0
  234. package/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.ts +32 -0
  235. package/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.ts +30 -0
  236. package/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.ts +55 -0
  237. package/Types/DataSource/DataSourceLimits.ts +62 -0
  238. package/Types/DataSource/DataSourceQueryConfig.ts +41 -0
  239. package/Types/DataSource/DataSourceTableResult.ts +38 -0
  240. package/Types/DataSource/DataSourceType.ts +213 -0
  241. package/Types/Date.ts +43 -3
  242. package/Types/Password.ts +64 -0
  243. package/Types/Permission.ts +46 -0
  244. package/Types/UserAuthenticationStatus.ts +34 -0
  245. package/UI/Components/Button/Button.tsx +1 -1
  246. package/UI/Components/ErrorBoundary.tsx +459 -108
  247. package/UI/Components/Icon/Icon.tsx +10 -9
  248. package/UI/Components/Modal/ConfirmModal.tsx +6 -1
  249. package/UI/Components/Modal/Modal.tsx +267 -35
  250. package/UI/Components/Modal/ModalFooter.tsx +6 -1
  251. package/UI/Components/MoreMenu/MoreMenu.tsx +19 -4
  252. package/UI/Components/MoreMenu/MoreMenuItem.tsx +6 -1
  253. package/UI/Components/StatusPage/ResourceGrid.tsx +314 -0
  254. package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +808 -0
  255. package/UI/Components/StatusPage/ResourceList.tsx +570 -0
  256. package/UI/Styles/Theme.css +18 -0
  257. package/UI/Utils/API/RequestOptions.ts +7 -0
  258. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +1 -0
  259. package/UI/Utils/ModelAPI/ModelAPI.ts +1 -0
  260. package/UI/Utils/TestDataSource.ts +61 -0
  261. package/UI/esbuild-config.js +45 -0
  262. package/Utils/Analytics.ts +15 -0
  263. package/Utils/Dashboard/Components/DashboardDataSourceChartComponent.ts +88 -0
  264. package/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.ts +123 -0
  265. package/Utils/Dashboard/Components/DashboardDataSourceShared.ts +16 -0
  266. package/Utils/Dashboard/Components/DashboardDataSourceTableComponent.ts +72 -0
  267. package/Utils/Dashboard/Components/DashboardDataSourceValueComponent.ts +126 -0
  268. package/Utils/Dashboard/Components/Index.ts +28 -0
  269. package/Utils/DataSource/DataSourceQueryText.ts +94 -0
  270. package/Utils/DataSource/DataSourceValueReducer.ts +156 -0
  271. package/Utils/Metrics/MetricResourceAttributeUtil.ts +380 -0
  272. package/Utils/NetworkDiscovery/ScanTargetUtil.ts +8 -6
  273. package/Utils/StatusPage/GroupHierarchyView.ts +931 -0
  274. package/Utils/StatusPage/ResourceExplorer.ts +853 -0
  275. package/build/dist/Models/DatabaseModels/AIRun.js +34 -0
  276. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  277. package/build/dist/Models/DatabaseModels/DataSource.js +774 -0
  278. package/build/dist/Models/DatabaseModels/DataSource.js.map +1 -0
  279. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  280. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  281. package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js +14 -4
  282. package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js.map +1 -1
  283. package/build/dist/Models/DatabaseModels/User.js +2 -0
  284. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  285. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +2 -0
  286. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  287. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +2 -0
  288. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  289. package/build/dist/Models/DatabaseModels/UserSession.js +2 -0
  290. package/build/dist/Models/DatabaseModels/UserSession.js.map +1 -1
  291. package/build/dist/Models/DatabaseModels/UserTotpAuth.js +6 -4
  292. package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -1
  293. package/build/dist/Models/DatabaseModels/UserWebAuthn.js +5 -3
  294. package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
  295. package/build/dist/Server/API/AIInsightAPI.js +34 -4
  296. package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
  297. package/build/dist/Server/API/AIInvestigationAPI.js +23 -0
  298. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  299. package/build/dist/Server/API/DashboardAPI.js +119 -433
  300. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  301. package/build/dist/Server/API/DataSourceAPI.js +173 -0
  302. package/build/dist/Server/API/DataSourceAPI.js.map +1 -0
  303. package/build/dist/Server/API/StatusPageAPI.js +11 -1
  304. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  305. package/build/dist/Server/API/UserAPI.js +94 -2
  306. package/build/dist/Server/API/UserAPI.js.map +1 -1
  307. package/build/dist/Server/Infrastructure/ClickhouseConfig.js +49 -0
  308. package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
  309. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js +20 -0
  310. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js.map +1 -0
  311. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js +19 -0
  312. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js.map +1 -0
  313. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js +64 -0
  314. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js.map +1 -0
  315. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  316. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  317. package/build/dist/Server/Infrastructure/Queue.js +27 -0
  318. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  319. package/build/dist/Server/Infrastructure/QueueWorker.js +13 -0
  320. package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
  321. package/build/dist/Server/Middleware/TelemetryIngest.js +8 -3
  322. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  323. package/build/dist/Server/Services/AIInsightService.js +110 -10
  324. package/build/dist/Server/Services/AIInsightService.js.map +1 -1
  325. package/build/dist/Server/Services/AIRunService.js +34 -0
  326. package/build/dist/Server/Services/AIRunService.js.map +1 -1
  327. package/build/dist/Server/Services/AIService.js +16 -2
  328. package/build/dist/Server/Services/AIService.js.map +1 -1
  329. package/build/dist/Server/Services/AlertService.js +28 -35
  330. package/build/dist/Server/Services/AlertService.js.map +1 -1
  331. package/build/dist/Server/Services/AnalyticsDatabaseService.js +8 -4
  332. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  333. package/build/dist/Server/Services/DataSourceService.js +159 -0
  334. package/build/dist/Server/Services/DataSourceService.js.map +1 -0
  335. package/build/dist/Server/Services/HostService.js +74 -0
  336. package/build/dist/Server/Services/HostService.js.map +1 -1
  337. package/build/dist/Server/Services/IncidentService.js +35 -24
  338. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  339. package/build/dist/Server/Services/Index.js +2 -0
  340. package/build/dist/Server/Services/Index.js.map +1 -1
  341. package/build/dist/Server/Services/MonitorService.js +45 -0
  342. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  343. package/build/dist/Server/Services/MonitorStatusService.js +129 -0
  344. package/build/dist/Server/Services/MonitorStatusService.js.map +1 -1
  345. package/build/dist/Server/Services/OpenTelemetryIngestService.js +222 -159
  346. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  347. package/build/dist/Server/Services/RumSessionPinService.js +7 -15
  348. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  349. package/build/dist/Server/Services/StatusPageSubscriberService.js +10 -0
  350. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  351. package/build/dist/Server/Services/UserService.js +241 -10
  352. package/build/dist/Server/Services/UserService.js.map +1 -1
  353. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +6 -0
  354. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  355. package/build/dist/Server/Types/Database/Permissions/DeletePermission.js +1 -0
  356. package/build/dist/Server/Types/Database/Permissions/DeletePermission.js.map +1 -1
  357. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js +2 -0
  358. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js.map +1 -1
  359. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +68 -12
  360. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
  361. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +2 -2
  362. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
  363. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +68 -8
  364. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  365. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +1 -0
  366. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  367. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +1 -0
  368. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  369. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js +97 -0
  370. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js.map +1 -0
  371. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +17 -15
  372. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
  373. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +178 -54
  374. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
  375. package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js +65 -16
  376. package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js.map +1 -1
  377. package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js +303 -0
  378. package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js.map +1 -0
  379. package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -1
  380. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +1261 -0
  381. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -0
  382. package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js +47 -0
  383. package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js.map +1 -0
  384. package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js +42 -0
  385. package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js.map +1 -0
  386. package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js +187 -0
  387. package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js.map +1 -0
  388. package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js +493 -0
  389. package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js.map +1 -0
  390. package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js +399 -0
  391. package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js.map +1 -0
  392. package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js +195 -0
  393. package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js.map +1 -0
  394. package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js +149 -0
  395. package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js.map +1 -0
  396. package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js +362 -0
  397. package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js.map +1 -0
  398. package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js +342 -0
  399. package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js.map +1 -0
  400. package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js +186 -0
  401. package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js.map +1 -0
  402. package/build/dist/Server/Utils/DataSource/EgressGuard.js +305 -0
  403. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -0
  404. package/build/dist/Server/Utils/DataSource/HttpFetch.js +134 -0
  405. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -0
  406. package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js +331 -0
  407. package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js.map +1 -0
  408. package/build/dist/Server/Utils/DataSource/SqlResultShaper.js +280 -0
  409. package/build/dist/Server/Utils/DataSource/SqlResultShaper.js.map +1 -0
  410. package/build/dist/Server/Utils/DataSource/Types.js +2 -0
  411. package/build/dist/Server/Utils/DataSource/Types.js.map +1 -0
  412. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +103 -9
  413. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -1
  414. package/build/dist/Server/Utils/InProcessMemo.js +113 -0
  415. package/build/dist/Server/Utils/InProcessMemo.js.map +1 -0
  416. package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js +406 -0
  417. package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js.map +1 -0
  418. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +34 -0
  419. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  420. package/build/dist/Server/Utils/Monitor/MonitorResource.js +14 -0
  421. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  422. package/build/dist/Server/Utils/Response.js +9 -1
  423. package/build/dist/Server/Utils/Response.js.map +1 -1
  424. package/build/dist/Server/Utils/SSRFProtection.js +192 -0
  425. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -0
  426. package/build/dist/Server/Utils/StartServer.js +7 -0
  427. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  428. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js +24 -0
  429. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js.map +1 -1
  430. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +25 -11
  431. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
  432. package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js +32 -0
  433. package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js.map +1 -0
  434. package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js +92 -5
  435. package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -1
  436. package/build/dist/Server/Utils/Telemetry/Telemetry.js +92 -6
  437. package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
  438. package/build/dist/Server/Utils/Telemetry.js +93 -6
  439. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  440. package/build/dist/Server/Utils/VendorAssets.js +121 -0
  441. package/build/dist/Server/Utils/VendorAssets.js.map +1 -0
  442. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +25 -4
  443. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  444. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +5 -0
  445. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  446. package/build/dist/Types/Analytics/RevenueEvent.js +26 -0
  447. package/build/dist/Types/Analytics/RevenueEvent.js.map +1 -0
  448. package/build/dist/Types/Dashboard/DashboardComponentType.js +27 -0
  449. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  450. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js +2 -0
  451. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js.map +1 -0
  452. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js +2 -0
  453. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js.map +1 -0
  454. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js +2 -0
  455. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js.map +1 -0
  456. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js +16 -0
  457. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js.map +1 -0
  458. package/build/dist/Types/DataSource/DataSourceLimits.js +47 -0
  459. package/build/dist/Types/DataSource/DataSourceLimits.js.map +1 -0
  460. package/build/dist/Types/DataSource/DataSourceQueryConfig.js +10 -0
  461. package/build/dist/Types/DataSource/DataSourceQueryConfig.js.map +1 -0
  462. package/build/dist/Types/DataSource/DataSourceTableResult.js +14 -0
  463. package/build/dist/Types/DataSource/DataSourceTableResult.js.map +1 -0
  464. package/build/dist/Types/DataSource/DataSourceType.js +183 -0
  465. package/build/dist/Types/DataSource/DataSourceType.js.map +1 -0
  466. package/build/dist/Types/Date.js +38 -3
  467. package/build/dist/Types/Date.js.map +1 -1
  468. package/build/dist/Types/Password.js +56 -0
  469. package/build/dist/Types/Password.js.map +1 -0
  470. package/build/dist/Types/Permission.js +42 -0
  471. package/build/dist/Types/Permission.js.map +1 -1
  472. package/build/dist/Types/UserAuthenticationStatus.js +2 -0
  473. package/build/dist/Types/UserAuthenticationStatus.js.map +1 -0
  474. package/build/dist/UI/Components/ErrorBoundary.js +388 -72
  475. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  476. package/build/dist/UI/Components/Icon/Icon.js +10 -4
  477. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  478. package/build/dist/UI/Components/Modal/ConfirmModal.js +1 -1
  479. package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
  480. package/build/dist/UI/Components/Modal/Modal.js +178 -19
  481. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  482. package/build/dist/UI/Components/Modal/ModalFooter.js +3 -1
  483. package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
  484. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +9 -6
  485. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  486. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +7 -1
  487. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
  488. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +119 -0
  489. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -0
  490. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +354 -0
  491. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -0
  492. package/build/dist/UI/Components/StatusPage/ResourceList.js +203 -0
  493. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -0
  494. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +1 -6
  495. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  496. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +3 -8
  497. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  498. package/build/dist/UI/Utils/TestDataSource.js +39 -0
  499. package/build/dist/UI/Utils/TestDataSource.js.map +1 -0
  500. package/build/dist/Utils/Analytics.js +4 -0
  501. package/build/dist/Utils/Analytics.js.map +1 -1
  502. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js +79 -0
  503. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js.map +1 -0
  504. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js +111 -0
  505. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js.map +1 -0
  506. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js +15 -0
  507. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js.map +1 -0
  508. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js +62 -0
  509. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js.map +1 -0
  510. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js +112 -0
  511. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js.map +1 -0
  512. package/build/dist/Utils/Dashboard/Components/Index.js +16 -0
  513. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  514. package/build/dist/Utils/DataSource/DataSourceQueryText.js +64 -0
  515. package/build/dist/Utils/DataSource/DataSourceQueryText.js.map +1 -0
  516. package/build/dist/Utils/DataSource/DataSourceValueReducer.js +124 -0
  517. package/build/dist/Utils/DataSource/DataSourceValueReducer.js.map +1 -0
  518. package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js +281 -0
  519. package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js.map +1 -0
  520. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +8 -6
  521. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
  522. package/build/dist/Utils/StatusPage/GroupHierarchyView.js +560 -0
  523. package/build/dist/Utils/StatusPage/GroupHierarchyView.js.map +1 -0
  524. package/build/dist/Utils/StatusPage/ResourceExplorer.js +519 -0
  525. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -0
  526. package/jest.config.json +1 -0
  527. package/package.json +5 -1
  528. package/tsconfig.json +12 -10
@@ -0,0 +1,268 @@
1
+ import UserMiddleware from "../Middleware/UserAuthorization";
2
+ import CommonAPI from "./CommonAPI";
3
+ import DataSourceService, {
4
+ Service as DataSourceServiceType,
5
+ } from "../Services/DataSourceService";
6
+ import {
7
+ ExpressRequest,
8
+ ExpressResponse,
9
+ NextFunction,
10
+ } from "../Utils/Express";
11
+ import Response from "../Utils/Response";
12
+ import BaseAPI from "./BaseAPI";
13
+ import DataSource from "../../Models/DatabaseModels/DataSource";
14
+ import BadDataException from "../../Types/Exception/BadDataException";
15
+ import Exception from "../../Types/Exception/Exception";
16
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
17
+ import { JSONObject } from "../../Types/JSON";
18
+ import ObjectID from "../../Types/ObjectID";
19
+ import AggregatedResult from "../../Types/BaseDatabase/AggregatedResult";
20
+ import DataSourceTableResult from "../../Types/DataSource/DataSourceTableResult";
21
+ import { DataSourceResultKind } from "../../Types/DataSource/DataSourceQueryConfig";
22
+ import {
23
+ DataSourceConnectionSettings,
24
+ DataSourceConnector,
25
+ } from "../Utils/DataSource/Types";
26
+ import ConnectorRegistry from "../Utils/DataSource/ConnectorRegistry";
27
+ import logger from "../Utils/Logger";
28
+
29
+ /*
30
+ * Upper bound on stored/ad-hoc query text. Real PromQL/SQL/DSL queries are
31
+ * a few KB; anything beyond this is abuse or a mistake.
32
+ */
33
+ const MAX_QUERY_LENGTH: number = 100_000;
34
+
35
+ export default class DataSourceAPI extends BaseAPI<
36
+ DataSource,
37
+ DataSourceServiceType
38
+ > {
39
+ public constructor() {
40
+ super(DataSource, DataSourceService);
41
+
42
+ /*
43
+ * Test a data source's connectivity + credentials. Authenticated
44
+ * users only; access is checked by reading the record with the
45
+ * caller's own permissions before any root read of credentials.
46
+ */
47
+ this.router.post(
48
+ `${new this.entityType().getCrudApiPath()?.toString()}/test`,
49
+ UserMiddleware.getUserMiddleware,
50
+ UserMiddleware.requireUserAuthentication,
51
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
52
+ try {
53
+ const body: JSONObject = req.body;
54
+
55
+ const dataSource: DataSource = await this.getAccessibleDataSource({
56
+ req,
57
+ dataSourceId: body["dataSourceId"] as string,
58
+ });
59
+
60
+ const settings: DataSourceConnectionSettings =
61
+ await this.getConnectionSettings(dataSource);
62
+
63
+ const connector: DataSourceConnector = ConnectorRegistry.getConnector(
64
+ settings.dataSourceType,
65
+ );
66
+
67
+ try {
68
+ await connector.testConnection(settings);
69
+ } catch (err) {
70
+ logger.error(err);
71
+ return Response.sendJsonObjectResponse(req, res, {
72
+ ok: false,
73
+ message: this.toFriendlyErrorMessage(err),
74
+ });
75
+ }
76
+
77
+ return Response.sendJsonObjectResponse(req, res, {
78
+ ok: true,
79
+ message: "Connection successful.",
80
+ });
81
+ } catch (err) {
82
+ next(err);
83
+ }
84
+ },
85
+ );
86
+
87
+ /*
88
+ * Execute a query against a data source and return normalized time
89
+ * series (for chart/value/gauge widgets) or rows (for the table
90
+ * widget).
91
+ *
92
+ * SECURITY: authenticated project users only — this route must NEVER
93
+ * be reachable from the anonymous public-dashboard surface, because
94
+ * it executes caller-supplied query text. Public dashboards render a
95
+ * placeholder for data-source widgets instead.
96
+ */
97
+ this.router.post(
98
+ `${new this.entityType().getCrudApiPath()?.toString()}/query`,
99
+ UserMiddleware.getUserMiddleware,
100
+ UserMiddleware.requireUserAuthentication,
101
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
102
+ try {
103
+ const body: JSONObject = req.body;
104
+
105
+ const query: string = (body["query"] as string) || "";
106
+ if (!query || query.trim().length === 0) {
107
+ return Response.sendErrorResponse(
108
+ req,
109
+ res,
110
+ new BadDataException("query is required"),
111
+ );
112
+ }
113
+ if (query.length > MAX_QUERY_LENGTH) {
114
+ return Response.sendErrorResponse(
115
+ req,
116
+ res,
117
+ new BadDataException("query is too long"),
118
+ );
119
+ }
120
+
121
+ const resultKind: DataSourceResultKind =
122
+ body["resultKind"] === DataSourceResultKind.Table
123
+ ? DataSourceResultKind.Table
124
+ : DataSourceResultKind.TimeSeries;
125
+
126
+ const startDate: Date = new Date(body["startDate"] as string);
127
+ const endDate: Date = new Date(body["endDate"] as string);
128
+ if (
129
+ isNaN(startDate.getTime()) ||
130
+ isNaN(endDate.getTime()) ||
131
+ startDate.getTime() >= endDate.getTime()
132
+ ) {
133
+ return Response.sendErrorResponse(
134
+ req,
135
+ res,
136
+ new BadDataException(
137
+ "A valid startDate and endDate are required (startDate must be before endDate).",
138
+ ),
139
+ );
140
+ }
141
+
142
+ let stepInSeconds: number | undefined = undefined;
143
+ if (body["stepInSeconds"] !== undefined) {
144
+ const parsedStep: number = Number(body["stepInSeconds"]);
145
+ if (Number.isFinite(parsedStep) && parsedStep > 0) {
146
+ // Floor, but never to 0 — Loki/Prometheus reject step=0.
147
+ stepInSeconds = Math.max(1, Math.floor(parsedStep));
148
+ }
149
+ }
150
+
151
+ const dataSource: DataSource = await this.getAccessibleDataSource({
152
+ req,
153
+ dataSourceId: body["dataSourceId"] as string,
154
+ });
155
+
156
+ const settings: DataSourceConnectionSettings =
157
+ await this.getConnectionSettings(dataSource);
158
+
159
+ const connector: DataSourceConnector = ConnectorRegistry.getConnector(
160
+ settings.dataSourceType,
161
+ );
162
+
163
+ try {
164
+ if (resultKind === DataSourceResultKind.Table) {
165
+ const tableResult: DataSourceTableResult =
166
+ await connector.queryTable(settings, query, {
167
+ startDate,
168
+ endDate,
169
+ stepInSeconds,
170
+ });
171
+ return Response.sendJsonObjectResponse(req, res, {
172
+ resultKind: DataSourceResultKind.Table,
173
+ result: tableResult as unknown as JSONObject,
174
+ });
175
+ }
176
+
177
+ const timeSeriesResult: AggregatedResult =
178
+ await connector.queryTimeSeries(settings, query, {
179
+ startDate,
180
+ endDate,
181
+ stepInSeconds,
182
+ });
183
+
184
+ return Response.sendJsonObjectResponse(req, res, {
185
+ resultKind: DataSourceResultKind.TimeSeries,
186
+ result: timeSeriesResult as unknown as JSONObject,
187
+ });
188
+ } catch (err) {
189
+ logger.error(err);
190
+ return Response.sendErrorResponse(
191
+ req,
192
+ res,
193
+ new BadDataException(
194
+ `Data source query failed: ${this.toFriendlyErrorMessage(err)}`,
195
+ ),
196
+ );
197
+ }
198
+ } catch (err) {
199
+ next(err);
200
+ }
201
+ },
202
+ );
203
+ }
204
+
205
+ /*
206
+ * Two-phase access pattern (same as LlmProviderAPI /test): first read
207
+ * the record with the CALLER'S permissions — wrong project or missing
208
+ * ReadDataSource yields null — and only then may callers proceed to a
209
+ * root read of credentials.
210
+ */
211
+ private async getAccessibleDataSource(data: {
212
+ req: ExpressRequest;
213
+ dataSourceId: string;
214
+ }): Promise<DataSource> {
215
+ if (!data.dataSourceId) {
216
+ throw new BadDataException("dataSourceId is required");
217
+ }
218
+
219
+ if (!ObjectID.isValidUUID(data.dataSourceId)) {
220
+ throw new BadDataException(
221
+ "Data source not found, or you do not have access to it.",
222
+ );
223
+ }
224
+
225
+ const props: DatabaseCommonInteractionProps =
226
+ await CommonAPI.getDatabaseCommonInteractionProps(data.req);
227
+
228
+ const accessibleDataSource: DataSource | null =
229
+ await DataSourceService.findOneById({
230
+ id: new ObjectID(data.dataSourceId),
231
+ select: {
232
+ _id: true,
233
+ projectId: true,
234
+ dataSourceType: true,
235
+ },
236
+ props: props,
237
+ });
238
+
239
+ if (!accessibleDataSource) {
240
+ throw new BadDataException(
241
+ "Data source not found, or you do not have access to it.",
242
+ );
243
+ }
244
+
245
+ return accessibleDataSource;
246
+ }
247
+
248
+ private async getConnectionSettings(
249
+ dataSource: DataSource,
250
+ ): Promise<DataSourceConnectionSettings> {
251
+ const settings: DataSourceConnectionSettings | null =
252
+ await DataSourceService.getConnectionSettingsById(dataSource.id!);
253
+
254
+ if (!settings) {
255
+ throw new BadDataException("Data source configuration is incomplete.");
256
+ }
257
+
258
+ return settings;
259
+ }
260
+
261
+ private toFriendlyErrorMessage(err: unknown): string {
262
+ const message: string =
263
+ err instanceof Exception
264
+ ? err.message
265
+ : "Could not reach the data source. Please verify the connection details.";
266
+ return message.substring(0, 1000);
267
+ }
268
+ }
@@ -3853,9 +3853,19 @@ export default class StatusPageAPI extends BaseAPI<
3853
3853
  `Updating existing subscriber with ID: ${subscriberId} for status page with ID: ${objectId}`,
3854
3854
  getLogAttributesFromRequest(req as any),
3855
3855
  );
3856
+ /*
3857
+ * Scope the lookup to the status page in the route. This endpoint only
3858
+ * checks read access on that status page, so without the statusPageId
3859
+ * clause anyone holding a subscriber UUID could pass any status page they
3860
+ * can read and edit a subscriber belonging to a different — possibly
3861
+ * private — status page. A subscriber on another page must be
3862
+ * indistinguishable from one that does not exist, so that the shared
3863
+ * "Subscriber not found" below cannot be used to probe for valid UUIDs.
3864
+ */
3856
3865
  statusPageSubscriber = await StatusPageSubscriberService.findOneBy({
3857
3866
  query: {
3858
3867
  _id: subscriberId.toString(),
3868
+ statusPageId: objectId,
3859
3869
  },
3860
3870
  props: {
3861
3871
  isRoot: true,
@@ -3864,7 +3874,7 @@ export default class StatusPageAPI extends BaseAPI<
3864
3874
 
3865
3875
  if (!statusPageSubscriber) {
3866
3876
  logger.debug(
3867
- `Subscriber not found with ID: ${subscriberId}`,
3877
+ `Subscriber not found with ID: ${subscriberId} on status page with ID: ${objectId}`,
3868
3878
  getLogAttributesFromRequest(req as any),
3869
3879
  );
3870
3880
  throw new BadDataException("Subscriber not found");
@@ -12,8 +12,10 @@ import PositiveNumber from "../../Types/PositiveNumber";
12
12
  import TeamMembersByProject, {
13
13
  UserProjectMembership,
14
14
  } from "../../Utils/TeamMembersByProject";
15
+ import Email from "../../Types/Email";
15
16
  import MasterAdminAuthorization from "../Middleware/MasterAdminAuthorization";
16
17
  import TeamMemberService from "../Services/TeamMemberService";
18
+ import UserAuthenticationStatus from "../../Types/UserAuthenticationStatus";
17
19
  import UserService, {
18
20
  Service as UserServiceType,
19
21
  } from "../Services/UserService";
@@ -191,6 +193,123 @@ export default class UserAPI extends BaseAPI<User, UserServiceType> {
191
193
  },
192
194
  );
193
195
 
196
+ /*
197
+ * How one user can sign in, for Admin Dashboard > User > Authentication.
198
+ *
199
+ * A dedicated endpoint rather than extra columns on the CRUD read, because
200
+ * the interesting fact -- "does this account have a password at all?" --
201
+ * cannot be answered from the CRUD API without shipping the password
202
+ * column itself. A master admin bypasses column read permissions, so
203
+ * selecting `password` in the browser would put every user's scrypt digest
204
+ * in a page's network tab. The booleans below are derived server-side and
205
+ * nothing secret crosses the wire.
206
+ */
207
+ this.router.get(
208
+ `${new this.entityType().getCrudApiPath()?.toString()}/:userId/authentication-status`,
209
+ MasterAdminAuthorization.isAuthorizedMasterAdminMiddleware,
210
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
211
+ try {
212
+ const userId: ObjectID = UserAPI.getUserIdFromParams(req);
213
+
214
+ const status: UserAuthenticationStatus =
215
+ await UserService.getAuthenticationStatus(userId);
216
+
217
+ /*
218
+ * Whether an account has a password is exactly the sort of answer a
219
+ * shared cache must not keep -- and it changes the moment either
220
+ * action below is used.
221
+ */
222
+ Response.setNoCacheHeaders(res);
223
+
224
+ return Response.sendJsonObjectResponse(
225
+ req,
226
+ res,
227
+ status as unknown as JSONObject,
228
+ );
229
+ } catch (err) {
230
+ return next(err);
231
+ }
232
+ },
233
+ );
234
+
235
+ /*
236
+ * Set a user's password on their behalf.
237
+ *
238
+ * Master-admin only, and deliberately its own route rather than a PUT to
239
+ * /user/:id with a password in it. That generic write would work -- a
240
+ * master admin bypasses the password column's `update: [CurrentUser]` ACL
241
+ * -- but nothing about the URL would say so, the password policy could not
242
+ * be enforced, and the payload would have to be a hand-serialized
243
+ * HashedString. Here the gate is a middleware anyone can grep for, and the
244
+ * body is a plain string.
245
+ *
246
+ * Session revocation and the "Password Changed." email happen in
247
+ * UserService's update hook, not here, so they cannot be forgotten by a
248
+ * caller and cannot fire twice.
249
+ */
250
+ this.router.post(
251
+ `${new this.entityType().getCrudApiPath()?.toString()}/:userId/set-password`,
252
+ MasterAdminAuthorization.isAuthorizedMasterAdminMiddleware,
253
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
254
+ try {
255
+ const userId: ObjectID = UserAPI.getUserIdFromParams(req);
256
+
257
+ const password: unknown = req.body?.["password"];
258
+
259
+ /*
260
+ * Type-checked rather than cast. `as string` on a JSON body is a
261
+ * lie the moment somebody posts {"password": {...}} or a number, and
262
+ * the value flows into the hasher.
263
+ */
264
+ if (typeof password !== "string") {
265
+ throw new BadDataException("Password is required");
266
+ }
267
+
268
+ await UserService.setPassword({
269
+ userId: userId,
270
+ password: password,
271
+ });
272
+
273
+ return Response.sendEmptySuccessResponse(req, res);
274
+ } catch (err) {
275
+ return next(err);
276
+ }
277
+ },
278
+ );
279
+
280
+ /*
281
+ * Email the user a link that lets them choose their own password.
282
+ *
283
+ * The counterpart to setting one for them: it never puts the operator in
284
+ * possession of the user's credentials, which is the better default when
285
+ * the point is simply to get somebody back into a locked-out account. The
286
+ * link is the same one /forgot-password sends, redeemed by the same page.
287
+ */
288
+ this.router.post(
289
+ `${new this.entityType().getCrudApiPath()?.toString()}/:userId/send-password-reset-link`,
290
+ MasterAdminAuthorization.isAuthorizedMasterAdminMiddleware,
291
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
292
+ try {
293
+ const userId: ObjectID = UserAPI.getUserIdFromParams(req);
294
+
295
+ const email: Email = await UserService.sendPasswordResetLink({
296
+ userId: userId,
297
+ });
298
+
299
+ /*
300
+ * Echoed back so the page can say where the link went. The caller is
301
+ * a master admin who can already read this user's email through the
302
+ * CRUD API, so this discloses nothing new.
303
+ */
304
+ return Response.sendJsonObjectResponse(req, res, {
305
+ email: email.toString(),
306
+ });
307
+ } catch (err) {
308
+ return next(err);
309
+ }
310
+ },
311
+ );
312
+
194
313
  this.router.get(
195
314
  `${new this.entityType().getCrudApiPath()?.toString()}/profile-picture/:userId`,
196
315
  async (req: ExpressRequest, res: ExpressResponse) => {
@@ -23,6 +23,52 @@ const hostProtocol: string = ClickHouseIsHostHttps ? "https" : "http";
23
23
  const clickhouseHost: Hostname = ClickhouseHost || new Hostname("clickhouse");
24
24
  const clickhousePort: string = (ClickhousePort || 8123).toString();
25
25
 
26
+ /*
27
+ * How long the client keeps an idle pooled HTTP socket alive before
28
+ * destroying it (keep_alive.idle_socket_ttl). @clickhouse/client enables
29
+ * keep-alive by default but expires idle sockets after only 2500ms, while
30
+ * the telemetry fan-in writer's flush window (TELEMETRY_FANIN_MAX_WAIT_MS,
31
+ * see TelemetryFanInWriter.ts) defaults to 5000ms — so under sub-saturation
32
+ * ingest load every pooled socket was destroyed between flushes and every
33
+ * flush paid TCP (+TLS) connection setup again. The default here is bounded
34
+ * on both sides:
35
+ *
36
+ * - ABOVE the 5000ms fan-in flush window, so the socket a flush opened is
37
+ * still alive when the next flush fires and gets reused instead of
38
+ * being re-established;
39
+ * - BELOW the ClickHouse server's keep_alive_timeout of 10s (the bundled
40
+ * Clickhouse/config.xml pins <keep_alive_timeout>10</keep_alive_timeout>,
41
+ * which is also the server default since 23.11), so the CLIENT always
42
+ * retires an idle socket before the SERVER does. Operators who lower
43
+ * the server's keep_alive_timeout below this TTL must lower
44
+ * CLICKHOUSE_KEEP_ALIVE_IDLE_SOCKET_TTL_MS along with it (keeping it a
45
+ * fair bit under the server value) — otherwise the client reuses
46
+ * sockets the server has already closed and requests fail with
47
+ * ECONNRESET.
48
+ *
49
+ * The value must be a positive number of milliseconds; unset, non-numeric,
50
+ * zero and negative values all fall back to the default. Zero is rejected
51
+ * deliberately: the client treats 0 as "disable idle-socket reaping
52
+ * entirely", which reintroduces the server-closes-first ECONNRESET failure
53
+ * mode this TTL exists to prevent.
54
+ */
55
+ const DEFAULT_KEEP_ALIVE_IDLE_SOCKET_TTL_MS: number = 8000;
56
+
57
+ const keepAliveIdleSocketTtlRawValue: string = (
58
+ process.env["CLICKHOUSE_KEEP_ALIVE_IDLE_SOCKET_TTL_MS"] || ""
59
+ ).trim();
60
+
61
+ const keepAliveIdleSocketTtlParsedValue: number = parseInt(
62
+ keepAliveIdleSocketTtlRawValue,
63
+ 10,
64
+ );
65
+
66
+ const keepAliveIdleSocketTtlInMs: number =
67
+ Number.isFinite(keepAliveIdleSocketTtlParsedValue) &&
68
+ keepAliveIdleSocketTtlParsedValue > 0
69
+ ? keepAliveIdleSocketTtlParsedValue
70
+ : DEFAULT_KEEP_ALIVE_IDLE_SOCKET_TTL_MS;
71
+
26
72
  const options: ClickHouseClientConfigOptions = {
27
73
  url: `${hostProtocol}://${clickhouseHost.toString()}:${clickhousePort}`,
28
74
  username: ClickhouseUsername,
@@ -72,6 +118,19 @@ const options: ClickHouseClientConfigOptions = {
72
118
  request: true,
73
119
  response: true,
74
120
  },
121
+ /*
122
+ * Reuse pooled sockets across fan-in flush windows — see the note on
123
+ * keepAliveIdleSocketTtlInMs above for both bounds on the TTL and the
124
+ * operator warning about the server's keep_alive_timeout. `enabled: true`
125
+ * restates the client default explicitly so the pairing with
126
+ * idle_socket_ttl is visible here rather than implied. This lives on the
127
+ * shared `options` object, so every pool derived from it (query, ingest,
128
+ * migration, test) gets the same keep-alive behavior.
129
+ */
130
+ keep_alive: {
131
+ enabled: true,
132
+ idle_socket_ttl: keepAliveIdleSocketTtlInMs,
133
+ },
75
134
  };
76
135
 
77
136
  if (ShouldClickhouseSslEnable && ClickhouseTlsCa) {
@@ -0,0 +1,39 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class AddDataSourceTable1786303472848 implements MigrationInterface {
4
+ public name: string = "AddDataSourceTable1786303472848";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `CREATE TABLE "DataSource" ("_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, "name" character varying(100) NOT NULL, "slug" character varying(100) NOT NULL, "description" character varying(500), "dataSourceType" character varying(100) NOT NULL, "url" character varying, "databaseHost" character varying(100), "databasePort" integer, "databaseName" character varying(100), "username" character varying(100), "password" text, "apiToken" text, "customHeaders" jsonb, "additionalOptions" jsonb, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_49141becafea4a0574d9b5219ca" PRIMARY KEY ("_id"))`,
9
+ );
10
+ await queryRunner.query(
11
+ `CREATE INDEX "IDX_0e559ea9d7fbc66d014a29c380" ON "DataSource" ("projectId") `,
12
+ );
13
+ await queryRunner.query(
14
+ `ALTER TABLE "DataSource" ADD CONSTRAINT "FK_0e559ea9d7fbc66d014a29c3804" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
15
+ );
16
+ await queryRunner.query(
17
+ `ALTER TABLE "DataSource" ADD CONSTRAINT "FK_38843f53e5ca0ce0bf4de525d6f" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
18
+ );
19
+ await queryRunner.query(
20
+ `ALTER TABLE "DataSource" ADD CONSTRAINT "FK_29f0d663494b52c4ed2c0cc8e88" FOREIGN KEY ("deletedByUserId") 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 "DataSource" DROP CONSTRAINT "FK_29f0d663494b52c4ed2c0cc8e88"`,
27
+ );
28
+ await queryRunner.query(
29
+ `ALTER TABLE "DataSource" DROP CONSTRAINT "FK_38843f53e5ca0ce0bf4de525d6f"`,
30
+ );
31
+ await queryRunner.query(
32
+ `ALTER TABLE "DataSource" DROP CONSTRAINT "FK_0e559ea9d7fbc66d014a29c3804"`,
33
+ );
34
+ await queryRunner.query(
35
+ `DROP INDEX "public"."IDX_0e559ea9d7fbc66d014a29c380"`,
36
+ );
37
+ await queryRunner.query(`DROP TABLE "DataSource"`);
38
+ }
39
+ }
@@ -0,0 +1,24 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ /*
4
+ * Generated with `npm run generate-postgres-migration` after adding
5
+ * AIRun.analysisTldr — the AI-written one or two sentence summary of a
6
+ * completed investigation's posted report. Nullable: legacy runs, runs that
7
+ * published no report, and runs whose bounded TL;DR call failed simply have
8
+ * none, and the panel omits the TL;DR block for them.
9
+ */
10
+ export class AddInvestigationAnalysisTldr1786600000000
11
+ implements MigrationInterface
12
+ {
13
+ public name = "AddInvestigationAnalysisTldr1786600000000";
14
+
15
+ public async up(queryRunner: QueryRunner): Promise<void> {
16
+ await queryRunner.query(
17
+ `ALTER TABLE "AIRun" ADD "analysisTldr" character varying(500)`,
18
+ );
19
+ }
20
+
21
+ public async down(queryRunner: QueryRunner): Promise<void> {
22
+ await queryRunner.query(`ALTER TABLE "AIRun" DROP COLUMN "analysisTldr"`);
23
+ }
24
+ }
@@ -0,0 +1,76 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ /*
4
+ * Drops the global UNIQUE constraints on ProjectCallSMSConfig's Twilio
5
+ * credentials. Generated with `npm run generate-postgres-migration` after
6
+ * flipping both columns to `unique: false`; the statements are the generator's,
7
+ * renumbered to sort last and given IF EXISTS (see below).
8
+ *
9
+ * WHY THEY WERE WRONG
10
+ *
11
+ * ProjectCallSMSConfig is tenant-scoped (@TenantColumn("projectId")) and
12
+ * inherently multi-row: a project has as many configs as it has Twilio
13
+ * setups. The constraints came from the InitialMigration, where this table's
14
+ * columns were modelled on GlobalConfig — a singleton table whose every column
15
+ * carries a pointless `unique: true`. On a singleton that is harmless. Here it
16
+ * meant no two rows anywhere in the instance could share a Twilio account.
17
+ *
18
+ * That is not a constraint anybody wants:
19
+ *
20
+ * - One Twilio account, two numbers. Poland (and several other countries)
21
+ * requires a Local number for Voice and a Mobile number for SMS, so a
22
+ * single project legitimately needs two configs on one account. This is
23
+ * what issue #3020 was reported against.
24
+ * - Two projects, one account. On a shared instance the FIRST project to
25
+ * save a given account SID locked every other project out of it, across
26
+ * the tenant boundary — one tenant could deny another the use of its own
27
+ * Twilio credentials, and neither could see why.
28
+ *
29
+ * Both surfaced the same way: Postgres raised unique_violation (23505),
30
+ * which is not a OneUptime Exception, so it fell through to the generic
31
+ * handler and reached the client as a bare 500 `{"error":"Server Error"}`
32
+ * with nothing to act on.
33
+ *
34
+ * NOT REPLACED WITH A NARROWER UNIQUE
35
+ *
36
+ * There is no uniqueness to restore at any scope. Reusing one account across
37
+ * configs is the supported case, not an accident to be guarded against. Config
38
+ * identity is `name`, which is already unique per project via
39
+ * @UniqueColumnBy("projectId"). After this migration ProjectCallSMSConfig has
40
+ * no UNIQUE constraint on any credential column, which matches every other
41
+ * tenant-scoped table: theirs are all on slugs, keys and tokens — identifiers
42
+ * that really are global.
43
+ *
44
+ * IF EXISTS
45
+ *
46
+ * Self-hosted operators hit by #3020 were told in the issue thread that the
47
+ * workaround is to drop the constraint by hand. IF EXISTS keeps this migration
48
+ * from failing on those databases. down() cannot be made safe the same way: it
49
+ * will fail if duplicates exist by then, which is correct — silently
50
+ * hard-deleting a project's Twilio config to make room for a constraint would
51
+ * be worse than a failed rollback.
52
+ */
53
+ export class DropProjectCallSMSConfigCredentialUniques1786700000000
54
+ implements MigrationInterface
55
+ {
56
+ public name: string =
57
+ "DropProjectCallSMSConfigCredentialUniques1786700000000";
58
+
59
+ public async up(queryRunner: QueryRunner): Promise<void> {
60
+ await queryRunner.query(
61
+ `ALTER TABLE "ProjectCallSMSConfig" DROP CONSTRAINT IF EXISTS "UQ_0886139eac04ad49627e446d477"`,
62
+ );
63
+ await queryRunner.query(
64
+ `ALTER TABLE "ProjectCallSMSConfig" DROP CONSTRAINT IF EXISTS "UQ_2eb1a240d549a7701b6e82d2f94"`,
65
+ );
66
+ }
67
+
68
+ public async down(queryRunner: QueryRunner): Promise<void> {
69
+ await queryRunner.query(
70
+ `ALTER TABLE "ProjectCallSMSConfig" ADD CONSTRAINT "UQ_2eb1a240d549a7701b6e82d2f94" UNIQUE ("twilioAuthToken")`,
71
+ );
72
+ await queryRunner.query(
73
+ `ALTER TABLE "ProjectCallSMSConfig" ADD CONSTRAINT "UQ_0886139eac04ad49627e446d477" UNIQUE ("twilioAccountSID")`,
74
+ );
75
+ }
76
+ }
@@ -509,6 +509,9 @@ import { RestoreDroppedUniqueIndexes1786200000000 } from "./1786200000000-Restor
509
509
  import { QuarantineUnboundGitHubInstallations1786300000000 } from "./1786300000000-QuarantineUnboundGitHubInstallations";
510
510
  import { AddMasterPasswordSalt1786400000000 } from "./1786400000000-AddMasterPasswordSalt";
511
511
  import { AddInvestigationCodeFixRecommendation1786500000000 } from "./1786500000000-AddInvestigationCodeFixRecommendation";
512
+ import { AddInvestigationAnalysisTldr1786600000000 } from "./1786600000000-AddInvestigationAnalysisTldr";
513
+ import { DropProjectCallSMSConfigCredentialUniques1786700000000 } from "./1786700000000-DropProjectCallSMSConfigCredentialUniques";
514
+ import { AddDataSourceTable1786303472848 } from "./1786303472848-AddDataSourceTable";
512
515
 
513
516
  export default [
514
517
  InitialMigration,
@@ -1022,4 +1025,7 @@ export default [
1022
1025
  AddMasterPasswordSalt1786400000000,
1023
1026
  MigrationName1786105470826,
1024
1027
  AddInvestigationCodeFixRecommendation1786500000000,
1028
+ AddInvestigationAnalysisTldr1786600000000,
1029
+ DropProjectCallSMSConfigCredentialUniques1786700000000,
1030
+ AddDataSourceTable1786303472848,
1025
1031
  ];