@oneuptime/common 12.0.4 → 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 (838) hide show
  1. package/Models/DatabaseModels/AIRun.ts +71 -1
  2. package/Models/DatabaseModels/AlertFeed.ts +30 -0
  3. package/Models/DatabaseModels/Dashboard.ts +28 -0
  4. package/Models/DatabaseModels/DataSource.ts +744 -0
  5. package/Models/DatabaseModels/Incident.ts +2 -0
  6. package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
  7. package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
  8. package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
  9. package/Models/DatabaseModels/IncidentFeed.ts +30 -0
  10. package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
  11. package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
  12. package/Models/DatabaseModels/Index.ts +3 -0
  13. package/Models/DatabaseModels/LogSavedView.ts +33 -0
  14. package/Models/DatabaseModels/Project.ts +231 -9
  15. package/Models/DatabaseModels/ProjectCallSMSConfig.ts +10 -2
  16. package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
  17. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
  18. package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
  19. package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.ts +4 -4
  20. package/Models/DatabaseModels/StatusPage.ts +28 -0
  21. package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
  22. package/Models/DatabaseModels/User.ts +2 -0
  23. package/Models/DatabaseModels/UserOnCallLog.ts +2 -0
  24. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +2 -0
  25. package/Models/DatabaseModels/UserSession.ts +2 -0
  26. package/Models/DatabaseModels/UserTotpAuth.ts +6 -4
  27. package/Models/DatabaseModels/UserWebAuthn.ts +5 -3
  28. package/Server/API/AIAgentDataAPI.ts +44 -55
  29. package/Server/API/AIInsightAPI.ts +47 -4
  30. package/Server/API/AIInvestigationAPI.ts +200 -17
  31. package/Server/API/DashboardAPI.ts +186 -502
  32. package/Server/API/DataSourceAPI.ts +268 -0
  33. package/Server/API/StatusPageAPI.ts +49 -20
  34. package/Server/API/UserAPI.ts +119 -0
  35. package/Server/EnvironmentConfig.ts +16 -0
  36. package/Server/Infrastructure/ClickhouseConfig.ts +74 -1
  37. package/Server/Infrastructure/ClickhouseDatabase.ts +1 -1
  38. package/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.ts +27 -0
  39. package/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.ts +89 -0
  40. package/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.ts +27 -0
  41. package/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.ts +39 -0
  42. package/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.ts +40 -0
  43. package/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.ts +26 -0
  44. package/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.ts +24 -0
  45. package/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.ts +76 -0
  46. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +16 -0
  47. package/Server/Infrastructure/Queue.ts +26 -0
  48. package/Server/Infrastructure/QueueWorker.ts +17 -0
  49. package/Server/Middleware/TelemetryIngest.ts +8 -3
  50. package/Server/Services/AIInsightService.ts +132 -12
  51. package/Server/Services/AIRunService.ts +112 -10
  52. package/Server/Services/AIService.ts +109 -22
  53. package/Server/Services/AlertFeedService.ts +5 -0
  54. package/Server/Services/AlertService.ts +38 -32
  55. package/Server/Services/AnalyticsDatabaseService.ts +37 -4
  56. package/Server/Services/DataSourceService.ts +200 -0
  57. package/Server/Services/DatabaseService.ts +43 -2
  58. package/Server/Services/HostService.ts +92 -0
  59. package/Server/Services/IncidentFeedService.ts +5 -0
  60. package/Server/Services/IncidentService.ts +45 -0
  61. package/Server/Services/Index.ts +2 -0
  62. package/Server/Services/LlmLogService.ts +46 -2
  63. package/Server/Services/MonitorService.ts +49 -0
  64. package/Server/Services/MonitorStatusService.ts +166 -0
  65. package/Server/Services/OpenTelemetryIngestService.ts +255 -184
  66. package/Server/Services/RumSessionPinService.ts +7 -21
  67. package/Server/Services/StatusPageSubscriberService.ts +13 -0
  68. package/Server/Services/UserService.ts +280 -9
  69. package/Server/Static/Vendor/README.md +62 -0
  70. package/Server/Static/Vendor/fonts/InterVariable.woff2 +0 -0
  71. package/Server/Static/Vendor/highlight/highlight.min.js +1244 -0
  72. package/Server/Static/Vendor/highlight/languages/apache.min.js +15 -0
  73. package/Server/Static/Vendor/highlight/languages/bash.min.js +21 -0
  74. package/Server/Static/Vendor/highlight/languages/c.min.js +41 -0
  75. package/Server/Static/Vendor/highlight/languages/cpp.min.js +47 -0
  76. package/Server/Static/Vendor/highlight/languages/csharp.min.js +49 -0
  77. package/Server/Static/Vendor/highlight/languages/css.min.js +31 -0
  78. package/Server/Static/Vendor/highlight/languages/diff.min.js +9 -0
  79. package/Server/Static/Vendor/highlight/languages/dns.min.js +11 -0
  80. package/Server/Static/Vendor/highlight/languages/dockerfile.min.js +8 -0
  81. package/Server/Static/Vendor/highlight/languages/go.min.js +20 -0
  82. package/Server/Static/Vendor/highlight/languages/graphql.min.js +12 -0
  83. package/Server/Static/Vendor/highlight/languages/http.min.js +14 -0
  84. package/Server/Static/Vendor/highlight/languages/ini.min.js +15 -0
  85. package/Server/Static/Vendor/highlight/languages/java.min.js +38 -0
  86. package/Server/Static/Vendor/highlight/languages/javascript.min.js +81 -0
  87. package/Server/Static/Vendor/highlight/languages/json.min.js +8 -0
  88. package/Server/Static/Vendor/highlight/languages/kotlin.min.js +46 -0
  89. package/Server/Static/Vendor/highlight/languages/lua.min.js +15 -0
  90. package/Server/Static/Vendor/highlight/languages/makefile.min.js +14 -0
  91. package/Server/Static/Vendor/highlight/languages/nginx.min.js +21 -0
  92. package/Server/Static/Vendor/highlight/languages/perl.min.js +41 -0
  93. package/Server/Static/Vendor/highlight/languages/php.min.js +59 -0
  94. package/Server/Static/Vendor/highlight/languages/powershell.min.js +39 -0
  95. package/Server/Static/Vendor/highlight/languages/python.min.js +42 -0
  96. package/Server/Static/Vendor/highlight/languages/r.min.js +26 -0
  97. package/Server/Static/Vendor/highlight/languages/ruby.min.js +54 -0
  98. package/Server/Static/Vendor/highlight/languages/rust.min.js +27 -0
  99. package/Server/Static/Vendor/highlight/languages/scala.min.js +28 -0
  100. package/Server/Static/Vendor/highlight/languages/sql.min.js +21 -0
  101. package/Server/Static/Vendor/highlight/languages/swift.min.js +68 -0
  102. package/Server/Static/Vendor/highlight/languages/typescript.min.js +99 -0
  103. package/Server/Static/Vendor/highlight/languages/xml.min.js +29 -0
  104. package/Server/Static/Vendor/highlight/languages/yaml.min.js +28 -0
  105. package/Server/Static/Vendor/highlight/styles/github-dark.min.css +10 -0
  106. package/Server/Static/Vendor/highlight/styles/vs2015.min.css +1 -0
  107. package/Server/Static/Vendor/tailwind/tailwind-3.4.5.js +21028 -0
  108. package/Server/Types/Database/Permissions/BasePermission.ts +7 -0
  109. package/Server/Types/Database/Permissions/DeletePermission.ts +2 -0
  110. package/Server/Types/Database/Permissions/ReadPermission.ts +3 -0
  111. package/Server/Types/Database/Permissions/TenantPermission.ts +101 -16
  112. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +6 -0
  113. package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +4 -0
  114. package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +8 -5
  115. package/Server/Utils/AI/CodeFix/FixRunBudget.ts +90 -16
  116. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +2 -0
  117. package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +2 -0
  118. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +311 -31
  119. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +26 -24
  120. package/Server/Utils/AI/SRE/ConfidenceSignal.ts +182 -71
  121. package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +252 -43
  122. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +26 -24
  123. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.ts +125 -0
  124. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +25 -15
  125. package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +256 -57
  126. package/Server/Utils/AI/SRE/Insights/InsightStore.ts +76 -18
  127. package/Server/Utils/AI/SRE/InstrumentationTaskTrigger.ts +47 -13
  128. package/Server/Utils/AI/SRE/InvestigationGrader.ts +9 -5
  129. package/Server/Utils/AI/SRE/InvestigationQueue.ts +141 -24
  130. package/Server/Utils/AI/SRE/InvestigationSubjectLock.ts +66 -0
  131. package/Server/Utils/AI/SRE/InvestigationTldr.ts +352 -0
  132. package/Server/Utils/AI/SRE/PostedRootCause.ts +94 -3
  133. package/Server/Utils/AI/SRE/README.md +1 -1
  134. package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +132 -10
  135. package/Server/Utils/AnalyticsDatabase/ClusterConfig.ts +24 -0
  136. package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +7 -2
  137. package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +1793 -0
  138. package/Server/Utils/Dashboard/PublicDashboardViewConfig.ts +65 -0
  139. package/Server/Utils/DataSource/ConnectorRegistry.ts +53 -0
  140. package/Server/Utils/DataSource/Connectors/ClickHouseConnector.ts +338 -0
  141. package/Server/Utils/DataSource/Connectors/ElasticsearchConnector.ts +717 -0
  142. package/Server/Utils/DataSource/Connectors/LokiConnector.ts +606 -0
  143. package/Server/Utils/DataSource/Connectors/MySqlConnector.ts +307 -0
  144. package/Server/Utils/DataSource/Connectors/PostgresConnector.ts +260 -0
  145. package/Server/Utils/DataSource/Connectors/PrometheusConnector.ts +555 -0
  146. package/Server/Utils/DataSource/Connectors/RestApiConnector.ts +597 -0
  147. package/Server/Utils/DataSource/Connectors/SqlServerConnector.ts +318 -0
  148. package/Server/Utils/DataSource/EgressGuard.ts +446 -0
  149. package/Server/Utils/DataSource/HttpFetch.ts +221 -0
  150. package/Server/Utils/DataSource/SqlQueryGuard.ts +383 -0
  151. package/Server/Utils/DataSource/SqlResultShaper.ts +372 -0
  152. package/Server/Utils/DataSource/Types.ts +93 -0
  153. package/Server/Utils/Database/PostgresErrorTranslator.ts +172 -17
  154. package/Server/Utils/InProcessMemo.ts +141 -0
  155. package/Server/Utils/InstanceHealth/TelemetryIngestion.ts +628 -0
  156. package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +29 -0
  157. package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +56 -0
  158. package/Server/Utils/Monitor/MonitorMetricUtil.ts +104 -0
  159. package/Server/Utils/Monitor/MonitorResource.ts +14 -0
  160. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -0
  161. package/Server/Utils/PasswordHash.ts +28 -4
  162. package/Server/Utils/Response.ts +12 -1
  163. package/Server/Utils/SSRFProtection.ts +237 -0
  164. package/Server/Utils/StartServer.ts +8 -0
  165. package/Server/Utils/StatusPageSubscriberWebhook.ts +30 -0
  166. package/Server/Utils/Telemetry/CaptureSpan.ts +30 -18
  167. package/Server/Utils/Telemetry/IngestionTimestamp.ts +75 -0
  168. package/Server/Utils/Telemetry/ResourceHeartbeat.ts +99 -7
  169. package/Server/Utils/Telemetry/Telemetry.ts +112 -1
  170. package/Server/Utils/Telemetry.ts +104 -3
  171. package/Server/Utils/VendorAssets.ts +165 -0
  172. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +28 -5
  173. package/Server/Utils/Workspace/Slack/Slack.ts +5 -0
  174. package/Server/Views/Partials/Head.ejs +21 -7
  175. package/Tests/App/AdminDashboard/AdminProjectsIdFilter.test.tsx +207 -0
  176. package/Tests/App/AdminDashboard/AdminUsersIdFilter.test.tsx +216 -0
  177. package/Tests/App/Dashboard/AIInsightViewActions.test.tsx +422 -0
  178. package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +251 -0
  179. package/Tests/App/Dashboard/AddWidgetModal.test.tsx +10 -3
  180. package/Tests/App/Dashboard/AlertsSideMenu.test.tsx +387 -0
  181. package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +199 -0
  182. package/Tests/App/Dashboard/DataSourceChartSyntheticConfig.test.tsx +736 -0
  183. package/Tests/App/Dashboard/DataSourceQueryEditor.test.tsx +868 -0
  184. package/Tests/App/Dashboard/DataSourceWidgetCatalog.test.ts +440 -0
  185. package/Tests/App/Dashboard/DataSourceWidgetFetching.test.tsx +2109 -0
  186. package/Tests/App/Dashboard/DataSourceWidgetViews.test.tsx +726 -0
  187. package/Tests/App/Dashboard/EventStatusPanel.test.tsx +747 -0
  188. package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +447 -0
  189. package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +480 -0
  190. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1695 -0
  191. package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +500 -0
  192. package/Tests/App/Dashboard/PortMonitorCriteriaFilter.test.ts +93 -0
  193. package/Tests/App/Dashboard/ProductMenuBreadcrumbs.test.tsx +391 -0
  194. package/Tests/App/Dashboard/ScheduledMaintenanceSideMenu.test.tsx +326 -0
  195. package/Tests/App/Dashboard/SideMenuHarness.tsx +187 -0
  196. package/Tests/App/Dashboard/WidgetCatalog.test.ts +6 -1
  197. package/Tests/App/StatusPage/PublicStatusPageAPIErrorHandling.test.ts +117 -0
  198. package/Tests/App/StatusPage/StatusPageModelAPIPolymorphism.test.ts +223 -0
  199. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +1858 -0
  200. package/Tests/Models/DatabaseModels/DataSourceModelSecrets.test.ts +70 -0
  201. package/Tests/Models/DatabaseModels/PermissionCatalogueCoverage.test.ts +243 -0
  202. package/Tests/Server/API/AIAgentDataFixFromIncidentContext.test.ts +266 -0
  203. package/Tests/Server/API/AIInvestigationAPI.test.ts +781 -0
  204. package/Tests/Server/API/AIInvestigationCreateFixTask.test.ts +80 -0
  205. package/Tests/Server/API/DashboardMasterPasswordAPI.test.ts +172 -1
  206. package/Tests/Server/API/DashboardPublicDataSourceStrip.test.ts +686 -0
  207. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +585 -823
  208. package/Tests/Server/API/DataSourceAPIRoutes.test.ts +486 -0
  209. package/Tests/Server/API/StatusPageMasterPasswordAPI.test.ts +335 -0
  210. package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +291 -0
  211. package/Tests/Server/API/UserAuthenticationAPI.test.ts +641 -0
  212. package/Tests/Server/Infrastructure/ClickhouseKeepAliveOptions.test.ts +441 -0
  213. package/Tests/Server/Middleware/TelemetryIngestTokenLog.test.ts +140 -0
  214. package/Tests/Server/Services/AIInsightService.test.ts +266 -11
  215. package/Tests/Server/Services/AIRunAnalysisTldrPersistence.test.ts +160 -0
  216. package/Tests/Server/Services/AIRunCodeFixClaim.test.ts +59 -5
  217. package/Tests/Server/Services/AIRunHumanVerdict.test.ts +127 -58
  218. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +400 -20
  219. package/Tests/Server/Services/AddMasterPasswordSaltMigration.test.ts +283 -0
  220. package/Tests/Server/Services/AlertMetricResourceAttributes.test.ts +352 -0
  221. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +25 -1
  222. package/Tests/Server/Services/DataSourceServiceSettings.test.ts +244 -0
  223. package/Tests/Server/Services/DatabaseServicePerUserPasswordSalt.test.ts +45 -35
  224. package/Tests/Server/Services/DatabaseServiceUpdateColumnsWithoutHooks.test.ts +54 -0
  225. package/Tests/Server/Services/FeedAIRunAssociation.test.ts +125 -0
  226. package/Tests/Server/Services/FixFromIncidentTaskTrigger.test.ts +418 -57
  227. package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +397 -0
  228. package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +41 -2
  229. package/Tests/Server/Services/IncidentMetricResourceAttributes.test.ts +408 -0
  230. package/Tests/Server/Services/InstrumentationTaskTrigger.test.ts +173 -14
  231. package/Tests/Server/Services/MasterPasswordScrypt.test.ts +567 -0
  232. package/Tests/Server/Services/MonitorStatusServiceDeleteReferenceCleanup.test.ts +351 -0
  233. package/Tests/Server/Services/MonitorStatusServiceValidation.test.ts +171 -0
  234. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +398 -0
  235. package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +19 -0
  236. package/Tests/Server/Services/ProjectCallSMSConfigCredentialUniqueness.test.ts +305 -0
  237. package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +36 -1
  238. package/Tests/Server/Services/RumSessionPinUniqueViolationRecovery.test.ts +163 -0
  239. package/Tests/Server/Services/SeparateIncidentAlertAiSettingsMigration.test.ts +194 -0
  240. package/Tests/Server/Services/UserAuthenticationService.test.ts +973 -0
  241. package/Tests/Server/Types/Database/ObjectIdColumnQuery.test.ts +262 -0
  242. package/Tests/Server/Types/Database/Permissions/TenantPermission.test.ts +358 -0
  243. package/Tests/Server/Utils/AI/AIAlertGating.test.ts +37 -4
  244. package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +330 -29
  245. package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +25 -0
  246. package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +293 -5
  247. package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +59 -1
  248. package/Tests/Server/Utils/AI/FixFromIncidentAutoTrigger.test.ts +342 -19
  249. package/Tests/Server/Utils/AI/FixRunBudget.test.ts +214 -30
  250. package/Tests/Server/Utils/AI/Insights/ExceptionSpikeDetector.test.ts +6 -1
  251. package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +121 -4
  252. package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +2 -0
  253. package/Tests/Server/Utils/AI/Insights/NewExceptionDetector.test.ts +361 -10
  254. package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +65 -17
  255. package/Tests/Server/Utils/AI/InvestigationQueueRemediationExecution.test.ts +3 -0
  256. package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +605 -20
  257. package/Tests/Server/Utils/AI/InvestigationTldr.test.ts +623 -0
  258. package/Tests/Server/Utils/AI/InvestigationTldrWiring.test.ts +98 -0
  259. package/Tests/Server/Utils/AI/PostedRootCause.test.ts +254 -0
  260. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +4 -0
  261. package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +2 -0
  262. package/Tests/Server/Utils/AI/SubjectCodeFixRunDedupe.test.ts +44 -0
  263. package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +30 -0
  264. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +857 -0
  265. package/Tests/Server/Utils/Dashboard/PublicDashboardViewConfig.test.ts +480 -0
  266. package/Tests/Server/Utils/DataSource/ClickHouseConnector.test.ts +759 -0
  267. package/Tests/Server/Utils/DataSource/ConnectorRegistry.test.ts +37 -0
  268. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +645 -0
  269. package/Tests/Server/Utils/DataSource/ElasticsearchConnector.test.ts +1206 -0
  270. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +616 -0
  271. package/Tests/Server/Utils/DataSource/LokiConnector.test.ts +970 -0
  272. package/Tests/Server/Utils/DataSource/MySqlConnector.test.ts +935 -0
  273. package/Tests/Server/Utils/DataSource/PostgresConnector.test.ts +854 -0
  274. package/Tests/Server/Utils/DataSource/PrometheusConnector.test.ts +881 -0
  275. package/Tests/Server/Utils/DataSource/RestApiConnector.test.ts +1020 -0
  276. package/Tests/Server/Utils/DataSource/SqlQueryGuard.test.ts +425 -0
  277. package/Tests/Server/Utils/DataSource/SqlResultShaper.test.ts +555 -0
  278. package/Tests/Server/Utils/DataSource/SqlServerConnector.test.ts +934 -0
  279. package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +228 -7
  280. package/Tests/Server/Utils/InProcessMemo.test.ts +292 -0
  281. package/Tests/Server/Utils/InstanceHealth/TelemetryIngestion.test.ts +960 -0
  282. package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +103 -0
  283. package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +212 -0
  284. package/Tests/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.test.ts +401 -0
  285. package/Tests/Server/Utils/Monitor/MonitorMetricResourceAttributes.test.ts +336 -0
  286. package/Tests/Server/Utils/Monitor/MonitorMetricUtilPortTimings.test.ts +243 -0
  287. package/Tests/Server/Utils/OfflineAssetHygiene.test.ts +521 -0
  288. package/Tests/Server/Utils/PasswordHash.test.ts +30 -0
  289. package/Tests/Server/Utils/ResponseRenderAnalytics.test.ts +143 -0
  290. package/Tests/Server/Utils/SSRFProtection.test.ts +193 -0
  291. package/Tests/Server/Utils/StatusPageSubscriberWebhook.test.ts +101 -0
  292. package/Tests/Server/Utils/TailwindBuildCopy.test.ts +225 -0
  293. package/Tests/Server/Utils/Telemetry/ResourceHeartbeatL1Memo.test.ts +355 -0
  294. package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +128 -0
  295. package/Tests/Server/Utils/Telemetry/TelemetryUtilAttributeKeys.test.ts +381 -0
  296. package/Tests/Server/Utils/Telemetry.test.ts +87 -0
  297. package/Tests/Server/Utils/VendorAssetIntegrity.test.ts +343 -0
  298. package/Tests/Server/Utils/VendorAssets.test.ts +671 -0
  299. package/Tests/Server/Views/OfflineRender.test.ts +297 -0
  300. package/Tests/Types/Dashboard/DashboardTemplates.test.ts +111 -0
  301. package/Tests/Types/Dashboard/DataSourceComponentTypes.test.ts +618 -0
  302. package/Tests/Types/DateClickhouseFormat.test.ts +192 -0
  303. package/Tests/Types/Monitor/CephMetricCatalog.test.ts +104 -0
  304. package/Tests/Types/Monitor/CriteriaFilter.test.ts +4 -0
  305. package/Tests/Types/Monitor/DockerMetricCatalog.test.ts +109 -0
  306. package/Tests/Types/Monitor/DockerSwarmMetricCatalog.test.ts +118 -0
  307. package/Tests/Types/Monitor/HostMetricCatalog.test.ts +104 -0
  308. package/Tests/Types/Monitor/IotMetricCatalog.test.ts +104 -0
  309. package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +118 -0
  310. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +42 -0
  311. package/Tests/Types/Monitor/MonitorStep.test.ts +38 -0
  312. package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +75 -0
  313. package/Tests/Types/Monitor/PodmanMetricCatalog.test.ts +109 -0
  314. package/Tests/Types/Monitor/ProxmoxMetricCatalog.test.ts +107 -0
  315. package/Tests/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.test.ts +151 -0
  316. package/Tests/Types/Password.test.ts +363 -0
  317. package/Tests/Types/Permission.test.ts +137 -0
  318. package/Tests/Types/Rum/SessionReplayMaskingMode.test.ts +101 -0
  319. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +5 -5
  320. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +3 -5
  321. package/Tests/UI/Components/ConfirmModal.test.tsx +7 -0
  322. package/Tests/UI/Components/ErrorBoundary.test.tsx +211 -0
  323. package/Tests/UI/Components/FeedItemSafeMode.test.tsx +74 -0
  324. package/Tests/UI/Components/Modal.test.tsx +281 -1
  325. package/Tests/UI/Components/MoreMenu.test.tsx +756 -0
  326. package/Tests/UI/Components/ObjectIdFilterPipeline.test.tsx +396 -0
  327. package/Tests/UI/Components/StatusPage/ResourceGroupNavigator.test.tsx +1147 -0
  328. package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +62 -0
  329. package/Tests/UI/Monitor/PortMonitorView.test.tsx +237 -0
  330. package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +91 -0
  331. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +116 -1
  332. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  333. package/Tests/UI/Utils/DownloadFile.test.ts +103 -0
  334. package/Tests/UI/Utils/ErrorSupportBundle.test.ts +582 -0
  335. package/Tests/UI/Utils/Project.test.ts +31 -0
  336. package/Tests/UI/Utils/StatusPageModelAPIInjection.test.ts +245 -0
  337. package/Tests/UI/Utils/UseDashboardGridDnd.test.tsx +820 -0
  338. package/Tests/Utils/Analytics.test.ts +23 -0
  339. package/Tests/Utils/Dashboard/Components/DashboardDataSourceComponents.test.ts +640 -0
  340. package/Tests/Utils/Dashboard/DashboardViewConfig.test.ts +329 -0
  341. package/Tests/Utils/Dashboard/GridLayout.test.ts +951 -0
  342. package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +138 -0
  343. package/Tests/Utils/DataSource/DataSourceValueReducer.test.ts +526 -0
  344. package/Tests/Utils/Metrics/MetricResourceAttributeUtil.test.ts +691 -0
  345. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +117 -0
  346. package/Tests/Utils/RecordingRuleExpression.test.ts +327 -0
  347. package/Tests/Utils/StatusPage/GroupHierarchyView.test.ts +1452 -0
  348. package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +186 -0
  349. package/Tests/Utils/StatusPage/GroupTree.test.ts +456 -0
  350. package/Tests/Utils/StatusPage/OverviewGroupHierarchyVisibility.test.ts +588 -0
  351. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +931 -0
  352. package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +288 -0
  353. package/Tests/Utils/Telemetry/IngestionTimestamp.test.ts +170 -0
  354. package/Tests/Utils/Telemetry/SavedViewTimeRange.test.ts +244 -0
  355. package/Tests/Utils/Telemetry/TelemetryQueryTimeRange.test.ts +825 -0
  356. package/Types/AI/AIInsightEvidence.ts +6 -0
  357. package/Types/AI/AIRunCodeFixRecommendation.ts +17 -0
  358. package/Types/AI/CodeFixTaskContext.ts +63 -3
  359. package/Types/AI/CodeFixTaskType.ts +3 -3
  360. package/Types/Analytics/RevenueEvent.ts +31 -0
  361. package/Types/Dashboard/DashboardComponentType.ts +31 -0
  362. package/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.ts +27 -0
  363. package/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.ts +32 -0
  364. package/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.ts +30 -0
  365. package/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.ts +55 -0
  366. package/Types/DataSource/DataSourceLimits.ts +62 -0
  367. package/Types/DataSource/DataSourceQueryConfig.ts +41 -0
  368. package/Types/DataSource/DataSourceTableResult.ts +38 -0
  369. package/Types/DataSource/DataSourceType.ts +213 -0
  370. package/Types/Date.ts +43 -3
  371. package/Types/HashedString.ts +4 -3
  372. package/Types/Monitor/CriteriaFilter.ts +4 -0
  373. package/Types/Monitor/DomainMonitor/DomainLookupMethod.ts +23 -0
  374. package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +7 -0
  375. package/Types/Monitor/MonitorCriteriaInstance.ts +24 -7
  376. package/Types/Monitor/MonitorMetricType.ts +8 -0
  377. package/Types/Monitor/MonitorStep.ts +10 -1
  378. package/Types/Monitor/MonitorStepDomainMonitor.ts +21 -0
  379. package/Types/Monitor/PortMonitor/PortMonitorTimings.ts +10 -0
  380. package/Types/Password.ts +64 -0
  381. package/Types/Permission.ts +69 -175
  382. package/Types/Probe/ProbeMonitorResponse.ts +6 -0
  383. package/Types/UserAuthenticationStatus.ts +34 -0
  384. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +2 -3
  385. package/UI/Components/Button/Button.tsx +1 -1
  386. package/UI/Components/ErrorBoundary.tsx +549 -71
  387. package/UI/Components/Feed/FeedItem.tsx +9 -2
  388. package/UI/Components/Icon/Icon.tsx +10 -9
  389. package/UI/Components/Modal/ConfirmModal.tsx +6 -1
  390. package/UI/Components/Modal/Modal.tsx +267 -35
  391. package/UI/Components/Modal/ModalFooter.tsx +6 -1
  392. package/UI/Components/ModelDetail/CardModelDetail.tsx +0 -12
  393. package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
  394. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +12 -2
  395. package/UI/Components/MoreMenu/MoreMenu.tsx +301 -98
  396. package/UI/Components/MoreMenu/MoreMenuItem.tsx +13 -5
  397. package/UI/Components/StatusPage/ResourceGrid.tsx +314 -0
  398. package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +808 -0
  399. package/UI/Components/StatusPage/ResourceList.tsx +570 -0
  400. package/UI/Styles/Theme.css +18 -0
  401. package/UI/Utils/API/RequestOptions.ts +7 -0
  402. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +1 -0
  403. package/UI/Utils/DownloadFile.ts +16 -8
  404. package/UI/Utils/ErrorSupportBundle.ts +805 -0
  405. package/UI/Utils/ModelAPI/ModelAPI.ts +20 -8
  406. package/UI/Utils/Project.ts +4 -0
  407. package/UI/Utils/StatusPage.ts +8 -2
  408. package/UI/Utils/TestDataSource.ts +61 -0
  409. package/UI/Utils/UseDashboardGridDnd.ts +917 -0
  410. package/UI/esbuild-config.js +45 -0
  411. package/Utils/Analytics.ts +15 -0
  412. package/Utils/Dashboard/Components/DashboardDataSourceChartComponent.ts +88 -0
  413. package/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.ts +123 -0
  414. package/Utils/Dashboard/Components/DashboardDataSourceShared.ts +16 -0
  415. package/Utils/Dashboard/Components/DashboardDataSourceTableComponent.ts +72 -0
  416. package/Utils/Dashboard/Components/DashboardDataSourceValueComponent.ts +126 -0
  417. package/Utils/Dashboard/Components/Index.ts +28 -0
  418. package/Utils/Dashboard/DashboardViewConfig.ts +80 -36
  419. package/Utils/Dashboard/GridLayout.ts +523 -0
  420. package/Utils/DataSource/DataSourceQueryText.ts +94 -0
  421. package/Utils/DataSource/DataSourceValueReducer.ts +156 -0
  422. package/Utils/Metrics/MetricResourceAttributeUtil.ts +380 -0
  423. package/Utils/Metrics/RecordingRuleExpression.ts +19 -17
  424. package/Utils/Monitor/MonitorMetricType.ts +44 -2
  425. package/Utils/NetworkDiscovery/ScanTargetUtil.ts +8 -6
  426. package/Utils/StatusPage/GroupHierarchyView.ts +931 -0
  427. package/Utils/StatusPage/GroupNestingLayout.ts +69 -0
  428. package/Utils/StatusPage/GroupTree.ts +157 -66
  429. package/Utils/StatusPage/ResourceExplorer.ts +853 -0
  430. package/Utils/StatusPage/ResourceUptime.ts +37 -2
  431. package/Utils/Telemetry/SavedViewTimeRange.ts +114 -0
  432. package/Utils/Telemetry/TelemetryQueryTimeRange.ts +334 -0
  433. package/build/dist/Models/DatabaseModels/AIRun.js +73 -1
  434. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  435. package/build/dist/Models/DatabaseModels/AlertFeed.js +32 -0
  436. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  437. package/build/dist/Models/DatabaseModels/Dashboard.js +29 -0
  438. package/build/dist/Models/DatabaseModels/Dashboard.js.map +1 -1
  439. package/build/dist/Models/DatabaseModels/DataSource.js +774 -0
  440. package/build/dist/Models/DatabaseModels/DataSource.js.map +1 -0
  441. package/build/dist/Models/DatabaseModels/Incident.js +2 -0
  442. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  443. package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
  444. package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
  445. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
  446. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
  447. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
  448. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
  449. package/build/dist/Models/DatabaseModels/IncidentFeed.js +32 -0
  450. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
  451. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
  452. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  453. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
  454. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  455. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  456. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  457. package/build/dist/Models/DatabaseModels/LogSavedView.js +33 -0
  458. package/build/dist/Models/DatabaseModels/LogSavedView.js.map +1 -1
  459. package/build/dist/Models/DatabaseModels/Project.js +241 -11
  460. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  461. package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js +14 -4
  462. package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js.map +1 -1
  463. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
  464. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  465. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
  466. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  467. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
  468. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
  469. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js +4 -4
  470. package/build/dist/Models/DatabaseModels/StatusPage.js +29 -0
  471. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  472. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
  473. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  474. package/build/dist/Models/DatabaseModels/User.js +2 -0
  475. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  476. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +2 -0
  477. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  478. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +2 -0
  479. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  480. package/build/dist/Models/DatabaseModels/UserSession.js +2 -0
  481. package/build/dist/Models/DatabaseModels/UserSession.js.map +1 -1
  482. package/build/dist/Models/DatabaseModels/UserTotpAuth.js +6 -4
  483. package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -1
  484. package/build/dist/Models/DatabaseModels/UserWebAuthn.js +5 -3
  485. package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
  486. package/build/dist/Server/API/AIAgentDataAPI.js +28 -46
  487. package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
  488. package/build/dist/Server/API/AIInsightAPI.js +34 -4
  489. package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
  490. package/build/dist/Server/API/AIInvestigationAPI.js +134 -11
  491. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  492. package/build/dist/Server/API/DashboardAPI.js +127 -438
  493. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  494. package/build/dist/Server/API/DataSourceAPI.js +173 -0
  495. package/build/dist/Server/API/DataSourceAPI.js.map +1 -0
  496. package/build/dist/Server/API/StatusPageAPI.js +40 -12
  497. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  498. package/build/dist/Server/API/UserAPI.js +94 -2
  499. package/build/dist/Server/API/UserAPI.js.map +1 -1
  500. package/build/dist/Server/EnvironmentConfig.js +14 -0
  501. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  502. package/build/dist/Server/Infrastructure/ClickhouseConfig.js +61 -1
  503. package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
  504. package/build/dist/Server/Infrastructure/ClickhouseDatabase.js +1 -1
  505. package/build/dist/Server/Infrastructure/ClickhouseDatabase.js.map +1 -1
  506. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js +22 -0
  507. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js.map +1 -0
  508. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js +36 -0
  509. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js.map +1 -0
  510. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js +18 -0
  511. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js.map +1 -0
  512. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js +20 -0
  513. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786303472848-AddDataSourceTable.js.map +1 -0
  514. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js +19 -0
  515. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js.map +1 -0
  516. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js +19 -0
  517. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js.map +1 -0
  518. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js +19 -0
  519. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786600000000-AddInvestigationAnalysisTldr.js.map +1 -0
  520. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js +64 -0
  521. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786700000000-DropProjectCallSMSConfigCredentialUniques.js.map +1 -0
  522. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +16 -0
  523. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  524. package/build/dist/Server/Infrastructure/Queue.js +27 -0
  525. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  526. package/build/dist/Server/Infrastructure/QueueWorker.js +13 -0
  527. package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
  528. package/build/dist/Server/Middleware/TelemetryIngest.js +8 -3
  529. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  530. package/build/dist/Server/Services/AIInsightService.js +110 -10
  531. package/build/dist/Server/Services/AIInsightService.js.map +1 -1
  532. package/build/dist/Server/Services/AIRunService.js +92 -12
  533. package/build/dist/Server/Services/AIRunService.js.map +1 -1
  534. package/build/dist/Server/Services/AIService.js +88 -21
  535. package/build/dist/Server/Services/AIService.js.map +1 -1
  536. package/build/dist/Server/Services/AlertFeedService.js +3 -0
  537. package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
  538. package/build/dist/Server/Services/AlertService.js +28 -35
  539. package/build/dist/Server/Services/AlertService.js.map +1 -1
  540. package/build/dist/Server/Services/AnalyticsDatabaseService.js +37 -5
  541. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  542. package/build/dist/Server/Services/DataSourceService.js +159 -0
  543. package/build/dist/Server/Services/DataSourceService.js.map +1 -0
  544. package/build/dist/Server/Services/DatabaseService.js +21 -2
  545. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  546. package/build/dist/Server/Services/HostService.js +74 -0
  547. package/build/dist/Server/Services/HostService.js.map +1 -1
  548. package/build/dist/Server/Services/IncidentFeedService.js +3 -0
  549. package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
  550. package/build/dist/Server/Services/IncidentService.js +35 -24
  551. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  552. package/build/dist/Server/Services/Index.js +2 -0
  553. package/build/dist/Server/Services/Index.js.map +1 -1
  554. package/build/dist/Server/Services/LlmLogService.js +22 -1
  555. package/build/dist/Server/Services/LlmLogService.js.map +1 -1
  556. package/build/dist/Server/Services/MonitorService.js +45 -0
  557. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  558. package/build/dist/Server/Services/MonitorStatusService.js +129 -0
  559. package/build/dist/Server/Services/MonitorStatusService.js.map +1 -1
  560. package/build/dist/Server/Services/OpenTelemetryIngestService.js +222 -159
  561. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  562. package/build/dist/Server/Services/RumSessionPinService.js +7 -15
  563. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  564. package/build/dist/Server/Services/StatusPageSubscriberService.js +10 -0
  565. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  566. package/build/dist/Server/Services/UserService.js +241 -10
  567. package/build/dist/Server/Services/UserService.js.map +1 -1
  568. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +6 -0
  569. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  570. package/build/dist/Server/Types/Database/Permissions/DeletePermission.js +1 -0
  571. package/build/dist/Server/Types/Database/Permissions/DeletePermission.js.map +1 -1
  572. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js +2 -0
  573. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js.map +1 -1
  574. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +68 -12
  575. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
  576. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +3 -0
  577. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  578. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +4 -0
  579. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
  580. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +8 -5
  581. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
  582. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +63 -24
  583. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
  584. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +2 -0
  585. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  586. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +2 -0
  587. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
  588. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +222 -34
  589. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  590. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +22 -19
  591. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  592. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +128 -49
  593. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -1
  594. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +170 -31
  595. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -1
  596. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +22 -19
  597. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  598. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js +97 -0
  599. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.js.map +1 -0
  600. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +17 -15
  601. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
  602. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +178 -54
  603. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
  604. package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js +65 -16
  605. package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js.map +1 -1
  606. package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js +33 -9
  607. package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js.map +1 -1
  608. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +9 -5
  609. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
  610. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +121 -41
  611. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  612. package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js +46 -0
  613. package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js.map +1 -0
  614. package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js +303 -0
  615. package/build/dist/Server/Utils/AI/SRE/InvestigationTldr.js.map +1 -0
  616. package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js +61 -14
  617. package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js.map +1 -1
  618. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +79 -1
  619. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -1
  620. package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js +21 -0
  621. package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js.map +1 -1
  622. package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -1
  623. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +1261 -0
  624. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -0
  625. package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js +47 -0
  626. package/build/dist/Server/Utils/Dashboard/PublicDashboardViewConfig.js.map +1 -0
  627. package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js +42 -0
  628. package/build/dist/Server/Utils/DataSource/ConnectorRegistry.js.map +1 -0
  629. package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js +187 -0
  630. package/build/dist/Server/Utils/DataSource/Connectors/ClickHouseConnector.js.map +1 -0
  631. package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js +493 -0
  632. package/build/dist/Server/Utils/DataSource/Connectors/ElasticsearchConnector.js.map +1 -0
  633. package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js +399 -0
  634. package/build/dist/Server/Utils/DataSource/Connectors/LokiConnector.js.map +1 -0
  635. package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js +195 -0
  636. package/build/dist/Server/Utils/DataSource/Connectors/MySqlConnector.js.map +1 -0
  637. package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js +149 -0
  638. package/build/dist/Server/Utils/DataSource/Connectors/PostgresConnector.js.map +1 -0
  639. package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js +362 -0
  640. package/build/dist/Server/Utils/DataSource/Connectors/PrometheusConnector.js.map +1 -0
  641. package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js +342 -0
  642. package/build/dist/Server/Utils/DataSource/Connectors/RestApiConnector.js.map +1 -0
  643. package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js +186 -0
  644. package/build/dist/Server/Utils/DataSource/Connectors/SqlServerConnector.js.map +1 -0
  645. package/build/dist/Server/Utils/DataSource/EgressGuard.js +305 -0
  646. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -0
  647. package/build/dist/Server/Utils/DataSource/HttpFetch.js +134 -0
  648. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -0
  649. package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js +331 -0
  650. package/build/dist/Server/Utils/DataSource/SqlQueryGuard.js.map +1 -0
  651. package/build/dist/Server/Utils/DataSource/SqlResultShaper.js +280 -0
  652. package/build/dist/Server/Utils/DataSource/SqlResultShaper.js.map +1 -0
  653. package/build/dist/Server/Utils/DataSource/Types.js +2 -0
  654. package/build/dist/Server/Utils/DataSource/Types.js.map +1 -0
  655. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +103 -9
  656. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -1
  657. package/build/dist/Server/Utils/InProcessMemo.js +113 -0
  658. package/build/dist/Server/Utils/InProcessMemo.js.map +1 -0
  659. package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js +406 -0
  660. package/build/dist/Server/Utils/InstanceHealth/TelemetryIngestion.js.map +1 -0
  661. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +20 -3
  662. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
  663. package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +43 -0
  664. package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
  665. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +67 -0
  666. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  667. package/build/dist/Server/Utils/Monitor/MonitorResource.js +14 -0
  668. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  669. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -0
  670. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  671. package/build/dist/Server/Utils/PasswordHash.js +25 -4
  672. package/build/dist/Server/Utils/PasswordHash.js.map +1 -1
  673. package/build/dist/Server/Utils/Response.js +9 -1
  674. package/build/dist/Server/Utils/Response.js.map +1 -1
  675. package/build/dist/Server/Utils/SSRFProtection.js +192 -0
  676. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -0
  677. package/build/dist/Server/Utils/StartServer.js +7 -0
  678. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  679. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js +24 -0
  680. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js.map +1 -1
  681. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +25 -11
  682. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
  683. package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js +32 -0
  684. package/build/dist/Server/Utils/Telemetry/IngestionTimestamp.js.map +1 -0
  685. package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js +92 -5
  686. package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -1
  687. package/build/dist/Server/Utils/Telemetry/Telemetry.js +92 -6
  688. package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
  689. package/build/dist/Server/Utils/Telemetry.js +93 -6
  690. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  691. package/build/dist/Server/Utils/VendorAssets.js +121 -0
  692. package/build/dist/Server/Utils/VendorAssets.js.map +1 -0
  693. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +25 -4
  694. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  695. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +5 -0
  696. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  697. package/build/dist/Types/AI/AIRunCodeFixRecommendation.js +18 -0
  698. package/build/dist/Types/AI/AIRunCodeFixRecommendation.js.map +1 -0
  699. package/build/dist/Types/AI/CodeFixTaskContext.js +23 -3
  700. package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -1
  701. package/build/dist/Types/AI/CodeFixTaskType.js +3 -3
  702. package/build/dist/Types/Analytics/RevenueEvent.js +26 -0
  703. package/build/dist/Types/Analytics/RevenueEvent.js.map +1 -0
  704. package/build/dist/Types/Dashboard/DashboardComponentType.js +27 -0
  705. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  706. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js +2 -0
  707. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceChartComponent.js.map +1 -0
  708. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js +2 -0
  709. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceGaugeComponent.js.map +1 -0
  710. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js +2 -0
  711. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceTableComponent.js.map +1 -0
  712. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js +16 -0
  713. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDataSourceValueComponent.js.map +1 -0
  714. package/build/dist/Types/DataSource/DataSourceLimits.js +47 -0
  715. package/build/dist/Types/DataSource/DataSourceLimits.js.map +1 -0
  716. package/build/dist/Types/DataSource/DataSourceQueryConfig.js +10 -0
  717. package/build/dist/Types/DataSource/DataSourceQueryConfig.js.map +1 -0
  718. package/build/dist/Types/DataSource/DataSourceTableResult.js +14 -0
  719. package/build/dist/Types/DataSource/DataSourceTableResult.js.map +1 -0
  720. package/build/dist/Types/DataSource/DataSourceType.js +183 -0
  721. package/build/dist/Types/DataSource/DataSourceType.js.map +1 -0
  722. package/build/dist/Types/Date.js +38 -3
  723. package/build/dist/Types/Date.js.map +1 -1
  724. package/build/dist/Types/HashedString.js +4 -3
  725. package/build/dist/Types/HashedString.js.map +1 -1
  726. package/build/dist/Types/Monitor/CriteriaFilter.js +4 -0
  727. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  728. package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js +24 -0
  729. package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js.map +1 -0
  730. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +24 -7
  731. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  732. package/build/dist/Types/Monitor/MonitorMetricType.js +7 -0
  733. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  734. package/build/dist/Types/Monitor/MonitorStep.js +6 -1
  735. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  736. package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js +15 -0
  737. package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
  738. package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js +2 -0
  739. package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js.map +1 -0
  740. package/build/dist/Types/Password.js +56 -0
  741. package/build/dist/Types/Password.js.map +1 -0
  742. package/build/dist/Types/Permission.js +65 -155
  743. package/build/dist/Types/Permission.js.map +1 -1
  744. package/build/dist/Types/UserAuthenticationStatus.js +2 -0
  745. package/build/dist/Types/UserAuthenticationStatus.js.map +1 -0
  746. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +2 -5
  747. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  748. package/build/dist/UI/Components/ErrorBoundary.js +427 -52
  749. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  750. package/build/dist/UI/Components/Feed/FeedItem.js +2 -2
  751. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  752. package/build/dist/UI/Components/Icon/Icon.js +10 -4
  753. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  754. package/build/dist/UI/Components/Modal/ConfirmModal.js +1 -1
  755. package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
  756. package/build/dist/UI/Components/Modal/Modal.js +178 -19
  757. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  758. package/build/dist/UI/Components/Modal/ModalFooter.js +3 -1
  759. package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
  760. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +0 -12
  761. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  762. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
  763. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  764. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +12 -2
  765. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  766. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +197 -66
  767. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  768. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +7 -1
  769. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
  770. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +119 -0
  771. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -0
  772. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +354 -0
  773. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -0
  774. package/build/dist/UI/Components/StatusPage/ResourceList.js +203 -0
  775. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -0
  776. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +1 -6
  777. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  778. package/build/dist/UI/Utils/DownloadFile.js +15 -8
  779. package/build/dist/UI/Utils/DownloadFile.js.map +1 -1
  780. package/build/dist/UI/Utils/ErrorSupportBundle.js +476 -0
  781. package/build/dist/UI/Utils/ErrorSupportBundle.js.map +1 -0
  782. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +20 -15
  783. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  784. package/build/dist/UI/Utils/Project.js +3 -0
  785. package/build/dist/UI/Utils/Project.js.map +1 -1
  786. package/build/dist/UI/Utils/StatusPage.js +4 -4
  787. package/build/dist/UI/Utils/StatusPage.js.map +1 -1
  788. package/build/dist/UI/Utils/TestDataSource.js +39 -0
  789. package/build/dist/UI/Utils/TestDataSource.js.map +1 -0
  790. package/build/dist/UI/Utils/UseDashboardGridDnd.js +551 -0
  791. package/build/dist/UI/Utils/UseDashboardGridDnd.js.map +1 -0
  792. package/build/dist/Utils/Analytics.js +4 -0
  793. package/build/dist/Utils/Analytics.js.map +1 -1
  794. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js +79 -0
  795. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceChartComponent.js.map +1 -0
  796. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js +111 -0
  797. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceGaugeComponent.js.map +1 -0
  798. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js +15 -0
  799. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceShared.js.map +1 -0
  800. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js +62 -0
  801. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceTableComponent.js.map +1 -0
  802. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js +112 -0
  803. package/build/dist/Utils/Dashboard/Components/DashboardDataSourceValueComponent.js.map +1 -0
  804. package/build/dist/Utils/Dashboard/Components/Index.js +16 -0
  805. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  806. package/build/dist/Utils/Dashboard/DashboardViewConfig.js +42 -26
  807. package/build/dist/Utils/Dashboard/DashboardViewConfig.js.map +1 -1
  808. package/build/dist/Utils/Dashboard/GridLayout.js +338 -0
  809. package/build/dist/Utils/Dashboard/GridLayout.js.map +1 -0
  810. package/build/dist/Utils/DataSource/DataSourceQueryText.js +64 -0
  811. package/build/dist/Utils/DataSource/DataSourceQueryText.js.map +1 -0
  812. package/build/dist/Utils/DataSource/DataSourceValueReducer.js +124 -0
  813. package/build/dist/Utils/DataSource/DataSourceValueReducer.js.map +1 -0
  814. package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js +281 -0
  815. package/build/dist/Utils/Metrics/MetricResourceAttributeUtil.js.map +1 -0
  816. package/build/dist/Utils/Metrics/RecordingRuleExpression.js +19 -17
  817. package/build/dist/Utils/Metrics/RecordingRuleExpression.js.map +1 -1
  818. package/build/dist/Utils/Monitor/MonitorMetricType.js +38 -6
  819. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  820. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +8 -6
  821. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
  822. package/build/dist/Utils/StatusPage/GroupHierarchyView.js +560 -0
  823. package/build/dist/Utils/StatusPage/GroupHierarchyView.js.map +1 -0
  824. package/build/dist/Utils/StatusPage/GroupNestingLayout.js +46 -0
  825. package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -1
  826. package/build/dist/Utils/StatusPage/GroupTree.js +79 -34
  827. package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -1
  828. package/build/dist/Utils/StatusPage/ResourceExplorer.js +519 -0
  829. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -0
  830. package/build/dist/Utils/StatusPage/ResourceUptime.js +22 -1
  831. package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
  832. package/build/dist/Utils/Telemetry/SavedViewTimeRange.js +79 -0
  833. package/build/dist/Utils/Telemetry/SavedViewTimeRange.js.map +1 -0
  834. package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js +236 -0
  835. package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js.map +1 -0
  836. package/jest.config.json +1 -0
  837. package/package.json +5 -1
  838. package/tsconfig.json +12 -10
@@ -0,0 +1,973 @@
1
+ import DatabaseConfig from "../../../Server/DatabaseConfig";
2
+ import { EncryptionSecret } from "../../../Server/EnvironmentConfig";
3
+ import MailService from "../../../Server/Services/MailService";
4
+ import UserService from "../../../Server/Services/UserService";
5
+ import UserSessionService from "../../../Server/Services/UserSessionService";
6
+ import logger from "../../../Server/Utils/Logger";
7
+ import User from "../../../Models/DatabaseModels/User";
8
+ import Hostname from "../../../Types/API/Hostname";
9
+ import HTTPErrorResponse from "../../../Types/API/HTTPErrorResponse";
10
+ import Protocol from "../../../Types/API/Protocol";
11
+ import OneUptimeDate from "../../../Types/Date";
12
+ import Email from "../../../Types/Email";
13
+ import EmailTemplateType from "../../../Types/Email/EmailTemplateType";
14
+ import BadDataException from "../../../Types/Exception/BadDataException";
15
+ import NotFoundException from "../../../Types/Exception/NotFoundException";
16
+ import HashedString from "../../../Types/HashedString";
17
+ import ObjectID from "../../../Types/ObjectID";
18
+ import UserAuthenticationStatus from "../../../Types/UserAuthenticationStatus";
19
+ import { getJestSpyOn } from "../../Spy";
20
+ import {
21
+ afterEach,
22
+ beforeEach,
23
+ describe,
24
+ expect,
25
+ jest,
26
+ test,
27
+ } from "@jest/globals";
28
+
29
+ /*
30
+ * ---------------------------------------------------------------------------
31
+ * UserService.getAuthenticationStatus / setPassword / sendPasswordResetLink --
32
+ * the three methods behind Admin Dashboard > Users > (a user) > Authentication.
33
+ *
34
+ * These are the only place in the product where one human changes another
35
+ * human's credentials, so every invariant they carry is a security property
36
+ * rather than a nicety, and each one of them can break WITHOUT the page looking
37
+ * any different:
38
+ *
39
+ * - the status page reads `enableTwoFactorAuth`. `User` also has a
40
+ * `twoFactorAuthEnabled` column left over from the initial migration that
41
+ * nothing writes. Reading the wrong one renders "Two-factor auth: disabled"
42
+ * for a user who has it very much enabled -- the page still renders, the
43
+ * operator is just told the opposite of the truth.
44
+ * - setPassword hands the write path an UNHASHED HashedString on purpose.
45
+ * "Helpfully" pre-hashing it would store a digest that does not agree with
46
+ * the per-user salt the write path mints, and nothing fails until the user
47
+ * tries to log in.
48
+ * - sendPasswordResetLink stores only a SHA-256 of the token. Storing the
49
+ * token itself would still produce a working link, so no test that merely
50
+ * follows the link would notice; the difference only shows up in what a
51
+ * leaked database row is worth.
52
+ *
53
+ * Everything below stubs at this service's own boundary -- `findOneBy` and
54
+ * `updateOneById` on the UserService singleton, plus MailService and
55
+ * DatabaseConfig -- so the assertions are about what these three methods ASK
56
+ * for, which is exactly where the bugs above would live. No database is
57
+ * involved.
58
+ * ---------------------------------------------------------------------------
59
+ */
60
+
61
+ // The values the mocked DatabaseConfig reports, so the expected link is exact.
62
+ const TEST_HOSTNAME: string = "oneuptime.example.com";
63
+ const EXPECTED_ORIGIN: string = `http://${TEST_HOSTNAME}`;
64
+
65
+ type BuildUserFunction = (data: {
66
+ id: ObjectID;
67
+ email?: string | undefined;
68
+ password?: HashedString | undefined;
69
+ isEmailVerified?: boolean | undefined;
70
+ enableTwoFactorAuth?: boolean | undefined;
71
+ twoFactorAuthEnabled?: boolean | undefined;
72
+ resetPasswordToken?: string | undefined;
73
+ resetPasswordExpires?: Date | undefined;
74
+ }) => User;
75
+
76
+ const buildUser: BuildUserFunction = (data: {
77
+ id: ObjectID;
78
+ email?: string | undefined;
79
+ password?: HashedString | undefined;
80
+ isEmailVerified?: boolean | undefined;
81
+ enableTwoFactorAuth?: boolean | undefined;
82
+ twoFactorAuthEnabled?: boolean | undefined;
83
+ resetPasswordToken?: string | undefined;
84
+ resetPasswordExpires?: Date | undefined;
85
+ }): User => {
86
+ const user: User = new User();
87
+ user.id = data.id;
88
+
89
+ if (data.email !== undefined) {
90
+ user.email = new Email(data.email);
91
+ }
92
+
93
+ /*
94
+ * Assigned only when supplied, so an omitted field leaves the column
95
+ * genuinely absent -- the same shape a `select` that did not ask for it
96
+ * produces -- rather than explicitly undefined.
97
+ */
98
+ if (data.password !== undefined) {
99
+ user.password = data.password;
100
+ }
101
+
102
+ if (data.isEmailVerified !== undefined) {
103
+ user.isEmailVerified = data.isEmailVerified;
104
+ }
105
+
106
+ if (data.enableTwoFactorAuth !== undefined) {
107
+ user.enableTwoFactorAuth = data.enableTwoFactorAuth;
108
+ }
109
+
110
+ if (data.twoFactorAuthEnabled !== undefined) {
111
+ user.twoFactorAuthEnabled = data.twoFactorAuthEnabled;
112
+ }
113
+
114
+ if (data.resetPasswordToken !== undefined) {
115
+ user.resetPasswordToken = data.resetPasswordToken;
116
+ }
117
+
118
+ if (data.resetPasswordExpires !== undefined) {
119
+ user.resetPasswordExpires = data.resetPasswordExpires;
120
+ }
121
+
122
+ return user;
123
+ };
124
+
125
+ describe("UserService -- master-admin authentication management", () => {
126
+ let userId: ObjectID;
127
+ let findOneBySpy: any;
128
+ let updateOneByIdSpy: any;
129
+ let sendMailSpy: any;
130
+ let revokeSessionsSpy: any;
131
+
132
+ beforeEach(() => {
133
+ jest.restoreAllMocks();
134
+
135
+ userId = ObjectID.generate();
136
+
137
+ findOneBySpy = getJestSpyOn(UserService, "findOneBy").mockImplementation(
138
+ async (): Promise<User | null> => {
139
+ return null;
140
+ },
141
+ );
142
+
143
+ updateOneByIdSpy = getJestSpyOn(
144
+ UserService,
145
+ "updateOneById",
146
+ ).mockImplementation(async (): Promise<void> => {
147
+ return undefined;
148
+ });
149
+
150
+ sendMailSpy = getJestSpyOn(MailService, "sendMail").mockImplementation(
151
+ async (): Promise<any> => {
152
+ return {};
153
+ },
154
+ );
155
+
156
+ /*
157
+ * Revocation belongs to the update hook, not to setPassword. It is stubbed
158
+ * here purely so the "was it called?" assertion cannot accidentally reach a
159
+ * real session table.
160
+ */
161
+ revokeSessionsSpy = getJestSpyOn(
162
+ UserSessionService,
163
+ "revokeAllSessionsByUserId",
164
+ ).mockImplementation(async (): Promise<void> => {
165
+ return undefined;
166
+ });
167
+
168
+ getJestSpyOn(DatabaseConfig, "getHost").mockImplementation(
169
+ async (): Promise<Hostname> => {
170
+ return new Hostname(TEST_HOSTNAME);
171
+ },
172
+ );
173
+
174
+ getJestSpyOn(DatabaseConfig, "getHttpProtocol").mockImplementation(
175
+ async (): Promise<Protocol> => {
176
+ return Protocol.HTTP;
177
+ },
178
+ );
179
+
180
+ getJestSpyOn(logger, "info").mockImplementation((): void => {
181
+ return undefined;
182
+ });
183
+
184
+ /*
185
+ * The deliberate-failure cases below hand a rejection to the CaptureSpan
186
+ * decorator, which records it. That is correct behaviour, and it is also a
187
+ * stack trace on stderr for a test that passed -- silenced so a genuine
188
+ * error in this suite's output is still worth reading.
189
+ */
190
+ getJestSpyOn(logger, "error").mockImplementation((): void => {
191
+ return undefined;
192
+ });
193
+ });
194
+
195
+ afterEach(() => {
196
+ jest.restoreAllMocks();
197
+ });
198
+
199
+ type ResolveUserFunction = (user: User | null) => void;
200
+
201
+ // Makes the next (and every subsequent) findOneBy return this row.
202
+ const resolveUser: ResolveUserFunction = (user: User | null): void => {
203
+ findOneBySpy.mockImplementation(async (): Promise<User | null> => {
204
+ return user;
205
+ });
206
+ };
207
+
208
+ describe("getAuthenticationStatus", () => {
209
+ test("throws NotFoundException when there is no such user", async () => {
210
+ /*
211
+ * Returning a status object full of `false` for a user id that does not
212
+ * exist would render an ordinary-looking page describing nobody -- an
213
+ * operator acting on a mistyped id has to be told, not shown defaults.
214
+ */
215
+ resolveUser(null);
216
+
217
+ await expect(UserService.getAuthenticationStatus(userId)).rejects.toThrow(
218
+ NotFoundException,
219
+ );
220
+ });
221
+
222
+ test("hasPassword is true when the password column is set", async () => {
223
+ /*
224
+ * The column carries a scrypt digest read out of the row, so the flag has
225
+ * to be derived from presence, not from any particular shape of value.
226
+ */
227
+ resolveUser(
228
+ buildUser({
229
+ id: userId,
230
+ password: new HashedString("a-stored-scrypt-digest", true),
231
+ }),
232
+ );
233
+
234
+ const status: UserAuthenticationStatus =
235
+ await UserService.getAuthenticationStatus(userId);
236
+
237
+ expect(status.hasPassword).toBe(true);
238
+ });
239
+
240
+ test("hasPassword is false for an SSO-only user with no password", async () => {
241
+ /*
242
+ * This is the fact the Authentication page exists to show: a user with no
243
+ * password cannot be helped by "send them a reset link", they need one
244
+ * set. Reporting true here would send the operator down the wrong path.
245
+ */
246
+ resolveUser(buildUser({ id: userId }));
247
+
248
+ const status: UserAuthenticationStatus =
249
+ await UserService.getAuthenticationStatus(userId);
250
+
251
+ expect(status.hasPassword).toBe(false);
252
+ });
253
+
254
+ test("isEmailVerified mirrors the column", async () => {
255
+ resolveUser(buildUser({ id: userId, isEmailVerified: true }));
256
+
257
+ const verified: UserAuthenticationStatus =
258
+ await UserService.getAuthenticationStatus(userId);
259
+ expect(verified.isEmailVerified).toBe(true);
260
+
261
+ resolveUser(buildUser({ id: userId, isEmailVerified: false }));
262
+
263
+ const unverified: UserAuthenticationStatus =
264
+ await UserService.getAuthenticationStatus(userId);
265
+ expect(unverified.isEmailVerified).toBe(false);
266
+ });
267
+
268
+ test("reads enableTwoFactorAuth, not the vestigial twoFactorAuthEnabled column", async () => {
269
+ /*
270
+ * THE SUBTLE ONE. `User` declares BOTH `enableTwoFactorAuth` and
271
+ * `twoFactorAuthEnabled`. Only `enableTwoFactorAuth` is the one login
272
+ * consults and the one the rest of the product writes;
273
+ * `twoFactorAuthEnabled` is a leftover that nothing maintains.
274
+ *
275
+ * This row is the disagreeing case: 2FA is genuinely ON, and the dead
276
+ * column says off. Reading the dead column would compile, would render,
277
+ * and would tell an operator "two-factor auth is disabled" about a user
278
+ * who cannot get in without their authenticator -- which is exactly the
279
+ * moment the operator is deciding whether to reset it.
280
+ */
281
+ resolveUser(
282
+ buildUser({
283
+ id: userId,
284
+ enableTwoFactorAuth: true,
285
+ twoFactorAuthEnabled: false,
286
+ }),
287
+ );
288
+
289
+ const status: UserAuthenticationStatus =
290
+ await UserService.getAuthenticationStatus(userId);
291
+
292
+ expect(status.isTwoFactorAuthEnabled).toBe(true);
293
+ });
294
+
295
+ test("does not report 2FA on just because the vestigial column is set", async () => {
296
+ /*
297
+ * The mirror of the case above, so the test cannot pass by hard-coding
298
+ * true: the dead column says on, the live one says off, and the answer
299
+ * has to follow the live one.
300
+ */
301
+ resolveUser(
302
+ buildUser({
303
+ id: userId,
304
+ enableTwoFactorAuth: false,
305
+ twoFactorAuthEnabled: true,
306
+ }),
307
+ );
308
+
309
+ const status: UserAuthenticationStatus =
310
+ await UserService.getAuthenticationStatus(userId);
311
+
312
+ expect(status.isTwoFactorAuthEnabled).toBe(false);
313
+ });
314
+
315
+ test("hasPendingPasswordResetLink is false when no token has ever been minted", async () => {
316
+ resolveUser(buildUser({ id: userId }));
317
+
318
+ const status: UserAuthenticationStatus =
319
+ await UserService.getAuthenticationStatus(userId);
320
+
321
+ expect(status.hasPendingPasswordResetLink).toBe(false);
322
+ });
323
+
324
+ test("hasPendingPasswordResetLink is false once the token has expired", async () => {
325
+ /*
326
+ * Nothing clears `resetPasswordToken` when it lapses -- the column keeps
327
+ * the last token until something overwrites it. Treating "column is set"
328
+ * as "link is pending" would therefore report a live link for every user
329
+ * who ever requested one, and /reset-password would refuse it.
330
+ */
331
+ resolveUser(
332
+ buildUser({
333
+ id: userId,
334
+ resetPasswordToken: "a-hashed-token",
335
+ resetPasswordExpires: OneUptimeDate.getSomeHoursAgo(1),
336
+ }),
337
+ );
338
+
339
+ const status: UserAuthenticationStatus =
340
+ await UserService.getAuthenticationStatus(userId);
341
+
342
+ expect(status.hasPendingPasswordResetLink).toBe(false);
343
+ });
344
+
345
+ test("hasPendingPasswordResetLink is false for a token with no expiry at all", async () => {
346
+ /*
347
+ * A token with a null expiry is not an eternal link -- /reset-password
348
+ * requires an unexpired expiry to redeem it, so a row in this shape has
349
+ * nothing redeemable on it.
350
+ */
351
+ resolveUser(
352
+ buildUser({
353
+ id: userId,
354
+ resetPasswordToken: "a-hashed-token",
355
+ }),
356
+ );
357
+
358
+ const status: UserAuthenticationStatus =
359
+ await UserService.getAuthenticationStatus(userId);
360
+
361
+ expect(status.hasPendingPasswordResetLink).toBe(false);
362
+ });
363
+
364
+ test("hasPendingPasswordResetLink is true for an unexpired token", async () => {
365
+ resolveUser(
366
+ buildUser({
367
+ id: userId,
368
+ resetPasswordToken: "a-hashed-token",
369
+ resetPasswordExpires: OneUptimeDate.getSomeHoursAfter(1),
370
+ }),
371
+ );
372
+
373
+ const status: UserAuthenticationStatus =
374
+ await UserService.getAuthenticationStatus(userId);
375
+
376
+ expect(status.hasPendingPasswordResetLink).toBe(true);
377
+ });
378
+
379
+ test("returns only the four booleans -- never the password digest itself", async () => {
380
+ /*
381
+ * The whole reason this is a DTO rather than a selected row: the caller
382
+ * is a master admin, whose props bypass column read permissions, so
383
+ * handing the model back would put every user's password digest (and the
384
+ * hash of their outstanding reset token) into a browser's network tab.
385
+ *
386
+ * Asserting the exact key set rather than "password is undefined" is
387
+ * deliberate -- a future field added to the row would otherwise ride
388
+ * along unnoticed.
389
+ */
390
+ const digest: string = "a-stored-scrypt-digest";
391
+
392
+ resolveUser(
393
+ buildUser({
394
+ id: userId,
395
+ password: new HashedString(digest, true),
396
+ resetPasswordToken: "a-hashed-token",
397
+ resetPasswordExpires: OneUptimeDate.getSomeHoursAfter(1),
398
+ }),
399
+ );
400
+
401
+ const status: UserAuthenticationStatus =
402
+ await UserService.getAuthenticationStatus(userId);
403
+
404
+ expect(Object.keys(status).sort()).toEqual([
405
+ "hasPassword",
406
+ "hasPendingPasswordResetLink",
407
+ "isEmailVerified",
408
+ "isTwoFactorAuthEnabled",
409
+ ]);
410
+
411
+ const serialized: string = JSON.stringify(status);
412
+ expect(serialized).not.toContain(digest);
413
+ expect(serialized).not.toContain("a-hashed-token");
414
+
415
+ for (const value of Object.values(status)) {
416
+ expect(typeof value).toBe("boolean");
417
+ }
418
+ });
419
+
420
+ test("selects exactly the columns the four booleans are derived from", async () => {
421
+ /*
422
+ * Pinned literally because both halves matter. Dropping a column here
423
+ * turns its boolean permanently false rather than raising anything --
424
+ * losing `enableTwoFactorAuth` would silently report 2FA off for
425
+ * everyone. Adding one widens what a root read pulls out of the row for
426
+ * no reason.
427
+ */
428
+ resolveUser(buildUser({ id: userId }));
429
+
430
+ await UserService.getAuthenticationStatus(userId);
431
+
432
+ const call: any = findOneBySpy.mock.calls[0][0];
433
+
434
+ expect(call.select).toEqual({
435
+ _id: true,
436
+ password: true,
437
+ isEmailVerified: true,
438
+ enableTwoFactorAuth: true,
439
+ resetPasswordToken: true,
440
+ resetPasswordExpires: true,
441
+ });
442
+
443
+ expect(call.query).toEqual({ _id: userId });
444
+ expect(call.props).toEqual({ isRoot: true });
445
+ });
446
+ });
447
+
448
+ describe("setPassword", () => {
449
+ const VALID_PASSWORD: string = "a-perfectly-fine-password";
450
+
451
+ type ExpectRejectedBeforeAnyQueryFunction = (
452
+ password: string,
453
+ ) => Promise<void>;
454
+
455
+ /*
456
+ * Validating FIRST is the point of the ordering, not an accident of it.
457
+ * Every OneUptime password form enforces the length rule in the browser;
458
+ * an admin API is precisely the caller that is not a browser. A guard
459
+ * placed after the read would still reject the value, but only after the
460
+ * request had already spent a query -- and, more importantly, the shape
461
+ * "read the row, then decide" is the one that invites a later edit to slip
462
+ * an update in between.
463
+ */
464
+ const expectRejectedBeforeAnyQuery: ExpectRejectedBeforeAnyQueryFunction =
465
+ async (password: string): Promise<void> => {
466
+ // A row is available on purpose: nothing may go looking for it.
467
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
468
+
469
+ await expect(
470
+ UserService.setPassword({ userId: userId, password: password }),
471
+ ).rejects.toThrow(BadDataException);
472
+
473
+ expect(findOneBySpy).not.toHaveBeenCalled();
474
+ expect(updateOneByIdSpy).not.toHaveBeenCalled();
475
+ };
476
+
477
+ test("rejects a password shorter than the minimum, before touching the database", async () => {
478
+ await expectRejectedBeforeAnyQuery("short");
479
+ });
480
+
481
+ test("rejects a password that is only whitespace, before touching the database", async () => {
482
+ /*
483
+ * Long enough to pass the length rule, and still not a password. It is
484
+ * rejected rather than trimmed on purpose -- trimming would store
485
+ * something other than what was typed.
486
+ */
487
+ await expectRejectedBeforeAnyQuery(" ");
488
+ });
489
+
490
+ test("rejects an empty password, before touching the database", async () => {
491
+ await expectRejectedBeforeAnyQuery("");
492
+ });
493
+
494
+ test("accepts a password of exactly the minimum length", async () => {
495
+ /*
496
+ * Guards the boundary from the off-by-one direction: a `<=` here would
497
+ * start rejecting passwords that every existing OneUptime form accepts.
498
+ */
499
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
500
+
501
+ await UserService.setPassword({ userId: userId, password: "abcdef" });
502
+
503
+ expect(updateOneByIdSpy).toHaveBeenCalledTimes(1);
504
+ });
505
+
506
+ test("throws NotFoundException for a user that does not exist, and updates nothing", async () => {
507
+ resolveUser(null);
508
+
509
+ await expect(
510
+ UserService.setPassword({
511
+ userId: userId,
512
+ password: VALID_PASSWORD,
513
+ }),
514
+ ).rejects.toThrow(NotFoundException);
515
+
516
+ expect(updateOneByIdSpy).not.toHaveBeenCalled();
517
+ });
518
+
519
+ test("hands the write path the PLAINTEXT wrapped in an unhashed HashedString", async () => {
520
+ /*
521
+ * THE CENTRAL ASSERTION OF THIS FILE.
522
+ *
523
+ * `sanitizeCreateOrUpdate` is what mints a fresh per-user salt and runs
524
+ * scrypt, and it only does that for a HashedString whose isValueHashed()
525
+ * is false. Passing a bare string, or "helpfully" pre-hashing here,
526
+ * strands the row: the stored digest and the row's salt stop agreeing
527
+ * with each other.
528
+ *
529
+ * Nothing about that failure is visible at the time. The update commits,
530
+ * the admin page says the password was set, the operator tells the user
531
+ * their new password -- and the account is locked out at the next login
532
+ * attempt, with no error anywhere pointing back at this line.
533
+ */
534
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
535
+
536
+ await UserService.setPassword({
537
+ userId: userId,
538
+ password: VALID_PASSWORD,
539
+ });
540
+
541
+ const call: any = updateOneByIdSpy.mock.calls[0][0];
542
+ const password: any = call.data.password;
543
+
544
+ expect(password).toBeInstanceOf(HashedString);
545
+ expect(password.isValueHashed()).toBe(false);
546
+ expect(password.toString()).toBe(VALID_PASSWORD);
547
+ });
548
+
549
+ test("clears any outstanding reset link in the SAME update", async () => {
550
+ /*
551
+ * A link mailed five minutes before the admin intervened must not still
552
+ * be redeemable afterwards -- whoever holds it could set the password
553
+ * again, undoing the intervention. Doing it as a second statement would
554
+ * leave a window where the new password is live and the old link still
555
+ * works; doing it in the same update means there is no such window.
556
+ */
557
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
558
+
559
+ await UserService.setPassword({
560
+ userId: userId,
561
+ password: VALID_PASSWORD,
562
+ });
563
+
564
+ expect(updateOneByIdSpy).toHaveBeenCalledTimes(1);
565
+
566
+ const data: any = updateOneByIdSpy.mock.calls[0][0].data;
567
+
568
+ // Present as keys, or the column is left untouched rather than cleared.
569
+ expect(Object.keys(data)).toContain("resetPasswordToken");
570
+ expect(Object.keys(data)).toContain("resetPasswordExpires");
571
+
572
+ expect(data.resetPasswordToken).toBeFalsy();
573
+ expect(data.resetPasswordExpires).toBeFalsy();
574
+ });
575
+
576
+ test("updates the row that was found, as root, WITHOUT ignoring hooks", async () => {
577
+ /*
578
+ * `ignoreHooks: true` would make this update look identical and behave
579
+ * completely differently: `onUpdateSuccess` is what revokes every session
580
+ * the user has open and mails them "Password Changed.". Skipping it would
581
+ * leave an attacker's stolen session alive across the very password
582
+ * change meant to kill it, and tell the user nothing.
583
+ */
584
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
585
+
586
+ await UserService.setPassword({
587
+ userId: userId,
588
+ password: VALID_PASSWORD,
589
+ });
590
+
591
+ const call: any = updateOneByIdSpy.mock.calls[0][0];
592
+
593
+ expect(call.id.toString()).toBe(userId.toString());
594
+ expect(call.props.isRoot).toBe(true);
595
+ expect(call.props.ignoreHooks).toBeFalsy();
596
+ });
597
+
598
+ test("does not revoke sessions or send mail itself", async () => {
599
+ /*
600
+ * The hook already does both. Doing them here as well would not be
601
+ * harmlessly redundant -- the user would receive two identical
602
+ * "Password Changed." emails from one admin action, which reads as a
603
+ * second, unexplained change to their account.
604
+ */
605
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
606
+
607
+ await UserService.setPassword({
608
+ userId: userId,
609
+ password: VALID_PASSWORD,
610
+ });
611
+
612
+ expect(revokeSessionsSpy).not.toHaveBeenCalled();
613
+ expect(sendMailSpy).not.toHaveBeenCalled();
614
+ });
615
+ });
616
+
617
+ describe("sendPasswordResetLink", () => {
618
+ type SentLinkFunction = () => string;
619
+
620
+ // The URL the operator's click actually put in the user's inbox.
621
+ const sentLink: SentLinkFunction = (): string => {
622
+ const mail: any = sendMailSpy.mock.calls[0][0];
623
+ return mail.vars.tokenVerifyUrl as string;
624
+ };
625
+
626
+ type StoredTokenFunction = () => string;
627
+
628
+ // What the row now holds in resetPasswordToken.
629
+ const storedToken: StoredTokenFunction = (): string => {
630
+ return updateOneByIdSpy.mock.calls[0][0].data
631
+ .resetPasswordToken as string;
632
+ };
633
+
634
+ test("throws NotFoundException for a user that does not exist, and sends no mail", async () => {
635
+ resolveUser(null);
636
+
637
+ await expect(
638
+ UserService.sendPasswordResetLink({ userId: userId }),
639
+ ).rejects.toThrow(NotFoundException);
640
+
641
+ expect(updateOneByIdSpy).not.toHaveBeenCalled();
642
+ expect(sendMailSpy).not.toHaveBeenCalled();
643
+ });
644
+
645
+ test("stores a hash of the token and mails the token itself", async () => {
646
+ /*
647
+ * The property that makes a leaked database row worthless. What is
648
+ * written to `resetPasswordToken` must NOT be the string in the email --
649
+ * if it were, anyone with read access to the User table (a backup, a
650
+ * replica, a support query) could mint themselves a working reset link
651
+ * for any account without touching the mail system at all.
652
+ *
653
+ * Both halves are asserted, because either alone is satisfiable by a
654
+ * bug: "they differ" alone passes if the stored value is unrelated
655
+ * garbage that /reset-password could never match, and "it hashes to the
656
+ * stored value" is only meaningful once we know they are not the same
657
+ * string to begin with.
658
+ *
659
+ * The hash is unsalted on purpose -- /reset-password looks the row up BY
660
+ * this digest, which a per-row salt would make impossible.
661
+ */
662
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
663
+
664
+ await UserService.sendPasswordResetLink({ userId: userId });
665
+
666
+ const stored: string = storedToken();
667
+ const tokenInEmail: string = sentLink().split("/reset-password/")[1]!;
668
+
669
+ expect(tokenInEmail).toBeTruthy();
670
+ expect(stored).toBeTruthy();
671
+ expect(stored).not.toBe(tokenInEmail);
672
+
673
+ expect(await HashedString.hashValue(tokenInEmail, EncryptionSecret)).toBe(
674
+ stored,
675
+ );
676
+ });
677
+
678
+ test("mints a different token on every send", async () => {
679
+ /*
680
+ * A token derived from anything stable about the user -- their id, their
681
+ * email -- would make yesterday's expired link valid again the moment a
682
+ * new one is issued.
683
+ */
684
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
685
+
686
+ await UserService.sendPasswordResetLink({ userId: userId });
687
+ await UserService.sendPasswordResetLink({ userId: userId });
688
+
689
+ const first: string = updateOneByIdSpy.mock.calls[0][0].data
690
+ .resetPasswordToken as string;
691
+ const second: string = updateOneByIdSpy.mock.calls[1][0].data
692
+ .resetPasswordToken as string;
693
+
694
+ expect(first).not.toBe(second);
695
+ });
696
+
697
+ test("the link points at the ordinary /accounts/reset-password page", async () => {
698
+ /*
699
+ * There is deliberately no admin-specific redemption route: the link an
700
+ * operator sends is redeemed by exactly the page the public
701
+ * /forgot-password flow uses. A different path here would mean a second
702
+ * code path capable of setting passwords, which is the thing this feature
703
+ * was careful not to create.
704
+ */
705
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
706
+
707
+ await UserService.sendPasswordResetLink({ userId: userId });
708
+
709
+ const link: string = sentLink();
710
+ const token: string = link.split("/reset-password/")[1]!;
711
+
712
+ expect(link).toBe(`${EXPECTED_ORIGIN}/accounts/reset-password/${token}`);
713
+ });
714
+
715
+ test("expires the link roughly 24 hours out", async () => {
716
+ /*
717
+ * In the future, or the link is dead on arrival and the operator is told
718
+ * it was sent. Bounded above, or a mis-set expiry turns one admin action
719
+ * into a password-reset link that stays redeemable for months.
720
+ */
721
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
722
+
723
+ const before: Date = OneUptimeDate.getCurrentDate();
724
+
725
+ await UserService.sendPasswordResetLink({ userId: userId });
726
+
727
+ const expires: Date = updateOneByIdSpy.mock.calls[0][0].data
728
+ .resetPasswordExpires as Date;
729
+
730
+ expect(expires).toBeInstanceOf(Date);
731
+ expect(OneUptimeDate.hasExpired(expires)).toBe(false);
732
+
733
+ const hoursOut: number = OneUptimeDate.getHoursBetweenTwoDates(
734
+ before,
735
+ expires,
736
+ );
737
+
738
+ expect(hoursOut).toBeGreaterThanOrEqual(23);
739
+ expect(hoursOut).toBeLessThanOrEqual(25);
740
+ });
741
+
742
+ test("writes the token as root against the requested user", async () => {
743
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
744
+
745
+ await UserService.sendPasswordResetLink({ userId: userId });
746
+
747
+ const call: any = updateOneByIdSpy.mock.calls[0][0];
748
+
749
+ expect(call.id.toString()).toBe(userId.toString());
750
+ expect(call.props.isRoot).toBe(true);
751
+ });
752
+
753
+ test("sends the ForgotPassword template to the user's own address", async () => {
754
+ /*
755
+ * The template is what renders the link into something clickable; a
756
+ * template type that does not reference `tokenVerifyUrl` would mail a
757
+ * cheerful message with no link in it, and this method would still
758
+ * report success.
759
+ */
760
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
761
+
762
+ await UserService.sendPasswordResetLink({ userId: userId });
763
+
764
+ const mail: any = sendMailSpy.mock.calls[0][0];
765
+
766
+ expect(mail.templateType).toBe(EmailTemplateType.ForgotPassword);
767
+ expect(mail.toEmail.toString()).toBe("user@example.com");
768
+
769
+ // Routeless URLs render with a trailing slash; the template links it as-is.
770
+ expect(mail.vars.homeURL).toBe(`${EXPECTED_ORIGIN}/`);
771
+ });
772
+
773
+ test("returns the address the link went to", async () => {
774
+ /*
775
+ * The operator pressed a button on a page identified by user id, not by
776
+ * email. Returning the address is what lets the UI say WHERE the link
777
+ * went, so a link sent to a stale address is noticed immediately rather
778
+ * than becoming "the user says they never got it".
779
+ */
780
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
781
+
782
+ const email: Email = await UserService.sendPasswordResetLink({
783
+ userId: userId,
784
+ });
785
+
786
+ expect(email.toString()).toBe("user@example.com");
787
+ });
788
+
789
+ test("a mail failure propagates instead of being reported as sent", async () => {
790
+ /*
791
+ * Most MailService calls in UserService are deliberately not awaited --
792
+ * a signup should not fail because SMTP is down. This one is the
793
+ * exception, and the exception is the whole point: a human is standing in
794
+ * front of the page waiting to tell someone "check your email".
795
+ * Swallowing the error here leaves them waiting for a link that was never
796
+ * sent.
797
+ */
798
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
799
+
800
+ sendMailSpy.mockImplementation(async (): Promise<never> => {
801
+ throw new Error("SMTP server is unreachable");
802
+ });
803
+
804
+ await expect(
805
+ UserService.sendPasswordResetLink({ userId: userId }),
806
+ ).rejects.toThrow("SMTP server is unreachable");
807
+ });
808
+
809
+ test("treats a REJECTED mail send as a failure, not a delivery", async () => {
810
+ /*
811
+ * The catch-shaped failure: the notification service was unreachable, so
812
+ * the HTTP client threw. This is the rarer of the two, and it is the only
813
+ * one a bare try/catch would have caught -- see the sibling test below
814
+ * for the one that matters more.
815
+ */
816
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
817
+
818
+ sendMailSpy.mockImplementation(async (): Promise<never> => {
819
+ throw new Error("connect ECONNREFUSED");
820
+ });
821
+
822
+ await expect(
823
+ UserService.sendPasswordResetLink({ userId: userId }),
824
+ ).rejects.toThrow("connect ECONNREFUSED");
825
+ });
826
+
827
+ test("treats a RESOLVED HTTPErrorResponse as a failure, not a delivery", async () => {
828
+ /*
829
+ * THE ONE THAT ACTUALLY BITES. MailService.sendMail is an HTTP call, and
830
+ * this codebase's API client only REJECTS when no response came back at
831
+ * all. A response that says no -- 400 "Global SMTP Config not found" on
832
+ * a fresh self-hosted instance, an SMTP auth failure, a rejected
833
+ * recipient -- comes back as a RESOLVED HTTPErrorResponse. And because
834
+ * HTTPErrorResponse extends HTTPResponse, it satisfies sendMail's
835
+ * declared return type, so nothing about it looks wrong to the compiler
836
+ * either.
837
+ *
838
+ * Without an explicit instanceof check, the awaited call returns
839
+ * normally, the rollback never runs, and the operator is told the link
840
+ * was sent while a live 24 hour token sits on a row nobody was emailed
841
+ * about. That is the exact state this method exists to avoid, reached by
842
+ * the most ordinary failure there is.
843
+ */
844
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
845
+
846
+ sendMailSpy.mockImplementation(async (): Promise<any> => {
847
+ return new HTTPErrorResponse(
848
+ 400,
849
+ { message: "Global SMTP Config not found" },
850
+ {},
851
+ );
852
+ });
853
+
854
+ await expect(
855
+ UserService.sendPasswordResetLink({ userId: userId }),
856
+ ).rejects.toThrow("Global SMTP Config not found");
857
+
858
+ // ...and the token it had already armed is taken back off the row.
859
+ expect(updateOneByIdSpy).toHaveBeenCalledTimes(2);
860
+ expect(
861
+ updateOneByIdSpy.mock.calls[1]![0].data.resetPasswordToken,
862
+ ).toBeFalsy();
863
+ expect(
864
+ updateOneByIdSpy.mock.calls[1]![0].data.resetPasswordExpires,
865
+ ).toBeFalsy();
866
+ });
867
+
868
+ test("takes the token back off the row when the mail could not be sent", async () => {
869
+ /*
870
+ * The token is written BEFORE the send, because the link in the email has
871
+ * to be redeemable the moment it lands. That ordering means a failed send
872
+ * would otherwise strand a live 24 hour token on a row nobody was ever
873
+ * told about -- and getAuthenticationStatus would then report "reset link
874
+ * pending" on the same screen as the error saying it could not be sent.
875
+ *
876
+ * So the send is unwound: the second update clears both columns, and the
877
+ * page and the operator end up telling the same story.
878
+ */
879
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
880
+
881
+ sendMailSpy.mockImplementation(async (): Promise<never> => {
882
+ throw new Error("SMTP server is unreachable");
883
+ });
884
+
885
+ await expect(
886
+ UserService.sendPasswordResetLink({ userId: userId }),
887
+ ).rejects.toThrow("SMTP server is unreachable");
888
+
889
+ expect(updateOneByIdSpy).toHaveBeenCalledTimes(2);
890
+
891
+ const clearingUpdate: any = updateOneByIdSpy.mock.calls[1]![0];
892
+
893
+ expect(clearingUpdate.id.toString()).toBe(userId.toString());
894
+ expect(clearingUpdate.data.resetPasswordToken).toBeFalsy();
895
+ expect(clearingUpdate.data.resetPasswordExpires).toBeFalsy();
896
+ expect(clearingUpdate.props.isRoot).toBe(true);
897
+
898
+ /*
899
+ * The columns are cleared, not merely overwritten with something else:
900
+ * a non-null token here would still read as a pending link.
901
+ */
902
+ expect("resetPasswordToken" in clearingUpdate.data).toBe(true);
903
+ expect("resetPasswordExpires" in clearingUpdate.data).toBe(true);
904
+ });
905
+
906
+ test("still reports the mail failure even if the token cannot be cleared", async () => {
907
+ /*
908
+ * The cleanup is best-effort and must never replace the error worth
909
+ * reporting. If it could, an SMTP outage plus a database blip would
910
+ * surface to the operator as a database error about a write they never
911
+ * asked for -- and the orphaned token expires by itself regardless.
912
+ */
913
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
914
+
915
+ sendMailSpy.mockImplementation(async (): Promise<never> => {
916
+ throw new Error("SMTP server is unreachable");
917
+ });
918
+
919
+ updateOneByIdSpy.mockImplementation(
920
+ async (update: any): Promise<void> => {
921
+ if (update.data.resetPasswordToken === null) {
922
+ throw new Error("Database is unavailable");
923
+ }
924
+
925
+ return undefined;
926
+ },
927
+ );
928
+
929
+ await expect(
930
+ UserService.sendPasswordResetLink({ userId: userId }),
931
+ ).rejects.toThrow("SMTP server is unreachable");
932
+ });
933
+
934
+ test("does not touch the token again when the mail was sent", async () => {
935
+ /*
936
+ * The mirror of the unwind: on the happy path there is exactly ONE write,
937
+ * the one that armed the link. A second update here would clear the token
938
+ * the user is about to click.
939
+ */
940
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
941
+
942
+ await UserService.sendPasswordResetLink({ userId: userId });
943
+
944
+ expect(updateOneByIdSpy).toHaveBeenCalledTimes(1);
945
+ expect(
946
+ updateOneByIdSpy.mock.calls[0]![0].data.resetPasswordToken,
947
+ ).toBeTruthy();
948
+ });
949
+
950
+ test("does not resolve before the mail send settles", async () => {
951
+ /*
952
+ * The failure above can only propagate if the send is awaited. This pins
953
+ * the awaiting directly, so a refactor to fire-and-forget is caught even
954
+ * if it happens to keep rejections visible some other way.
955
+ */
956
+ resolveUser(buildUser({ id: userId, email: "user@example.com" }));
957
+
958
+ let mailCompleted: boolean = false;
959
+
960
+ sendMailSpy.mockImplementation(async (): Promise<any> => {
961
+ await new Promise<void>((resolve: () => void) => {
962
+ setTimeout(resolve, 10);
963
+ });
964
+ mailCompleted = true;
965
+ return {};
966
+ });
967
+
968
+ await UserService.sendPasswordResetLink({ userId: userId });
969
+
970
+ expect(mailCompleted).toBe(true);
971
+ });
972
+ });
973
+ });