@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,521 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import {
5
+ VendorAssetsPath,
6
+ VendorAssetsRoute,
7
+ getMermaidDistPath,
8
+ } from "../../../Server/Utils/VendorAssets";
9
+
10
+ /*
11
+ * Every server-rendered page must be able to render with no route off the box.
12
+ *
13
+ * A CDN <script> in a view does not degrade on an air-gapped install; it
14
+ * blocks the parser until the connect times out, which is what
15
+ * https://github.com/OneUptime/oneuptime/issues/2570 reported as pages stuck
16
+ * on "Loading..." forever. One file added to a views directory with a
17
+ * copy-pasted CDN tag puts it back, and nothing else in the build would
18
+ * notice - so this scans the directories rather than the handful of files the
19
+ * fix happened to touch.
20
+ */
21
+
22
+ const REPOSITORY_ROOT: string = path.resolve(__dirname, "..", "..", "..", "..");
23
+
24
+ interface ViewFile {
25
+ /** Repo-relative, so a failure message names something greppable. */
26
+ name: string;
27
+ absolutePath: string;
28
+ contents: string;
29
+ }
30
+
31
+ interface ViewRoot {
32
+ label: string;
33
+ directories: Array<string>;
34
+ /*
35
+ * Hosts a view under this root may still reference. Anything not listed is
36
+ * a failure.
37
+ */
38
+ allowedHosts: Array<string>;
39
+ }
40
+
41
+ /*
42
+ * Prose explains these rules at length - including, in a couple of places, by
43
+ * naming the exact CDN host that is no longer allowed. Scanning the raw text
44
+ * would fail on the comment that documents the rule.
45
+ *
46
+ * Line comments are only stripped when they START a line: `//cdnjs.cloudflare.com`
47
+ * in an href is a protocol-relative URL, not a comment, and it is precisely
48
+ * the form this test has to keep catching.
49
+ */
50
+ const COMMENT_SYNTAXES: Array<RegExp> = [
51
+ /<!--[\s\S]*?-->/g,
52
+ /<%#[\s\S]*?%>/g,
53
+ /\/\*[\s\S]*?\*\//g,
54
+ /^[ \t]*\/\/.*$/gm,
55
+ ];
56
+
57
+ function stripComments(source: string): string {
58
+ /*
59
+ * Repeated until the text stops changing, rather than one pass per syntax.
60
+ * A single pass leaves the opener behind on overlapping comments
61
+ * ("<!--<!-- x -->" keeps a "<!--"), and removing a block comment can
62
+ * uncover a line comment that was inside it. Cheap here - these files are a
63
+ * few KB and it converges in two passes.
64
+ */
65
+ let previous: string = "";
66
+ let current: string = source;
67
+
68
+ while (current !== previous) {
69
+ previous = current;
70
+
71
+ for (const syntax of COMMENT_SYNTAXES) {
72
+ current = current.replace(syntax, "");
73
+ }
74
+ }
75
+
76
+ return current;
77
+ }
78
+
79
+ function collectViewFiles(directory: string): Array<ViewFile> {
80
+ if (!fs.existsSync(directory)) {
81
+ return [];
82
+ }
83
+
84
+ const files: Array<ViewFile> = [];
85
+
86
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
87
+ const absolutePath: string = path.join(directory, entry.name);
88
+
89
+ if (entry.isDirectory()) {
90
+ files.push(...collectViewFiles(absolutePath));
91
+ continue;
92
+ }
93
+
94
+ if (!entry.name.endsWith(".ejs")) {
95
+ continue;
96
+ }
97
+
98
+ files.push({
99
+ name: path.relative(REPOSITORY_ROOT, absolutePath),
100
+ absolutePath,
101
+ contents: stripComments(fs.readFileSync(absolutePath, "utf8")),
102
+ });
103
+ }
104
+
105
+ return files;
106
+ }
107
+
108
+ function featureSetViewDirectories(): Array<string> {
109
+ const featureSetRoot: string = path.join(
110
+ REPOSITORY_ROOT,
111
+ "App",
112
+ "FeatureSet",
113
+ );
114
+
115
+ if (!fs.existsSync(featureSetRoot)) {
116
+ return [];
117
+ }
118
+
119
+ const directories: Array<string> = [];
120
+
121
+ for (const featureSet of fs.readdirSync(featureSetRoot)) {
122
+ /* Docs and Identity capitalise it, the API reference does not. */
123
+ for (const viewsDirectory of ["Views", "views"]) {
124
+ const candidate: string = path.join(
125
+ featureSetRoot,
126
+ featureSet,
127
+ viewsDirectory,
128
+ );
129
+
130
+ if (fs.existsSync(candidate)) {
131
+ directories.push(candidate);
132
+ }
133
+ }
134
+ }
135
+
136
+ return directories;
137
+ }
138
+
139
+ /*
140
+ * Analytics is the one third-party host a view may still name. It is loaded
141
+ * async, it never blocks a render, and every occurrence is required to sit
142
+ * behind the enableGoogleTagManager flag - which Response.render and the
143
+ * frontend index pages both default to "only when this is the hosted
144
+ * product". The dedicated test below enforces the guard.
145
+ */
146
+ const ANALYTICS_HOST: string = "www.googletagmanager.com";
147
+
148
+ /*
149
+ * Matched as a pattern rather than with includes(), so that reading a view's
150
+ * source is not mistaken for validating a URL - it is neither given a URL nor
151
+ * deciding whether to fetch one.
152
+ */
153
+ const ANALYTICS_HOST_PATTERN: RegExp = /www\.googletagmanager\.com/;
154
+
155
+ const RENDER_BLOCKING_CDN_HOSTS: Array<string> = [
156
+ "cdn.tailwindcss.com",
157
+ "cdnjs.cloudflare.com",
158
+ "cdn.jsdelivr.net",
159
+ "unpkg.com",
160
+ "ajax.googleapis.com",
161
+ "code.jquery.com",
162
+ "js.stripe.com",
163
+ "fonts.googleapis.com",
164
+ "fonts.gstatic.com",
165
+ ];
166
+
167
+ const VIEW_ROOTS: Array<ViewRoot> = [
168
+ {
169
+ /*
170
+ * On-call acknowledge / message pages. Rendered by the API service, which
171
+ * every install has, and reached from a notification at the worst possible
172
+ * moment - these are the pages that must not need the internet.
173
+ */
174
+ label: "Common server views",
175
+ directories: [path.join(REPOSITORY_ROOT, "Common", "Server", "Views")],
176
+ allowedHosts: [ANALYTICS_HOST],
177
+ },
178
+ {
179
+ /*
180
+ * Docs, the API reference, and the SSO/OIDC message pages. All served out
181
+ * of the App container, which is what nginx routes "/" to whenever billing
182
+ * is off - i.e. on every self-hosted install.
183
+ */
184
+ label: "App feature set views",
185
+ directories: featureSetViewDirectories(),
186
+ allowedHosts: [ANALYTICS_HOST],
187
+ },
188
+ {
189
+ /*
190
+ * The marketing site and blog. nginx only routes to Home when billing is
191
+ * on, so this is never part of a self-hosted deployment and Google Fonts
192
+ * stays. The libraries a page cannot render without do not: those are
193
+ * shared with Docs and the reference, and one CDN copy drifting from the
194
+ * vendored one is its own bug.
195
+ */
196
+ label: "Home views",
197
+ directories: [path.join(REPOSITORY_ROOT, "Home", "Views")],
198
+ allowedHosts: [ANALYTICS_HOST, "fonts.googleapis.com", "fonts.gstatic.com"],
199
+ },
200
+ ];
201
+
202
+ describe("server-rendered views load no third-party assets", () => {
203
+ for (const root of VIEW_ROOTS) {
204
+ describe(root.label, () => {
205
+ const views: Array<ViewFile> = root.directories.flatMap(collectViewFiles);
206
+
207
+ test("has views to scan", () => {
208
+ /*
209
+ * A rename that empties a root would otherwise turn every check below
210
+ * into a vacuous pass.
211
+ */
212
+ expect(views.length).toBeGreaterThan(0);
213
+ });
214
+
215
+ const bannedHosts: Array<string> = RENDER_BLOCKING_CDN_HOSTS.filter(
216
+ (host: string): boolean => {
217
+ return !root.allowedHosts.includes(host);
218
+ },
219
+ );
220
+
221
+ test.each(
222
+ bannedHosts.map((host: string) => {
223
+ return [host];
224
+ }),
225
+ )("never references %s", (host: string) => {
226
+ const offenders: Array<string> = views
227
+ .filter((view: ViewFile): boolean => {
228
+ return view.contents.includes(host);
229
+ })
230
+ .map((view: ViewFile): string => {
231
+ return view.name;
232
+ });
233
+
234
+ expect(offenders).toEqual([]);
235
+ });
236
+ });
237
+ }
238
+
239
+ test("keeps analytics behind the enableGoogleTagManager flag", () => {
240
+ /*
241
+ * Not because googletagmanager.com hangs a render - it is injected async -
242
+ * but because a self-hosted install has no business phoning Google, and an
243
+ * air-gapped one just accumulates failed requests.
244
+ */
245
+ const offenders: Array<string> = VIEW_ROOTS.flatMap((root: ViewRoot) => {
246
+ return root.directories.flatMap(collectViewFiles);
247
+ })
248
+ .filter((view: ViewFile): boolean => {
249
+ return (
250
+ ANALYTICS_HOST_PATTERN.test(view.contents) &&
251
+ !view.contents.includes("enableGoogleTagManager")
252
+ );
253
+ })
254
+ .map((view: ViewFile): string => {
255
+ return view.name;
256
+ });
257
+
258
+ expect(offenders).toEqual([]);
259
+ });
260
+ });
261
+
262
+ describe("every /oneuptime-assets URL a view uses resolves to a real file", () => {
263
+ const allViews: Array<ViewFile> = VIEW_ROOTS.flatMap((root: ViewRoot) => {
264
+ return root.directories.flatMap(collectViewFiles);
265
+ });
266
+
267
+ /*
268
+ * Static references only. The two dynamic ones - the lazy highlight.js
269
+ * language loaders - are built by string concatenation and are covered by
270
+ * the langMap test below.
271
+ */
272
+ function referencedAssetPaths(): Array<{ view: string; urlPath: string }> {
273
+ const references: Array<{ view: string; urlPath: string }> = [];
274
+
275
+ for (const view of allViews) {
276
+ const matches: Array<string> =
277
+ view.contents.match(
278
+ new RegExp(`${VendorAssetsRoute}/[A-Za-z0-9._/-]+`, "g"),
279
+ ) || [];
280
+
281
+ for (const match of matches) {
282
+ references.push({ view: view.name, urlPath: match });
283
+ }
284
+ }
285
+
286
+ return references;
287
+ }
288
+
289
+ function resolveOnDisk(urlPath: string): string | null {
290
+ const relative: string = urlPath.slice(VendorAssetsRoute.length + 1);
291
+
292
+ if (relative.startsWith("mermaid/")) {
293
+ const mermaidDistPath: string | null = getMermaidDistPath();
294
+
295
+ if (!mermaidDistPath) {
296
+ return null;
297
+ }
298
+
299
+ return path.join(mermaidDistPath, relative.slice("mermaid/".length));
300
+ }
301
+
302
+ return path.join(VendorAssetsPath, relative);
303
+ }
304
+
305
+ test("finds the references at all", () => {
306
+ expect(referencedAssetPaths().length).toBeGreaterThan(0);
307
+ });
308
+
309
+ test("resolves every one of them", () => {
310
+ const missing: Array<string> = referencedAssetPaths()
311
+ .filter((reference: { urlPath: string }): boolean => {
312
+ const onDisk: string | null = resolveOnDisk(reference.urlPath);
313
+
314
+ return !onDisk || !fs.existsSync(onDisk);
315
+ })
316
+ .map((reference: { view: string; urlPath: string }): string => {
317
+ return `${reference.view}: ${reference.urlPath}`;
318
+ });
319
+
320
+ expect(missing).toEqual([]);
321
+ });
322
+
323
+ test("covers the assets the fix was actually about", () => {
324
+ /*
325
+ * The scan above proves whatever is referenced exists; it would also pass
326
+ * on a view that had quietly dropped the reference. These are the three
327
+ * things the issue named.
328
+ */
329
+ const expectations: Array<[string, Array<string>]> = [
330
+ [
331
+ path.join("App", "FeatureSet", "Docs", "Views", "Partials", "Head.ejs"),
332
+ [
333
+ "/oneuptime-assets/tailwind/tailwind-3.4.5.js",
334
+ "/oneuptime-assets/highlight/highlight.min.js",
335
+ "/oneuptime-assets/highlight/styles/vs2015.min.css",
336
+ "/oneuptime-assets/mermaid/mermaid.esm.min.mjs",
337
+ ],
338
+ ],
339
+ [
340
+ path.join(
341
+ "App",
342
+ "FeatureSet",
343
+ "APIReference",
344
+ "views",
345
+ "partials",
346
+ "head.ejs",
347
+ ),
348
+ [
349
+ "/oneuptime-assets/tailwind/tailwind-3.4.5.js",
350
+ "/oneuptime-assets/highlight/highlight.min.js",
351
+ "/oneuptime-assets/highlight/styles/github-dark.min.css",
352
+ ],
353
+ ],
354
+ [
355
+ path.join(
356
+ "App",
357
+ "FeatureSet",
358
+ "Identity",
359
+ "Views",
360
+ "Partials",
361
+ "Head.ejs",
362
+ ),
363
+ ["/oneuptime-assets/tailwind/tailwind-3.4.5.js"],
364
+ ],
365
+ [
366
+ path.join("Common", "Server", "Views", "Partials", "Head.ejs"),
367
+ [
368
+ "/oneuptime-assets/tailwind/tailwind-3.4.5.js",
369
+ "/oneuptime-assets/fonts/InterVariable.woff2",
370
+ ],
371
+ ],
372
+ [
373
+ path.join("Home", "Views", "head-basic.ejs"),
374
+ ["/oneuptime-assets/tailwind/tailwind-3.4.5.js"],
375
+ ],
376
+ [
377
+ path.join("Home", "Views", "Blog", "Post.ejs"),
378
+ [
379
+ "/oneuptime-assets/highlight/highlight.min.js",
380
+ "/oneuptime-assets/mermaid/mermaid.min.js",
381
+ ],
382
+ ],
383
+ ];
384
+
385
+ for (const [viewName, expectedUrls] of expectations) {
386
+ const view: ViewFile | undefined = allViews.find(
387
+ (candidate: ViewFile): boolean => {
388
+ return candidate.name === viewName;
389
+ },
390
+ );
391
+
392
+ expect([viewName, Boolean(view)]).toEqual([viewName, true]);
393
+
394
+ for (const expectedUrl of expectedUrls) {
395
+ expect([
396
+ viewName,
397
+ expectedUrl,
398
+ view?.contents.includes(expectedUrl),
399
+ ]).toEqual([viewName, expectedUrl, true]);
400
+ }
401
+ }
402
+ });
403
+ });
404
+
405
+ describe("lazily-loaded highlight.js grammars", () => {
406
+ /*
407
+ * The docs and the blog build their script URL by concatenation:
408
+ *
409
+ * s.src = '/oneuptime-assets/highlight/languages/' + lang + '.min.js';
410
+ *
411
+ * so nothing in the URL scan above can tell whether the grammar exists.
412
+ * Adding a language to one of these maps without vendoring the file leaves
413
+ * that language silently unhighlighted on an offline install - the same
414
+ * class of failure, just quieter.
415
+ */
416
+ const viewsWithLanguageMaps: Array<string> = [
417
+ path.join(
418
+ REPOSITORY_ROOT,
419
+ "App",
420
+ "FeatureSet",
421
+ "Docs",
422
+ "Views",
423
+ "Partials",
424
+ "Head.ejs",
425
+ ),
426
+ path.join(REPOSITORY_ROOT, "Home", "Views", "Blog", "Post.ejs"),
427
+ ];
428
+
429
+ function grammarsUsedBy(viewPath: string): Array<string> {
430
+ const contents: string = fs.readFileSync(viewPath, "utf8");
431
+ const map: RegExpMatchArray | null = contents.match(
432
+ /var langMap = \{([\s\S]*?)\};/,
433
+ );
434
+
435
+ if (!map || !map[1]) {
436
+ return [];
437
+ }
438
+
439
+ const values: Array<string> = map[1].match(/:\s*'([a-z0-9]+)'/g) || [];
440
+
441
+ return Array.from(
442
+ new Set(
443
+ values.map((value: string): string => {
444
+ return value.replace(/^:\s*'|'$/g, "");
445
+ }),
446
+ ),
447
+ ).sort();
448
+ }
449
+
450
+ test.each(
451
+ viewsWithLanguageMaps.map((viewPath: string) => {
452
+ return [viewPath];
453
+ }),
454
+ )("%s only maps grammars that are vendored", (viewPath: string) => {
455
+ const grammars: Array<string> = grammarsUsedBy(viewPath);
456
+
457
+ expect(grammars.length).toBeGreaterThan(0);
458
+
459
+ const missing: Array<string> = grammars.filter(
460
+ (grammar: string): boolean => {
461
+ return !fs.existsSync(
462
+ path.join(
463
+ VendorAssetsPath,
464
+ "highlight",
465
+ "languages",
466
+ `${grammar}.min.js`,
467
+ ),
468
+ );
469
+ },
470
+ );
471
+
472
+ expect(missing).toEqual([]);
473
+ });
474
+
475
+ test("vendors no grammar no view asks for", () => {
476
+ /*
477
+ * Not a correctness rule - a maintenance one. Every file here has to be
478
+ * re-downloaded on a highlight.js bump, so the set should stay the set
479
+ * something actually loads.
480
+ */
481
+ const requested: Set<string> = new Set<string>();
482
+
483
+ for (const viewPath of viewsWithLanguageMaps) {
484
+ for (const grammar of grammarsUsedBy(viewPath)) {
485
+ requested.add(grammar);
486
+ }
487
+ }
488
+
489
+ /* The API reference loads these with plain <script> tags. */
490
+ for (const eager of [
491
+ "python",
492
+ "go",
493
+ "java",
494
+ "csharp",
495
+ "php",
496
+ "ruby",
497
+ "rust",
498
+ "powershell",
499
+ "bash",
500
+ "json",
501
+ "javascript",
502
+ "typescript",
503
+ ]) {
504
+ requested.add(eager);
505
+ }
506
+
507
+ const vendored: Array<string> = fs
508
+ .readdirSync(path.join(VendorAssetsPath, "highlight", "languages"))
509
+ .map((file: string): string => {
510
+ return file.replace(/\.min\.js$/, "");
511
+ });
512
+
513
+ const unused: Array<string> = vendored.filter(
514
+ (grammar: string): boolean => {
515
+ return !requested.has(grammar);
516
+ },
517
+ );
518
+
519
+ expect(unused).toEqual([]);
520
+ });
521
+ });
@@ -0,0 +1,143 @@
1
+ import {
2
+ afterEach,
3
+ beforeEach,
4
+ describe,
5
+ expect,
6
+ jest,
7
+ test,
8
+ } from "@jest/globals";
9
+ import { ExpressRequest, ExpressResponse } from "../../../Server/Utils/Express";
10
+ import { JSONObject } from "../../../Types/JSON";
11
+
12
+ /*
13
+ * Response.render is the only thing standing between a self-hosted install and
14
+ * a Google Tag Manager snippet.
15
+ *
16
+ * The views it renders - the on-call acknowledge page, the SSO message page -
17
+ * are rendered from a dozen call sites, none of which pass an analytics flag,
18
+ * and their <head> partial now guards the GTM block on one. Somebody has to
19
+ * supply it. Doing that per call site would have meant a dozen chances to
20
+ * forget; doing it here means the default is right and a caller has to opt in
21
+ * on purpose.
22
+ */
23
+
24
+ interface RenderCall {
25
+ path: string;
26
+ variables: JSONObject;
27
+ }
28
+
29
+ describe("Response.render", () => {
30
+ let rendered: Array<RenderCall>;
31
+ let response: ExpressResponse;
32
+
33
+ beforeEach(() => {
34
+ rendered = [];
35
+
36
+ response = {
37
+ render: (path: string, variables: JSONObject): void => {
38
+ rendered.push({ path, variables });
39
+ },
40
+ } as unknown as ExpressResponse;
41
+ });
42
+
43
+ afterEach(() => {
44
+ jest.resetModules();
45
+ delete process.env["BILLING_ENABLED"];
46
+ });
47
+
48
+ type LoadResponse = () => Promise<{
49
+ render: (
50
+ request: ExpressRequest,
51
+ response: ExpressResponse,
52
+ path: string,
53
+ variables: JSONObject,
54
+ ) => void;
55
+ }>;
56
+
57
+ const loadResponse: LoadResponse = async () => {
58
+ const { default: ResponseUtil } = await import(
59
+ "../../../Server/Utils/Response"
60
+ );
61
+
62
+ return ResponseUtil as unknown as Awaited<ReturnType<LoadResponse>>;
63
+ };
64
+
65
+ test("turns analytics off when billing is off", async () => {
66
+ process.env["BILLING_ENABLED"] = "false";
67
+
68
+ (await loadResponse()).render(
69
+ {} as ExpressRequest,
70
+ response,
71
+ "/views/ViewMessage.ejs",
72
+ { title: "Acknowledged" },
73
+ );
74
+
75
+ expect(rendered[0]?.variables["enableGoogleTagManager"]).toBe(false);
76
+ });
77
+
78
+ test("turns analytics off when billing is not configured at all", async () => {
79
+ /*
80
+ * The common self-hosted case: the variable is simply absent, not set to
81
+ * "false".
82
+ */
83
+ delete process.env["BILLING_ENABLED"];
84
+
85
+ (await loadResponse()).render(
86
+ {} as ExpressRequest,
87
+ response,
88
+ "/views/ViewMessage.ejs",
89
+ {},
90
+ );
91
+
92
+ expect(rendered[0]?.variables["enableGoogleTagManager"]).toBe(false);
93
+ });
94
+
95
+ test("leaves analytics on for the hosted product", async () => {
96
+ process.env["BILLING_ENABLED"] = "true";
97
+
98
+ (await loadResponse()).render(
99
+ {} as ExpressRequest,
100
+ response,
101
+ "/views/ViewMessage.ejs",
102
+ {},
103
+ );
104
+
105
+ expect(rendered[0]?.variables["enableGoogleTagManager"]).toBe(true);
106
+ });
107
+
108
+ test("lets a caller override the default", async () => {
109
+ process.env["BILLING_ENABLED"] = "true";
110
+
111
+ (await loadResponse()).render(
112
+ {} as ExpressRequest,
113
+ response,
114
+ "/views/ViewMessage.ejs",
115
+ { enableGoogleTagManager: false },
116
+ );
117
+
118
+ expect(rendered[0]?.variables["enableGoogleTagManager"]).toBe(false);
119
+ });
120
+
121
+ test("passes the caller's own variables through untouched", async () => {
122
+ process.env["BILLING_ENABLED"] = "false";
123
+
124
+ (await loadResponse()).render(
125
+ {} as ExpressRequest,
126
+ response,
127
+ "/views/AcknowledgeUserOnCallNotification.ejs",
128
+ {
129
+ title: "Acknowledge Incident",
130
+ message: "Do you want to acknowledge this Incident?",
131
+ acknowledgeUrl: "https://oneuptime.example.com/api/ack/1",
132
+ },
133
+ );
134
+
135
+ expect(rendered[0]?.path).toBe(
136
+ "/views/AcknowledgeUserOnCallNotification.ejs",
137
+ );
138
+ expect(rendered[0]?.variables["title"]).toBe("Acknowledge Incident");
139
+ expect(rendered[0]?.variables["acknowledgeUrl"]).toBe(
140
+ "https://oneuptime.example.com/api/ack/1",
141
+ );
142
+ });
143
+ });