@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,686 @@
1
+ import Dashboard from "../../../Models/DatabaseModels/Dashboard";
2
+ import DashboardAPI from "../../../Server/API/DashboardAPI";
3
+ import DashboardService from "../../../Server/Services/DashboardService";
4
+ import {
5
+ ExpressRequest,
6
+ ExpressResponse,
7
+ NextFunction,
8
+ } from "../../../Server/Utils/Express";
9
+ import Response from "../../../Server/Utils/Response";
10
+ import DashboardComponentType, {
11
+ DataSourceComponentTypes,
12
+ } from "../../../Types/Dashboard/DashboardComponentType";
13
+ import DashboardViewConfig from "../../../Types/Dashboard/DashboardViewConfig";
14
+ import { JSONObject } from "../../../Types/JSON";
15
+ import ObjectID from "../../../Types/ObjectID";
16
+ import { mockRouter } from "./Helpers";
17
+ import {
18
+ afterEach,
19
+ beforeAll,
20
+ beforeEach,
21
+ describe,
22
+ expect,
23
+ it,
24
+ } from "@jest/globals";
25
+
26
+ jest.mock("../../../Server/Utils/Express", () => {
27
+ return {
28
+ getRouter: () => {
29
+ return mockRouter;
30
+ },
31
+ };
32
+ });
33
+
34
+ jest.mock("../../../Server/Utils/Response", () => {
35
+ return {
36
+ sendEntityArrayResponse: jest.fn().mockImplementation((...args: []) => {
37
+ return args;
38
+ }),
39
+ sendJsonObjectResponse: jest.fn().mockImplementation((...args: []) => {
40
+ return args;
41
+ }),
42
+ sendEmptySuccessResponse: jest.fn(),
43
+ sendEntityResponse: jest.fn().mockImplementation((...args: []) => {
44
+ return args;
45
+ }),
46
+ sendErrorResponse: jest.fn().mockImplementation((...args: []) => {
47
+ return args;
48
+ }),
49
+ };
50
+ });
51
+
52
+ /*
53
+ * PublicDashboardViewConfig.sanitize() strips the external Data Source
54
+ * widgets out of the dashboard config served to ANONYMOUS public-dashboard
55
+ * viewers, and it has thorough unit coverage of its own. What that unit
56
+ * coverage structurally cannot see is a PUBLIC ROUTE THAT FORGETS TO CALL IT
57
+ * — and the call sites are the whole of the protection.
58
+ *
59
+ * That is the leak these tests exist to prevent. A Data Source widget's
60
+ * stored config IS the query: raw SQL naming internal tables and columns,
61
+ * PromQL naming internal jobs and instances, plus the id of the connected
62
+ * Data Source. The client already refuses to render those widgets publicly
63
+ * (it draws a placeholder), so dropping them costs the viewer nothing; but
64
+ * a route that serves `dashboard.dashboardViewConfig` straight from the
65
+ * column publishes the query text to anyone who opens the page and reads
66
+ * the API response — no authentication, no master password, no trace.
67
+ *
68
+ * Two handlers in Common/Server/API/DashboardAPI.ts read the stored config
69
+ * for anonymous viewers, and both are covered here:
70
+ * - /overview/:dashboardIdOrDomain (POST and GET share one handler)
71
+ * - /view-config/:dashboardId
72
+ *
73
+ * The tests assert on the RESPONSE BODY rather than on the sanitizer being
74
+ * called, so they hold whichever way the strip is implemented, and they are
75
+ * driven off DataSourceComponentTypes so a fifth widget type added later is
76
+ * covered on both routes the day it is added.
77
+ */
78
+
79
+ const OVERVIEW_ROUTE: string = "/dashboard/overview/:dashboardIdOrDomain";
80
+
81
+ const VIEW_CONFIG_ROUTE: string = "/dashboard/view-config/:dashboardId";
82
+
83
+ /*
84
+ * Distinctive strings that only ever live inside a Data Source widget. Any
85
+ * one of them turning up in a public response body is the leak itself.
86
+ */
87
+ const CHART_QUERY_SECRET: string =
88
+ "SELECT token FROM internal_billing_accounts";
89
+
90
+ const TABLE_QUERY_SECRET: string =
91
+ "SELECT email, card_last4 FROM internal_customer_ledger";
92
+
93
+ const LEGEND_SECRET: string = "{{customer_email}}";
94
+
95
+ const DATA_SOURCE_ID_SECRET: string = "ds-internal-warehouse-9f21";
96
+
97
+ const DATA_SOURCE_TITLE_SECRET: string = "Internal billing revenue by tenant";
98
+
99
+ const DATA_SOURCE_SECRETS: Array<string> = [
100
+ CHART_QUERY_SECRET,
101
+ TABLE_QUERY_SECRET,
102
+ LEGEND_SECRET,
103
+ DATA_SOURCE_ID_SECRET,
104
+ DATA_SOURCE_TITLE_SECRET,
105
+ ];
106
+
107
+ // Everything an anonymous viewer is still supposed to receive.
108
+ const PUBLIC_CHART_TITLE: string = "Public CPU";
109
+
110
+ const PUBLIC_METRIC_NAME: string = "system.cpu.utilization";
111
+
112
+ const PUBLIC_TEXT: string = "Status of the public service";
113
+
114
+ type PublicConfigRoute = {
115
+ name: string;
116
+ method: string;
117
+ uri: string;
118
+ idParamName: string;
119
+ // Only the overview endpoint reshapes the config into widget summaries.
120
+ servesComponentSummaries: boolean;
121
+ };
122
+
123
+ const PUBLIC_CONFIG_ROUTES: Array<PublicConfigRoute> = [
124
+ {
125
+ name: "POST /dashboard/overview/:dashboardIdOrDomain",
126
+ method: "post",
127
+ uri: OVERVIEW_ROUTE,
128
+ idParamName: "dashboardIdOrDomain",
129
+ servesComponentSummaries: true,
130
+ },
131
+ {
132
+ name: "GET /dashboard/overview/:dashboardIdOrDomain",
133
+ method: "get",
134
+ uri: OVERVIEW_ROUTE,
135
+ idParamName: "dashboardIdOrDomain",
136
+ servesComponentSummaries: true,
137
+ },
138
+ {
139
+ name: "POST /dashboard/view-config/:dashboardId",
140
+ method: "post",
141
+ uri: VIEW_CONFIG_ROUTE,
142
+ idParamName: "dashboardId",
143
+ servesComponentSummaries: false,
144
+ },
145
+ ];
146
+
147
+ const OVERVIEW_ROUTES: Array<PublicConfigRoute> = PUBLIC_CONFIG_ROUTES.filter(
148
+ (route: PublicConfigRoute): boolean => {
149
+ return route.servesComponentSummaries;
150
+ },
151
+ );
152
+
153
+ type StripCase = {
154
+ routeName: string;
155
+ componentType: DashboardComponentType;
156
+ route: PublicConfigRoute;
157
+ };
158
+
159
+ /*
160
+ * One case per Data Source widget type, per public route. Driven off
161
+ * DataSourceComponentTypes rather than a hand-written list so a fifth type
162
+ * is exercised on every route from the moment it is added to the enum.
163
+ */
164
+ const STRIP_CASES: Array<StripCase> = PUBLIC_CONFIG_ROUTES.flatMap(
165
+ (route: PublicConfigRoute): Array<StripCase> => {
166
+ return DataSourceComponentTypes.map(
167
+ (componentType: DashboardComponentType): StripCase => {
168
+ return {
169
+ routeName: route.name,
170
+ componentType: componentType,
171
+ route: route,
172
+ };
173
+ },
174
+ );
175
+ },
176
+ );
177
+
178
+ describe("DashboardAPI public Data Source strip", () => {
179
+ let dashboardId: ObjectID;
180
+ let dashboard: Dashboard;
181
+ let mockResponse: ExpressResponse;
182
+ let nextFunction: NextFunction;
183
+
184
+ beforeAll(() => {
185
+ mockRouter.routes.length = 0;
186
+ new DashboardAPI();
187
+ });
188
+
189
+ type BuiltWidget = {
190
+ componentId: string;
191
+ widget: JSONObject;
192
+ };
193
+
194
+ type BuildWidgetFunction = (
195
+ componentType: DashboardComponentType,
196
+ argumentsObject?: JSONObject,
197
+ ) => BuiltWidget;
198
+
199
+ const buildWidget: BuildWidgetFunction = (
200
+ componentType: DashboardComponentType,
201
+ argumentsObject?: JSONObject,
202
+ ): BuiltWidget => {
203
+ const componentId: string = ObjectID.generate().toString();
204
+
205
+ return {
206
+ componentId: componentId,
207
+ widget: {
208
+ _type: "DashboardComponent",
209
+ componentId: componentId,
210
+ componentType: componentType,
211
+ topInDashboardUnits: 0,
212
+ leftInDashboardUnits: 0,
213
+ widthInDashboardUnits: 12,
214
+ heightInDashboardUnits: 6,
215
+ minWidthInDashboardUnits: 1,
216
+ minHeightInDashboardUnits: 1,
217
+ arguments: argumentsObject || {},
218
+ },
219
+ };
220
+ };
221
+
222
+ type SetDashboardWidgetsFunction = (widgets: Array<JSONObject>) => void;
223
+
224
+ const setDashboardWidgets: SetDashboardWidgetsFunction = (
225
+ widgets: Array<JSONObject>,
226
+ ): void => {
227
+ dashboard.dashboardViewConfig = {
228
+ _type: "DashboardViewConfig",
229
+ heightInDashboardUnits: 24,
230
+ components: widgets,
231
+ } as unknown as DashboardViewConfig;
232
+ };
233
+
234
+ type LeakyDashboard = {
235
+ publicComponentIds: Array<string>;
236
+ dataSourceComponentIds: Array<string>;
237
+ };
238
+
239
+ /*
240
+ * A realistic public dashboard: two widgets an anonymous viewer may keep
241
+ * seeing, interleaved with two Data Source widgets whose stored config
242
+ * carries the raw query text, the legend template, and the id of the
243
+ * connected Data Source.
244
+ */
245
+ type SetLeakyDashboardFunction = () => LeakyDashboard;
246
+
247
+ const setLeakyDashboard: SetLeakyDashboardFunction = (): LeakyDashboard => {
248
+ const metricChart: BuiltWidget = buildWidget(DashboardComponentType.Chart, {
249
+ chartTitle: PUBLIC_CHART_TITLE,
250
+ metricQueryConfigs: [
251
+ {
252
+ metricQueryData: {
253
+ filterData: { metricName: PUBLIC_METRIC_NAME },
254
+ },
255
+ },
256
+ ],
257
+ });
258
+
259
+ const text: BuiltWidget = buildWidget(DashboardComponentType.Text, {
260
+ text: PUBLIC_TEXT,
261
+ });
262
+
263
+ const dataSourceChart: BuiltWidget = buildWidget(
264
+ DashboardComponentType.DataSourceChart,
265
+ {
266
+ chartTitle: DATA_SOURCE_TITLE_SECRET,
267
+ queries: [
268
+ {
269
+ id: "query-1",
270
+ dataSourceId: DATA_SOURCE_ID_SECRET,
271
+ query: CHART_QUERY_SECRET,
272
+ legend: LEGEND_SECRET,
273
+ },
274
+ ],
275
+ },
276
+ );
277
+
278
+ const dataSourceTable: BuiltWidget = buildWidget(
279
+ DashboardComponentType.DataSourceTable,
280
+ {
281
+ maxRows: 25,
282
+ query: {
283
+ dataSourceId: DATA_SOURCE_ID_SECRET,
284
+ query: TABLE_QUERY_SECRET,
285
+ },
286
+ },
287
+ );
288
+
289
+ setDashboardWidgets([
290
+ metricChart.widget,
291
+ dataSourceChart.widget,
292
+ text.widget,
293
+ dataSourceTable.widget,
294
+ ]);
295
+
296
+ return {
297
+ publicComponentIds: [metricChart.componentId, text.componentId],
298
+ dataSourceComponentIds: [
299
+ dataSourceChart.componentId,
300
+ dataSourceTable.componentId,
301
+ ],
302
+ };
303
+ };
304
+
305
+ type CallRouteFunction = (route: PublicConfigRoute) => Promise<void>;
306
+
307
+ const callRoute: CallRouteFunction = async (
308
+ route: PublicConfigRoute,
309
+ ): Promise<void> => {
310
+ const request: ExpressRequest = {
311
+ params: {
312
+ [route.idParamName]: dashboardId.toString(),
313
+ },
314
+ body: {},
315
+ query: {},
316
+ cookies: {},
317
+ headers: {},
318
+ socket: {},
319
+ ips: [],
320
+ } as unknown as ExpressRequest;
321
+
322
+ await mockRouter
323
+ .match(route.method, route.uri)
324
+ .handlerFunction(request, mockResponse, nextFunction);
325
+ };
326
+
327
+ type GetResponseBodyFunction = () => JSONObject;
328
+
329
+ const getResponseBody: GetResponseBodyFunction = (): JSONObject => {
330
+ expect(nextFunction).not.toHaveBeenCalled();
331
+
332
+ const calls: Array<Array<unknown>> = (
333
+ Response.sendJsonObjectResponse as jest.Mock
334
+ ).mock.calls as Array<Array<unknown>>;
335
+
336
+ expect(calls.length).toBe(1);
337
+
338
+ return calls[0]![2] as JSONObject;
339
+ };
340
+
341
+ type GetServedComponentsFunction = (body: JSONObject) => Array<JSONObject>;
342
+
343
+ const getServedComponents: GetServedComponentsFunction = (
344
+ body: JSONObject,
345
+ ): Array<JSONObject> => {
346
+ const servedConfig: JSONObject | null = body[
347
+ "dashboardViewConfig"
348
+ ] as JSONObject | null;
349
+
350
+ expect(servedConfig).not.toBeNull();
351
+
352
+ return (servedConfig!["components"] || []) as unknown as Array<JSONObject>;
353
+ };
354
+
355
+ type ComponentIdsOfFunction = (
356
+ components: Array<JSONObject>,
357
+ ) => Array<string>;
358
+
359
+ const componentIdsOf: ComponentIdsOfFunction = (
360
+ components: Array<JSONObject>,
361
+ ): Array<string> => {
362
+ return components.map((component: JSONObject): string => {
363
+ return String(component["componentId"]);
364
+ });
365
+ };
366
+
367
+ type ComponentTypesOfFunction = (
368
+ components: Array<JSONObject>,
369
+ ) => Array<string>;
370
+
371
+ const componentTypesOf: ComponentTypesOfFunction = (
372
+ components: Array<JSONObject>,
373
+ ): Array<string> => {
374
+ return components.map((component: JSONObject): string => {
375
+ return String(component["componentType"]);
376
+ });
377
+ };
378
+
379
+ beforeEach(() => {
380
+ jest.clearAllMocks();
381
+
382
+ dashboardId = ObjectID.generate();
383
+
384
+ dashboard = new Dashboard();
385
+ dashboard.id = dashboardId;
386
+ dashboard.projectId = ObjectID.generate();
387
+ dashboard.isPublicDashboard = true;
388
+ dashboard.enableMasterPassword = false;
389
+ dashboard.name = "Public Dashboard";
390
+ setDashboardWidgets([]);
391
+
392
+ jest.spyOn(DashboardService, "findOneById").mockResolvedValue(dashboard);
393
+
394
+ /*
395
+ * PublicDashboardViewConfig.sanitize is deliberately NOT stubbed. The
396
+ * whole point of this file is that the routes CALL it — a stub would
397
+ * make every assertion below pass against a handler that forgot to.
398
+ */
399
+
400
+ mockResponse = {
401
+ cookie: jest.fn(),
402
+ send: jest.fn(),
403
+ json: jest.fn(),
404
+ status: jest.fn().mockReturnThis(),
405
+ } as unknown as ExpressResponse;
406
+
407
+ nextFunction = jest.fn();
408
+ });
409
+
410
+ afterEach(() => {
411
+ jest.restoreAllMocks();
412
+ });
413
+
414
+ describe("query text never reaches an anonymous viewer", () => {
415
+ it.each(PUBLIC_CONFIG_ROUTES)(
416
+ "$name serves the public widgets and none of the Data Source config",
417
+ async (route: PublicConfigRoute) => {
418
+ const built: LeakyDashboard = setLeakyDashboard();
419
+
420
+ /*
421
+ * Guard against a vacuous test: the STORED config really does carry
422
+ * every secret, so `not.toContain` below can only pass because the
423
+ * route stripped the widgets.
424
+ */
425
+ const storedConfig: string = JSON.stringify(
426
+ dashboard.dashboardViewConfig,
427
+ );
428
+
429
+ for (const secret of DATA_SOURCE_SECRETS) {
430
+ expect(storedConfig).toContain(secret);
431
+ }
432
+
433
+ await callRoute(route);
434
+
435
+ const body: JSONObject = getResponseBody();
436
+ const servedBody: string = JSON.stringify(body);
437
+
438
+ for (const secret of DATA_SOURCE_SECRETS) {
439
+ expect(servedBody).not.toContain(secret);
440
+ }
441
+
442
+ for (const componentId of built.dataSourceComponentIds) {
443
+ expect(servedBody).not.toContain(componentId);
444
+ }
445
+
446
+ // ...and the widgets a public viewer can render are untouched.
447
+ expect(componentIdsOf(getServedComponents(body))).toEqual(
448
+ built.publicComponentIds,
449
+ );
450
+ expect(componentTypesOf(getServedComponents(body))).toEqual([
451
+ DashboardComponentType.Chart,
452
+ DashboardComponentType.Text,
453
+ ]);
454
+ expect(servedBody).toContain(PUBLIC_CHART_TITLE);
455
+ expect(servedBody).toContain(PUBLIC_TEXT);
456
+ },
457
+ );
458
+
459
+ it.each(PUBLIC_CONFIG_ROUTES)(
460
+ "$name never serves the connected Data Source id, even with nothing to hide behind",
461
+ async (route: PublicConfigRoute) => {
462
+ /*
463
+ * dataSourceId is the one field a field-stripping (rather than
464
+ * widget-dropping) implementation is most likely to keep: it is not
465
+ * query text, it just points at the connected source. It still tells
466
+ * an anonymous viewer which internal Data Source records exist.
467
+ */
468
+ const dataSourceValue: BuiltWidget = buildWidget(
469
+ DashboardComponentType.DataSourceValue,
470
+ {
471
+ query: {
472
+ dataSourceId: DATA_SOURCE_ID_SECRET,
473
+ query: CHART_QUERY_SECRET,
474
+ },
475
+ },
476
+ );
477
+
478
+ setDashboardWidgets([dataSourceValue.widget]);
479
+
480
+ await callRoute(route);
481
+
482
+ const body: JSONObject = getResponseBody();
483
+
484
+ expect(JSON.stringify(body)).not.toContain(DATA_SOURCE_ID_SECRET);
485
+ expect(getServedComponents(body)).toEqual([]);
486
+ },
487
+ );
488
+
489
+ it.each(STRIP_CASES)(
490
+ "$routeName drops a $componentType widget and its stored query",
491
+ async (stripCase: StripCase) => {
492
+ const publicWidget: BuiltWidget = buildWidget(
493
+ DashboardComponentType.Value,
494
+ { title: PUBLIC_CHART_TITLE },
495
+ );
496
+
497
+ const querySecret: string = `SELECT secret FROM internal_${stripCase.componentType}_rows`;
498
+
499
+ /*
500
+ * Both persisted shapes at once: the chart widget stores an array of
501
+ * queries, the value/gauge/table widgets store a single one. A widget
502
+ * type added later gets whichever of the two it uses covered here.
503
+ */
504
+ const dataSourceWidget: BuiltWidget = buildWidget(
505
+ stripCase.componentType,
506
+ {
507
+ chartTitle: DATA_SOURCE_TITLE_SECRET,
508
+ query: {
509
+ dataSourceId: DATA_SOURCE_ID_SECRET,
510
+ query: querySecret,
511
+ },
512
+ queries: [
513
+ {
514
+ id: "query-1",
515
+ dataSourceId: DATA_SOURCE_ID_SECRET,
516
+ query: querySecret,
517
+ },
518
+ ],
519
+ },
520
+ );
521
+
522
+ setDashboardWidgets([publicWidget.widget, dataSourceWidget.widget]);
523
+
524
+ await callRoute(stripCase.route);
525
+
526
+ const body: JSONObject = getResponseBody();
527
+ const servedBody: string = JSON.stringify(body);
528
+
529
+ expect(servedBody).not.toContain(querySecret);
530
+ expect(servedBody).not.toContain(DATA_SOURCE_ID_SECRET);
531
+ expect(servedBody).not.toContain(DATA_SOURCE_TITLE_SECRET);
532
+ expect(servedBody).not.toContain(stripCase.componentType);
533
+ expect(componentIdsOf(getServedComponents(body))).toEqual([
534
+ publicWidget.componentId,
535
+ ]);
536
+ },
537
+ );
538
+ });
539
+
540
+ describe("the public routes agree with each other", () => {
541
+ it("serves the identical surviving widget set from every public route", async () => {
542
+ /*
543
+ * One stored config in, one set of widget ids out — whichever public
544
+ * route the viewer reaches for. A route that skipped the strip would
545
+ * show up here as a wider set than its siblings, even if the secrets
546
+ * themselves were renamed out from under the assertions above.
547
+ */
548
+ const built: LeakyDashboard = setLeakyDashboard();
549
+
550
+ type RouteResult = {
551
+ route: string;
552
+ componentIds: Array<string>;
553
+ };
554
+
555
+ const results: Array<RouteResult> = [];
556
+
557
+ for (const route of PUBLIC_CONFIG_ROUTES) {
558
+ jest.clearAllMocks();
559
+
560
+ await callRoute(route);
561
+
562
+ results.push({
563
+ route: route.name,
564
+ componentIds: componentIdsOf(getServedComponents(getResponseBody())),
565
+ });
566
+ }
567
+
568
+ expect(results).toEqual(
569
+ PUBLIC_CONFIG_ROUTES.map((route: PublicConfigRoute): RouteResult => {
570
+ return {
571
+ route: route.name,
572
+ componentIds: built.publicComponentIds,
573
+ };
574
+ }),
575
+ );
576
+ });
577
+
578
+ it("registers one shared handler for both overview methods", () => {
579
+ /*
580
+ * POST and GET are registered with the same handler function on
581
+ * purpose, so the strip can never drift between the two methods. If
582
+ * they are ever split into separate handlers, this fails and the
583
+ * per-method cases above become load-bearing rather than redundant.
584
+ */
585
+ expect(mockRouter.match("post", OVERVIEW_ROUTE).handlerFunction).toBe(
586
+ mockRouter.match("get", OVERVIEW_ROUTE).handlerFunction,
587
+ );
588
+ });
589
+ });
590
+
591
+ describe("overview summaries are built from the sanitized config", () => {
592
+ it.each(OVERVIEW_ROUTES)(
593
+ "$name summarises only the widgets that survived the strip",
594
+ async (route: PublicConfigRoute) => {
595
+ /*
596
+ * The overview endpoint does not only echo the config: it also
597
+ * reshapes it into `components` summaries and a `metricsUsed` list.
598
+ * Both must be derived from the SANITIZED config — a summary built
599
+ * from the stored column would republish the Data Source widget's
600
+ * title and every metric name buried in its query config.
601
+ */
602
+ setLeakyDashboard();
603
+
604
+ await callRoute(route);
605
+
606
+ const body: JSONObject = getResponseBody();
607
+ const summaries: Array<JSONObject> = body[
608
+ "components"
609
+ ] as unknown as Array<JSONObject>;
610
+
611
+ expect(componentTypesOf(summaries)).toEqual([
612
+ DashboardComponentType.Chart,
613
+ DashboardComponentType.Text,
614
+ ]);
615
+ expect(body["metricsUsed"]).toEqual([PUBLIC_METRIC_NAME]);
616
+ },
617
+ );
618
+ });
619
+
620
+ describe("an absent stored config stays null", () => {
621
+ it.each(PUBLIC_CONFIG_ROUTES)(
622
+ "$name serves dashboardViewConfig null rather than an empty object",
623
+ async (route: PublicConfigRoute) => {
624
+ /*
625
+ * Load-bearing for the public page, not just for tidiness.
626
+ * App/FeatureSet/PublicDashboard/src/Pages/DashboardView/DashboardViewPage.tsx
627
+ * does `response.data["dashboardViewConfig"] || createDefaultDashboardViewConfig()`.
628
+ * JSONFunctions.serialize(null) returns `{}`, which is truthy — it
629
+ * would sail past the fallback and the canvas would then read
630
+ * `.components.length` off undefined and throw.
631
+ */
632
+ const absentConfigs: Array<DashboardViewConfig | null | undefined> = [
633
+ null,
634
+ undefined,
635
+ ];
636
+
637
+ for (const absentConfig of absentConfigs) {
638
+ jest.clearAllMocks();
639
+
640
+ dashboard.dashboardViewConfig =
641
+ absentConfig as unknown as DashboardViewConfig;
642
+
643
+ await callRoute(route);
644
+
645
+ const body: JSONObject = getResponseBody();
646
+
647
+ expect(
648
+ Object.prototype.hasOwnProperty.call(body, "dashboardViewConfig"),
649
+ ).toBe(true);
650
+ expect(body["dashboardViewConfig"]).toBeNull();
651
+ expect(body["dashboardViewConfig"]).not.toEqual({});
652
+ }
653
+ },
654
+ );
655
+
656
+ it.each(PUBLIC_CONFIG_ROUTES)(
657
+ "$name serves an empty component list, not null, once a config exists",
658
+ async (route: PublicConfigRoute) => {
659
+ /*
660
+ * The opposite side of the same line: a dashboard whose only widget
661
+ * is a Data Source widget still HAS a stored config, so the viewer
662
+ * must get a real config with zero components — not the null that
663
+ * means "nothing was ever stored".
664
+ */
665
+ const dataSourceGauge: BuiltWidget = buildWidget(
666
+ DashboardComponentType.DataSourceGauge,
667
+ {
668
+ query: {
669
+ dataSourceId: DATA_SOURCE_ID_SECRET,
670
+ query: CHART_QUERY_SECRET,
671
+ },
672
+ },
673
+ );
674
+
675
+ setDashboardWidgets([dataSourceGauge.widget]);
676
+
677
+ await callRoute(route);
678
+
679
+ const body: JSONObject = getResponseBody();
680
+
681
+ expect(body["dashboardViewConfig"]).not.toBeNull();
682
+ expect(getServedComponents(body)).toEqual([]);
683
+ },
684
+ );
685
+ });
686
+ });