@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
@@ -1,4 +1,6 @@
1
- import PostgresErrorTranslator from "../../../../Server/Utils/Database/PostgresErrorTranslator";
1
+ import PostgresErrorTranslator, {
2
+ TranslatedPostgresException,
3
+ } from "../../../../Server/Utils/Database/PostgresErrorTranslator";
2
4
  import BadDataException from "../../../../Types/Exception/BadDataException";
3
5
  import Exception from "../../../../Types/Exception/Exception";
4
6
  import { describe, expect, it } from "@jest/globals";
@@ -7,7 +9,9 @@ import { describe, expect, it } from "@jest/globals";
7
9
  * Contract under test: TypeORM's QueryFailedError is not an Exception, so it
8
10
  * used to fall through StartServer's generic handler and reach the client as a
9
11
  * bare 500 "Server Error" — which is exactly what deleting a project hit when
10
- * another project's MonitorStatusTimeline rows still referenced its statuses.
12
+ * another project's MonitorStatusTimeline rows still referenced its statuses,
13
+ * and what issue #3020 hit when a second ProjectCallSMSConfig was given Twilio
14
+ * credentials another row already held.
11
15
  *
12
16
  * The translator turns the actionable Postgres failures into a
13
17
  * BadDataException (400) and leaves everything else untouched.
@@ -33,6 +37,22 @@ const foreignKeyDeleteError: () => FakeQueryFailedError =
33
37
  };
34
38
  };
35
39
 
40
+ /*
41
+ * The literal failure from issue #3020: PUT /api/call-sms-config setting a
42
+ * Twilio account SID that another ProjectCallSMSConfig row already carried.
43
+ */
44
+ const twilioAccountSidCollision: () => FakeQueryFailedError =
45
+ (): FakeQueryFailedError => {
46
+ return {
47
+ message:
48
+ 'duplicate key value violates unique constraint "UQ_0886139eac04ad49627e446d477"',
49
+ code: "23505",
50
+ table: "ProjectCallSMSConfig",
51
+ detail:
52
+ 'Key ("twilioAccountSID")=(AC-redacted-sid-that-must-not-leak) already exists.',
53
+ };
54
+ };
55
+
36
56
  describe("PostgresErrorTranslator", () => {
37
57
  describe("foreign key violation on delete", () => {
38
58
  it("translates to a BadDataException naming the blocking table", () => {
@@ -86,17 +106,218 @@ describe("PostgresErrorTranslator", () => {
86
106
  });
87
107
  });
88
108
 
89
- describe("errors it should not touch", () => {
90
- it("passes through a non-foreign-key Postgres error unchanged", () => {
91
- const uniqueViolation: FakeQueryFailedError = {
109
+ describe("unique violation (issue #3020)", () => {
110
+ it("translates to a BadDataException naming the table and the column", () => {
111
+ const translated: unknown = PostgresErrorTranslator.translate(
112
+ twilioAccountSidCollision(),
113
+ );
114
+
115
+ expect(translated).toBeInstanceOf(BadDataException);
116
+ expect((translated as Exception).message).toBe(
117
+ "A Project Call SMS Config with this Twilio Account SID already exists. Please use a different value and try again.",
118
+ );
119
+ });
120
+
121
+ it("is a 400, not the bare 500 the issue reported", () => {
122
+ /*
123
+ * The whole point: the reporter saw `{"error":"Server Error"}` with no
124
+ * indication of which field was at fault.
125
+ */
126
+ const translated: unknown = PostgresErrorTranslator.translate(
127
+ twilioAccountSidCollision(),
128
+ );
129
+
130
+ expect((translated as Exception).message).not.toBe("Server Error");
131
+ expect(translated).toBeInstanceOf(BadDataException);
132
+ });
133
+
134
+ it("does not leak the colliding value — it may belong to another project", () => {
135
+ const translated: unknown = PostgresErrorTranslator.translate(
136
+ twilioAccountSidCollision(),
137
+ );
138
+
139
+ expect((translated as Exception).message).not.toContain(
140
+ "AC-redacted-sid-that-must-not-leak",
141
+ );
142
+ });
143
+
144
+ it("handles an unquoted column name", () => {
145
+ const translated: unknown = PostgresErrorTranslator.translate({
92
146
  message: "duplicate key value violates unique constraint",
93
147
  code: "23505",
94
148
  table: "Project",
95
149
  detail: "Key (slug)=(acme) already exists.",
150
+ });
151
+
152
+ expect((translated as Exception).message).toBe(
153
+ "A Project with this Slug already exists. Please use a different value and try again.",
154
+ );
155
+ });
156
+
157
+ it("handles a composite key, listing every column", () => {
158
+ const translated: unknown = PostgresErrorTranslator.translate({
159
+ message: "duplicate key value violates unique constraint",
160
+ code: "23505",
161
+ table: "NetworkInterface",
162
+ detail:
163
+ 'Key ("networkDeviceId", "interfaceIndex")=(cfc2f04f-79cb-4344-8c54-dafe5e3a290c, 3) already exists.',
164
+ });
165
+
166
+ expect((translated as Exception).message).toBe(
167
+ "A Network Interface with the same Network Device Id, Interface Index already exists. Please use different values and try again.",
168
+ );
169
+ });
170
+
171
+ it("does not mistake the value list for the column list", () => {
172
+ /*
173
+ * `Key (a)=(b) already exists` has two parenthesised groups. Reading the
174
+ * wrong one would put another row's data in the message.
175
+ */
176
+ const translated: unknown = PostgresErrorTranslator.translate({
177
+ message: "duplicate key value violates unique constraint",
178
+ code: "23505",
179
+ table: "Project",
180
+ detail: "Key (slug)=(secret-customer-name) already exists.",
181
+ });
182
+
183
+ expect((translated as Exception).message).not.toContain(
184
+ "secret-customer-name",
185
+ );
186
+ });
187
+
188
+ it("reads the pg fields off driverError when the wrapper has no code", () => {
189
+ const translated: unknown = PostgresErrorTranslator.translate({
190
+ message: "wrapped",
191
+ driverError: twilioAccountSidCollision(),
192
+ });
193
+
194
+ expect(translated).toBeInstanceOf(BadDataException);
195
+ expect((translated as Exception).message).toContain("Twilio Account SID");
196
+ });
197
+
198
+ it("falls back to a generic message when the table is unknown", () => {
199
+ const translated: unknown = PostgresErrorTranslator.translate({
200
+ message: "duplicate key value violates unique constraint",
201
+ code: "23505",
202
+ detail: 'Key ("twilioAccountSID")=(AC123) already exists.',
203
+ });
204
+
205
+ expect((translated as Exception).message).toBe(
206
+ "A record with this Twilio Account SID already exists. Please use a different value and try again.",
207
+ );
208
+ });
209
+
210
+ it("falls back to a generic message when the columns cannot be parsed", () => {
211
+ const translated: unknown = PostgresErrorTranslator.translate({
212
+ message: "duplicate key value violates unique constraint",
213
+ code: "23505",
214
+ table: "Project",
215
+ detail: "some shape of detail we have not seen already exists.",
216
+ });
217
+
218
+ expect(translated).toBeInstanceOf(BadDataException);
219
+ expect((translated as Exception).message).toBe(
220
+ "A Project with these values already exists. Please use different values and try again.",
221
+ );
222
+ });
223
+
224
+ it("passes through a 23505 with no detail at all", () => {
225
+ /*
226
+ * Without DETAIL there is nothing actionable to say, so a bare 500 is
227
+ * still more honest than inventing a field name.
228
+ */
229
+ const noDetail: FakeQueryFailedError = {
230
+ message: "duplicate key value violates unique constraint",
231
+ code: "23505",
232
+ table: "Project",
233
+ };
234
+
235
+ expect(PostgresErrorTranslator.translate(noDetail)).toBe(noDetail);
236
+ });
237
+ });
238
+
239
+ describe("isUniqueViolation", () => {
240
+ it("recognises a raw QueryFailedError", () => {
241
+ expect(
242
+ PostgresErrorTranslator.isUniqueViolation(twilioAccountSidCollision()),
243
+ ).toBe(true);
244
+ });
245
+
246
+ it("recognises one wrapped under driverError", () => {
247
+ expect(
248
+ PostgresErrorTranslator.isUniqueViolation({
249
+ message: "wrapped",
250
+ driverError: twilioAccountSidCollision(),
251
+ }),
252
+ ).toBe(true);
253
+ });
254
+
255
+ it("still recognises it AFTER translation", () => {
256
+ /*
257
+ * The reason this method exists. DatabaseService.create runs every
258
+ * failure through the translator before rethrowing, so a service's own
259
+ * catch block never sees the raw error. RumSessionPinService recovers
260
+ * from a duplicate pin by returning the existing row; a local
261
+ * `code === "23505"` check there would have started silently returning
262
+ * false the moment 23505 became translatable, turning an idempotent
263
+ * "already pinned" back into an error.
264
+ */
265
+ const translated: unknown = PostgresErrorTranslator.translate(
266
+ twilioAccountSidCollision(),
267
+ );
268
+
269
+ expect(translated).toBeInstanceOf(BadDataException);
270
+ expect(PostgresErrorTranslator.isUniqueViolation(translated)).toBe(true);
271
+ });
272
+
273
+ it("records the SQLSTATE on the translated exception", () => {
274
+ const translated: TranslatedPostgresException =
275
+ PostgresErrorTranslator.translate(
276
+ twilioAccountSidCollision(),
277
+ ) as TranslatedPostgresException;
278
+
279
+ expect(translated.postgresErrorCode).toBe("23505");
280
+ });
281
+
282
+ it("does not confuse a foreign key violation for a unique one", () => {
283
+ const translated: unknown = PostgresErrorTranslator.translate(
284
+ foreignKeyDeleteError(),
285
+ );
286
+
287
+ expect(PostgresErrorTranslator.isUniqueViolation(translated)).toBe(false);
288
+ expect(
289
+ PostgresErrorTranslator.isUniqueViolation(foreignKeyDeleteError()),
290
+ ).toBe(false);
291
+ });
292
+
293
+ it("does not confuse Exception.code for a SQLSTATE", () => {
294
+ /*
295
+ * Exception.code is the numeric ExceptionCode, an entirely different
296
+ * namespace from Postgres SQLSTATEs.
297
+ */
298
+ expect(
299
+ PostgresErrorTranslator.isUniqueViolation(new BadDataException("Nope")),
300
+ ).toBe(false);
301
+ });
302
+
303
+ it("is false for null and non-objects", () => {
304
+ expect(PostgresErrorTranslator.isUniqueViolation(null)).toBe(false);
305
+ expect(PostgresErrorTranslator.isUniqueViolation(undefined)).toBe(false);
306
+ expect(PostgresErrorTranslator.isUniqueViolation("23505")).toBe(false);
307
+ });
308
+ });
309
+
310
+ describe("errors it should not touch", () => {
311
+ it("passes through an unrecognised Postgres error unchanged", () => {
312
+ const notNullViolation: FakeQueryFailedError = {
313
+ message: 'null value in column "name" violates not-null constraint',
314
+ code: "23502",
315
+ table: "Project",
316
+ detail: "Failing row contains (null).",
96
317
  };
97
318
 
98
- expect(PostgresErrorTranslator.translate(uniqueViolation)).toBe(
99
- uniqueViolation,
319
+ expect(PostgresErrorTranslator.translate(notNullViolation)).toBe(
320
+ notNullViolation,
100
321
  );
101
322
  });
102
323
 
@@ -0,0 +1,292 @@
1
+ import InProcessMemo from "../../../Server/Utils/InProcessMemo";
2
+ import { describe, expect, jest, test, afterEach } from "@jest/globals";
3
+
4
+ /*
5
+ * InProcessMemo is the L1 layer the telemetry ingest hot path now leans on
6
+ * in four places (autoDiscover entity ids, the maintenance-fence refusal
7
+ * memo, host resolution, resource retention). Its contract is small but
8
+ * every clause is load-bearing:
9
+ *
10
+ * - a hit must be free and a miss must be honest (expired == absent),
11
+ * - the map must stay bounded no matter what keys collectors invent,
12
+ * because the keys come from collector-controlled resource attributes,
13
+ * - eviction must be oldest-first so a hot steady-state working set is
14
+ * not evicted by one burst of novel keys, and
15
+ * - the clock must be steerable so the suites for the callers above can
16
+ * prove their TTL behaviour without sleeping.
17
+ *
18
+ * A fixed injected clock is used for determinism everywhere except the
19
+ * lazy-Date.now test, which pins the property the module-level memos in
20
+ * production depend on: a jest Date.now spy installed AFTER construction
21
+ * must still steer the default clock.
22
+ */
23
+
24
+ type Clock = { nowMs: number; now: () => number };
25
+
26
+ function makeClock(startMs: number = 1_000_000): Clock {
27
+ const clock: Clock = {
28
+ nowMs: startMs,
29
+ now: (): number => {
30
+ return clock.nowMs;
31
+ },
32
+ };
33
+ return clock;
34
+ }
35
+
36
+ describe("InProcessMemo", () => {
37
+ afterEach(() => {
38
+ jest.restoreAllMocks();
39
+ });
40
+
41
+ describe("get / set", () => {
42
+ test("returns what was stored, within the TTL", () => {
43
+ const clock: Clock = makeClock();
44
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
45
+ ttlInMs: 1000,
46
+ now: clock.now,
47
+ });
48
+
49
+ memo.set("k", "v");
50
+
51
+ expect(memo.get("k")).toBe("v");
52
+ });
53
+
54
+ test("misses on a key never stored", () => {
55
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
56
+ ttlInMs: 1000,
57
+ });
58
+
59
+ expect(memo.get("absent")).toBeUndefined();
60
+ });
61
+
62
+ test("stores falsy-but-present values distinguishably from a miss", () => {
63
+ /*
64
+ * The fence memo stores booleans and the empty string is a legal
65
+ * cached value in principle — `undefined` alone must mean "miss".
66
+ */
67
+ const memo: InProcessMemo<string | boolean> = new InProcessMemo<
68
+ string | boolean
69
+ >({ ttlInMs: 1000 });
70
+
71
+ memo.set("empty", "");
72
+ memo.set("false", false);
73
+
74
+ expect(memo.get("empty")).toBe("");
75
+ expect(memo.get("false")).toBe(false);
76
+ });
77
+
78
+ test("a later set overwrites an earlier one", () => {
79
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
80
+ ttlInMs: 1000,
81
+ });
82
+
83
+ memo.set("k", "v1");
84
+ memo.set("k", "v2");
85
+
86
+ expect(memo.get("k")).toBe("v2");
87
+ });
88
+
89
+ test("keys are independent", () => {
90
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
91
+ ttlInMs: 1000,
92
+ });
93
+
94
+ memo.set("a", "va");
95
+ memo.set("b", "vb");
96
+
97
+ expect(memo.get("a")).toBe("va");
98
+ expect(memo.get("b")).toBe("vb");
99
+ });
100
+ });
101
+
102
+ describe("TTL", () => {
103
+ test("expires exactly at the boundary — an entry at its expiry instant is a miss", () => {
104
+ const clock: Clock = makeClock();
105
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
106
+ ttlInMs: 1000,
107
+ now: clock.now,
108
+ });
109
+
110
+ memo.set("k", "v");
111
+
112
+ clock.nowMs += 999;
113
+ expect(memo.get("k")).toBe("v");
114
+
115
+ clock.nowMs += 1;
116
+ expect(memo.get("k")).toBeUndefined();
117
+ });
118
+
119
+ test("an expired entry is deleted on read, freeing its slot", () => {
120
+ const clock: Clock = makeClock();
121
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
122
+ ttlInMs: 1000,
123
+ now: clock.now,
124
+ });
125
+
126
+ memo.set("k", "v");
127
+ clock.nowMs += 2000;
128
+
129
+ expect(memo.get("k")).toBeUndefined();
130
+ expect(memo.size()).toBe(0);
131
+ });
132
+
133
+ test("re-setting a key restarts its TTL", () => {
134
+ const clock: Clock = makeClock();
135
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
136
+ ttlInMs: 1000,
137
+ now: clock.now,
138
+ });
139
+
140
+ memo.set("k", "v1");
141
+ clock.nowMs += 900;
142
+ memo.set("k", "v2");
143
+ clock.nowMs += 900;
144
+
145
+ // 1800ms after the first set, but only 900ms after the second.
146
+ expect(memo.get("k")).toBe("v2");
147
+ });
148
+
149
+ test("a per-set TTL override wins over the instance TTL", () => {
150
+ /*
151
+ * ResourceHeartbeat caps each entry at that caller's own liveness
152
+ * window, which can be shorter than the memo's 60s default.
153
+ */
154
+ const clock: Clock = makeClock();
155
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
156
+ ttlInMs: 60_000,
157
+ now: clock.now,
158
+ });
159
+
160
+ memo.set("short", "v", 1000);
161
+ memo.set("default", "v");
162
+
163
+ clock.nowMs += 1001;
164
+
165
+ expect(memo.get("short")).toBeUndefined();
166
+ expect(memo.get("default")).toBe("v");
167
+ });
168
+
169
+ test("the lazy default clock is steerable by a Date.now spy installed later", () => {
170
+ /*
171
+ * The production memos are constructed at module load, long before
172
+ * any test runs. If the constructor captured the Date.now REFERENCE,
173
+ * a later spy would be invisible and no caller suite could ever test
174
+ * expiry. Pin the lazy read.
175
+ */
176
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
177
+ ttlInMs: 1000,
178
+ });
179
+
180
+ let nowMs: number = 5_000_000;
181
+ jest.spyOn(Date, "now").mockImplementation(() => {
182
+ return nowMs;
183
+ });
184
+
185
+ memo.set("k", "v");
186
+ nowMs += 1001;
187
+
188
+ expect(memo.get("k")).toBeUndefined();
189
+ });
190
+ });
191
+
192
+ describe("bounding", () => {
193
+ test("never grows past maxEntries under churn", () => {
194
+ const memo: InProcessMemo<number> = new InProcessMemo<number>({
195
+ ttlInMs: 60_000,
196
+ maxEntries: 5,
197
+ });
198
+
199
+ for (let i: number = 0; i < 500; i++) {
200
+ memo.set(`key-${i}`, i);
201
+ }
202
+
203
+ expect(memo.size()).toBeLessThanOrEqual(5);
204
+ });
205
+
206
+ test("evicts the oldest entry first", () => {
207
+ const memo: InProcessMemo<number> = new InProcessMemo<number>({
208
+ ttlInMs: 60_000,
209
+ maxEntries: 3,
210
+ });
211
+
212
+ memo.set("a", 1);
213
+ memo.set("b", 2);
214
+ memo.set("c", 3);
215
+ memo.set("d", 4);
216
+
217
+ expect(memo.get("a")).toBeUndefined();
218
+ expect(memo.get("b")).toBe(2);
219
+ expect(memo.get("c")).toBe(3);
220
+ expect(memo.get("d")).toBe(4);
221
+ });
222
+
223
+ test("re-setting an existing key refreshes its recency instead of evicting", () => {
224
+ const memo: InProcessMemo<number> = new InProcessMemo<number>({
225
+ ttlInMs: 60_000,
226
+ maxEntries: 3,
227
+ });
228
+
229
+ memo.set("a", 1);
230
+ memo.set("b", 2);
231
+ memo.set("c", 3);
232
+ // "a" becomes the youngest; "b" is now the oldest.
233
+ memo.set("a", 10);
234
+ memo.set("d", 4);
235
+
236
+ expect(memo.get("b")).toBeUndefined();
237
+ expect(memo.get("a")).toBe(10);
238
+ expect(memo.get("c")).toBe(3);
239
+ expect(memo.get("d")).toBe(4);
240
+ });
241
+
242
+ test("defaults the cap to 10k — the established ingest-path bound", () => {
243
+ const memo: InProcessMemo<number> = new InProcessMemo<number>({
244
+ ttlInMs: 60_000,
245
+ });
246
+
247
+ for (let i: number = 0; i < 10_500; i++) {
248
+ memo.set(`key-${i}`, i);
249
+ }
250
+
251
+ expect(memo.size()).toBeLessThanOrEqual(10_000);
252
+ });
253
+ });
254
+
255
+ describe("delete / clear", () => {
256
+ test("delete drops exactly one entry", () => {
257
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
258
+ ttlInMs: 60_000,
259
+ });
260
+
261
+ memo.set("a", "va");
262
+ memo.set("b", "vb");
263
+ memo.delete("a");
264
+
265
+ expect(memo.get("a")).toBeUndefined();
266
+ expect(memo.get("b")).toBe("vb");
267
+ });
268
+
269
+ test("delete of an absent key is a no-op", () => {
270
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
271
+ ttlInMs: 60_000,
272
+ });
273
+
274
+ expect(() => {
275
+ memo.delete("absent");
276
+ }).not.toThrow();
277
+ });
278
+
279
+ test("clear drops everything", () => {
280
+ const memo: InProcessMemo<string> = new InProcessMemo<string>({
281
+ ttlInMs: 60_000,
282
+ });
283
+
284
+ memo.set("a", "va");
285
+ memo.set("b", "vb");
286
+ memo.clear();
287
+
288
+ expect(memo.size()).toBe(0);
289
+ expect(memo.get("a")).toBeUndefined();
290
+ });
291
+ });
292
+ });