@oneuptime/common 14.0.3 → 14.0.5

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 (617) hide show
  1. package/Models/DatabaseModels/Alert.ts +55 -0
  2. package/Models/DatabaseModels/DatabaseServer.ts +1650 -0
  3. package/Models/DatabaseModels/DatabaseServerEndpoint.ts +540 -0
  4. package/Models/DatabaseModels/DatabaseServerFeed.ts +625 -0
  5. package/Models/DatabaseModels/DatabaseServerLabelRule.ts +514 -0
  6. package/Models/DatabaseModels/DatabaseServerOwnerRule.ts +596 -0
  7. package/Models/DatabaseModels/DatabaseServerOwnerTeam.ts +491 -0
  8. package/Models/DatabaseModels/DatabaseServerOwnerUser.ts +490 -0
  9. package/Models/DatabaseModels/Incident.ts +55 -0
  10. package/Models/DatabaseModels/Index.ts +16 -0
  11. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +26 -0
  12. package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
  13. package/Models/DatabaseModels/TelemetryException.ts +2 -0
  14. package/Models/DatabaseModels/UserProjectSsoConsent.ts +146 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.ts +673 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.ts +51 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  18. package/Server/Middleware/MultipartFormData.ts +1 -1
  19. package/Server/Middleware/TelemetryIngest.ts +15 -8
  20. package/Server/Services/AlertReminderRuleService.ts +100 -24
  21. package/Server/Services/DatabaseServerEndpointService.ts +895 -0
  22. package/Server/Services/DatabaseServerFeedService.ts +128 -0
  23. package/Server/Services/DatabaseServerLabelRuleEngineService.ts +340 -0
  24. package/Server/Services/DatabaseServerLabelRuleService.ts +14 -0
  25. package/Server/Services/DatabaseServerOwnerRuleEngineService.ts +425 -0
  26. package/Server/Services/DatabaseServerOwnerRuleService.ts +14 -0
  27. package/Server/Services/DatabaseServerOwnerTeamService.ts +180 -0
  28. package/Server/Services/DatabaseServerOwnerUserService.ts +173 -0
  29. package/Server/Services/DatabaseServerService.ts +4546 -0
  30. package/Server/Services/DatabaseService.ts +14 -8
  31. package/Server/Services/DockerResourceService.ts +43 -2
  32. package/Server/Services/IncidentReminderRuleService.ts +103 -23
  33. package/Server/Services/Index.ts +16 -0
  34. package/Server/Services/InventoryItemService.ts +113 -5
  35. package/Server/Services/IoTDeviceService.ts +145 -37
  36. package/Server/Services/OpenTelemetryIngestService.ts +19 -0
  37. package/Server/Services/PodmanResourceService.ts +43 -2
  38. package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +107 -23
  39. package/Server/Services/ServiceService.ts +1 -1
  40. package/Server/Services/TelemetryUsageBillingService.ts +29 -2
  41. package/Server/Services/UserProjectSsoConsentService.ts +74 -0
  42. package/Server/Services/UserService.ts +14 -1
  43. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +18 -0
  44. package/Server/Types/Database/QueryHelper.ts +30 -1
  45. package/Server/Utils/AI/Toolbox/ResourceTools.ts +69 -1
  46. package/Server/Utils/Database/AffectedResourceRelations.ts +6 -0
  47. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +188 -6
  48. package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
  49. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +2262 -755
  50. package/Server/Utils/Monitor/MonitorIncident.ts +28 -1
  51. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +268 -6
  52. package/Server/Utils/Monitor/MonitorResource.ts +47 -11
  53. package/Server/Utils/Monitor/MonitorResourceContext.ts +1 -0
  54. package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +239 -21
  55. package/Server/Utils/Monitor/PerSeriesResolutionRootCause.ts +43 -0
  56. package/Server/Utils/Monitor/SeriesResourceLabels.ts +291 -0
  57. package/Server/Utils/Monitor/SeriesResourceLinker.ts +111 -12
  58. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
  59. package/Server/Utils/StartServer.ts +26 -6
  60. package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
  61. package/Server/Utils/Telemetry/DatabaseEndpointDiscovery.ts +688 -0
  62. package/Server/Utils/Telemetry/EntityRegistry.ts +5 -1
  63. package/Server/Utils/Telemetry/LogExceptionExtractor.ts +18 -1
  64. package/Server/Utils/Telemetry/ResourceEntityFilter.ts +175 -12
  65. package/Server/Utils/Telemetry/ResourceFacetResolver.ts +12 -0
  66. package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +606 -36
  67. package/Server/Utils/Telemetry/Telemetry.ts +16 -0
  68. package/Server/Utils/Telemetry/TelemetryEntity.ts +22 -22
  69. package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +16 -10
  70. package/Tests/App/Accounts/SignedInRedirect.test.tsx +241 -0
  71. package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +221 -4
  72. package/Tests/App/Dashboard/AIInsightsResourcePageContext.test.ts +42 -0
  73. package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +100 -0
  74. package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +86 -0
  75. package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +2 -0
  76. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +19 -0
  77. package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +14 -0
  78. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +26 -1
  79. package/Tests/App/Dashboard/DashboardAppSsoError.test.tsx +501 -0
  80. package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +64 -1
  81. package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +178 -18
  82. package/Tests/App/Dashboard/DashboardMasterPageSsoRedirect.test.tsx +444 -0
  83. package/Tests/App/Dashboard/DashboardNavBarForeignHiddenRule.test.tsx +573 -0
  84. package/Tests/App/Dashboard/DatabaseChartAxes.test.tsx +431 -0
  85. package/Tests/App/Dashboard/DatabaseContainerDetailBadge.test.tsx +249 -0
  86. package/Tests/App/Dashboard/DatabaseDashboardE2EFixes.test.ts +681 -0
  87. package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +1801 -0
  88. package/Tests/App/Dashboard/DatabaseFleetSummaryRefresh.test.tsx +280 -0
  89. package/Tests/App/Dashboard/DatabaseFormHelpers.test.tsx +321 -0
  90. package/Tests/App/Dashboard/DatabaseMetricMonitorLink.test.tsx +795 -0
  91. package/Tests/App/Dashboard/DatabaseOverviewHeader.test.tsx +580 -0
  92. package/Tests/App/Dashboard/DatabaseRecommendationsEngineMetrics.test.ts +270 -0
  93. package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +1486 -0
  94. package/Tests/App/Dashboard/DatabaseServerEngineMetricsFilter.test.ts +223 -0
  95. package/Tests/App/Dashboard/DatabaseServerPresentation.test.ts +435 -0
  96. package/Tests/App/Dashboard/DatabaseServerSummary.test.ts +186 -0
  97. package/Tests/App/Dashboard/DatabaseServerTelemetryQueries.test.ts +1553 -0
  98. package/Tests/App/Dashboard/DatabaseTableTruncation.test.tsx +326 -0
  99. package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +512 -0
  100. package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +774 -0
  101. package/Tests/App/Dashboard/DatabaseViewLayout.test.tsx +233 -0
  102. package/Tests/App/Dashboard/DatabaseWorkloadBadge.test.tsx +972 -0
  103. package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +5 -0
  104. package/Tests/App/Dashboard/DiscoveryReviewUnnamedHostHint.test.tsx +1061 -0
  105. package/Tests/App/Dashboard/EventOverlayScope.test.ts +147 -0
  106. package/Tests/App/Dashboard/EventOverlayScopeHook.test.tsx +1 -0
  107. package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +1 -0
  108. package/Tests/App/Dashboard/MetricsViewerDrillDown.test.tsx +310 -0
  109. package/Tests/App/Dashboard/MetricsViewerEntityScopedRows.test.tsx +495 -0
  110. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +132 -1
  111. package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +5 -0
  112. package/Tests/App/Dashboard/ProductOrientation.test.tsx +4 -3
  113. package/Tests/App/Dashboard/RecommendationsLoadedContext.test.tsx +349 -0
  114. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +62 -0
  115. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
  116. package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +14 -0
  117. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +2 -0
  118. package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +1085 -0
  119. package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +10 -0
  120. package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +2 -1
  121. package/Tests/App/StatusPage/StatusPageHeaderForeignHiddenRule.test.tsx +284 -0
  122. package/Tests/ClassStrings.ts +178 -0
  123. package/Tests/Fixtures/MobilePasskeyUser.json +1 -2
  124. package/Tests/ForeignHiddenRuleGuard.ts +2152 -0
  125. package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +2250 -0
  126. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +24 -5
  127. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  128. package/Tests/RenderedMarkup.ts +518 -0
  129. package/Tests/ResponsiveVisibility.test.ts +490 -4
  130. package/Tests/ResponsiveVisibility.ts +505 -52
  131. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  132. package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +541 -0
  133. package/Tests/Server/Infrastructure/Postgres/AddUserProjectSsoConsentMigration.test.ts +234 -0
  134. package/Tests/Server/Services/ContainerSnapshotUpsertPostgres.test.ts +319 -0
  135. package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +13 -0
  136. package/Tests/Server/Services/DatabaseServerEndpointService.test.ts +2033 -0
  137. package/Tests/Server/Services/DatabaseServerFeedAndOwnerServices.test.ts +529 -0
  138. package/Tests/Server/Services/DatabaseServerLifecycle.test.ts +3302 -0
  139. package/Tests/Server/Services/DatabaseServerRegistries.test.ts +603 -0
  140. package/Tests/Server/Services/DatabaseServerRuleEngines.test.ts +754 -0
  141. package/Tests/Server/Services/DatabaseServerService.test.ts +3558 -0
  142. package/Tests/Server/Services/DatabaseServerSqlPostgres.test.ts +2045 -0
  143. package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedPostgres.test.ts +362 -0
  144. package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedReply.test.ts +210 -0
  145. package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +18 -0
  146. package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +2 -0
  147. package/Tests/Server/Services/IncomingCallPolicyEscalationRuleTarget.test.ts +225 -0
  148. package/Tests/Server/Services/InventoryItemDisplayName.test.ts +280 -2
  149. package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +8 -2
  150. package/Tests/Server/Services/IoTDeviceLatestMetricsPostgres.test.ts +689 -0
  151. package/Tests/Server/Services/IoTDeviceService.test.ts +379 -0
  152. package/Tests/Server/Services/LatestMetricsValuesShape.test.ts +360 -0
  153. package/Tests/Server/Services/LlmModelPriceService.test.ts +402 -0
  154. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +7 -1
  155. package/Tests/Server/Services/OwnerRowUniqueness.test.ts +61 -9
  156. package/Tests/Server/Services/ReminderRuleLookupPostgres.test.ts +2250 -0
  157. package/Tests/Server/Services/ReminderRuleRefreshOpenSubjectsPaging.test.ts +653 -0
  158. package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +68 -20
  159. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
  160. package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +9 -0
  161. package/Tests/Server/Services/UserProjectSsoConsentPostgres.test.ts +153 -0
  162. package/Tests/Server/Services/UserProjectSsoConsentService.test.ts +192 -0
  163. package/Tests/Server/Services/UserServiceFirstMasterAdminElection.test.ts +71 -0
  164. package/Tests/Server/Services/UserSignupIdTakeoverPostgres.test.ts +238 -0
  165. package/Tests/Server/Services/WorkspaceNotificationSummaryHelpers.test.ts +592 -0
  166. package/Tests/Server/Types/Billing/PayAsYouGoMeteredAuthorization.test.ts +3 -0
  167. package/Tests/Server/Types/Database/EventOverlayScopePostgres.test.ts +1 -0
  168. package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +11 -0
  169. package/Tests/Server/Types/Database/Permissions/InfrastructureOwnershipScope.test.ts +8 -0
  170. package/Tests/Server/Types/Database/QueryHelperBooleanForCriteriaBackedRule.test.ts +1094 -0
  171. package/Tests/Server/Utils/AI/ResourceTools.test.ts +134 -0
  172. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +41 -0
  173. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +279 -9
  174. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaDisplayContext.test.ts +933 -0
  175. package/Tests/Server/Utils/Monitor/DatabaseMaintenanceSuppression.test.ts +582 -0
  176. package/Tests/Server/Utils/Monitor/DatabaseServerMonitorLinking.test.ts +753 -0
  177. package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +1 -0
  178. package/Tests/Server/Utils/Monitor/MonitorAlertCriteriaReferences.test.ts +1 -0
  179. package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +119 -0
  180. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +60 -25
  181. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorAffectedResourceEdgeCases.test.ts +1719 -0
  182. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesAffectedResources.test.ts +1447 -0
  183. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesRatioEmail.test.ts +352 -0
  184. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformMetricUnits.test.ts +717 -0
  185. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformRawScan.test.ts +2125 -0
  186. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformSeriesAffectedResources.test.ts +1288 -0
  187. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +1 -0
  188. package/Tests/Server/Utils/Monitor/MonitorIncidentCriteriaReferences.test.ts +1 -0
  189. package/Tests/Server/Utils/Monitor/MonitorIncidentMemberRoleMembership.test.ts +1 -0
  190. package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +88 -0
  191. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +205 -0
  192. package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +62 -0
  193. package/Tests/Server/Utils/Monitor/MonitorResourceDatabaseMaintenance.test.ts +803 -0
  194. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +133 -3
  195. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +1 -0
  196. package/Tests/Server/Utils/Monitor/PerSeriesRecoveryResolution.test.ts +472 -1
  197. package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1 -0
  198. package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +236 -2
  199. package/Tests/Server/Utils/SeriesResourceLabels.test.ts +70 -0
  200. package/Tests/Server/Utils/StartServerProtobufContentType.test.ts +54 -0
  201. package/Tests/Server/Utils/Telemetry/DatabaseEndpointDiscovery.test.ts +1895 -0
  202. package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +7 -0
  203. package/Tests/Server/Utils/Telemetry/LogExceptionExtractorSeverityGate.test.ts +90 -0
  204. package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +570 -0
  205. package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +97 -2
  206. package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +1337 -0
  207. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +295 -0
  208. package/Tests/Types/AI/AIResourceContext.test.ts +30 -0
  209. package/Tests/Types/DatabaseServer/DatabaseContainerClassifier.test.ts +3644 -0
  210. package/Tests/Types/DatabaseServer/DatabaseContainerCommand.test.ts +340 -0
  211. package/Tests/Types/DatabaseServer/DatabaseContainerCommandCorpus.ts +826 -0
  212. package/Tests/Types/DatabaseServer/DatabaseContainerCommandPostgres.test.ts +150 -0
  213. package/Tests/Types/DatabaseServer/DatabaseEndpoint.test.ts +2657 -0
  214. package/Tests/Types/DatabaseServer/DatabaseServerDiscoverySource.test.ts +64 -0
  215. package/Tests/Types/DatabaseServer/DatabaseServerEntityKeys.test.ts +952 -0
  216. package/Tests/Types/DatabaseServer/DatabaseServerMetricCatalog.test.ts +1161 -0
  217. package/Tests/Types/DatabaseServer/DatabaseSystem.test.ts +1514 -0
  218. package/Tests/Types/DatabaseServer/DatabaseTelemetryResolver.test.ts +1558 -0
  219. package/Tests/Types/Monitor/CephAlertTemplates.test.ts +255 -6
  220. package/Tests/Types/Monitor/DatabaseAlertTemplates.test.ts +2254 -0
  221. package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +298 -0
  222. package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +271 -0
  223. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +253 -9
  224. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +13 -5
  225. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +4 -2
  226. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +111 -2
  227. package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +61 -0
  228. package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +114 -0
  229. package/Tests/Types/Monitor/Utils/KubernetesAgentEmittedMetrics.ts +181 -0
  230. package/Tests/Types/NetworkDevice/DiscoveredHostNamingStatus.test.ts +401 -0
  231. package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +4 -1
  232. package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +24 -2
  233. package/Tests/UI/Components/Card.test.tsx +93 -2
  234. package/Tests/UI/Components/FeedOptions.test.ts +6 -0
  235. package/Tests/UI/Components/FeedOptionsButton.test.tsx +8 -1
  236. package/Tests/UI/Components/ForeignHiddenRuleResilience.test.tsx +1147 -0
  237. package/Tests/UI/Components/HeaderRightRail.test.tsx +41 -1
  238. package/Tests/UI/Components/LogsEntityNames.test.ts +16 -1
  239. package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +7 -3
  240. package/Tests/UI/Components/ResourceFacetConfigs.test.ts +2 -1
  241. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  242. package/Tests/UI/Components/SrOnlyForeignRule.test.tsx +994 -0
  243. package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +34 -1
  244. package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +4 -1
  245. package/Tests/UI/ForeignHiddenRuleGuard.test.ts +1951 -0
  246. package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +19 -1
  247. package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +19 -1
  248. package/Tests/UI/TailwindPlayCdnForeignHiddenRule.test.ts +1005 -0
  249. package/Tests/UI/ThemeGroupHoverReveal.test.ts +847 -0
  250. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +70 -0
  251. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +21 -0
  252. package/Tests/UI/Utils/ModelAPISsoRedirect.test.ts +127 -0
  253. package/Tests/UI/Utils/Navigation.test.ts +102 -0
  254. package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +23 -0
  255. package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
  256. package/Tests/Utils/MetricUnitUtil.test.ts +227 -2
  257. package/Tests/Utils/Monitor/MetricValueFormatter.test.ts +288 -2
  258. package/Tests/Utils/Monitor/PlatformResourceIdentityAndUnits.test.ts +1559 -0
  259. package/Tests/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.test.ts +2546 -0
  260. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +315 -0
  261. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +336 -1
  262. package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +244 -0
  263. package/Tests/Utils/ValueFormatter.test.ts +50 -0
  264. package/Tests/tsconfig.json +16 -0
  265. package/Types/AI/AIResourceContext.ts +7 -0
  266. package/Types/Dashboard/DashboardTemplates.ts +2 -1
  267. package/Types/DatabaseServer/DatabaseConnectionSpan.ts +77 -0
  268. package/Types/DatabaseServer/DatabaseContainerClassifier.ts +2068 -0
  269. package/Types/DatabaseServer/DatabaseContainerCommand.ts +801 -0
  270. package/Types/DatabaseServer/DatabaseEndpoint.ts +1943 -0
  271. package/Types/DatabaseServer/DatabaseServerDiscoverySource.ts +68 -0
  272. package/Types/DatabaseServer/DatabaseServerMetricCatalog.ts +966 -0
  273. package/Types/DatabaseServer/DatabaseSystem.ts +2124 -0
  274. package/Types/DatabaseServer/DatabaseTelemetryResolver.ts +555 -0
  275. package/Types/Email/EmailTemplateType.ts +1 -0
  276. package/Types/Monitor/CephAlertTemplates.ts +18 -0
  277. package/Types/Monitor/DatabaseAlertTemplates.ts +2020 -0
  278. package/Types/Monitor/KubernetesAlertTemplates.ts +64 -24
  279. package/Types/Monitor/KubernetesMetricCatalog.ts +118 -19
  280. package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +14 -0
  281. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +93 -10
  282. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +109 -8
  283. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +36 -7
  284. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +43 -2
  285. package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +41 -6
  286. package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +26 -0
  287. package/Types/NetworkDevice/DiscoveredHostNamingStatus.ts +147 -0
  288. package/Types/Permission.ts +267 -0
  289. package/Types/Probe/ProbeApiIngestResponse.ts +8 -0
  290. package/Types/Rules/RuleCriteriaFieldRegistry.ts +10 -0
  291. package/Types/Rules/RuleRun.ts +12 -0
  292. package/Types/Telemetry/EntityType.ts +23 -0
  293. package/Types/Telemetry/ResourceFacetCatalog.ts +14 -0
  294. package/Types/Telemetry/ServiceType.ts +8 -0
  295. package/UI/Components/Banner/Banner.tsx +1 -1
  296. package/UI/Components/Card/Card.tsx +1 -1
  297. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +2 -2
  298. package/UI/Components/Charts/Line/LineChart.tsx +7 -0
  299. package/UI/Components/CommandPalette/CommandPalette.tsx +1 -1
  300. package/UI/Components/Date/StartAndEndDate.tsx +5 -5
  301. package/UI/Components/Diagram/HorizontalStepChain.tsx +1 -1
  302. package/UI/Components/Feed/FeedOptionsButton.tsx +1 -1
  303. package/UI/Components/Forms/BasicForm.tsx +1 -1
  304. package/UI/Components/Header/Header.tsx +1 -1
  305. package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -1
  306. package/UI/Components/HeaderAlert/HeaderAlert.tsx +1 -1
  307. package/UI/Components/LogsViewer/components/FacetValueRow.tsx +1 -1
  308. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +1 -1
  309. package/UI/Components/Modal/ModalFooter.tsx +1 -1
  310. package/UI/Components/ModelDetail/CardModelDetail.tsx +2 -2
  311. package/UI/Components/ModelTable/BaseModelTable.tsx +4 -4
  312. package/UI/Components/Navbar/NavBar.tsx +9 -2
  313. package/UI/Components/Navbar/NavBarMenuModal.tsx +2 -2
  314. package/UI/Components/Page/Page.tsx +1 -1
  315. package/UI/Components/Pagination/Pagination.tsx +3 -3
  316. package/UI/Components/ProgressButtons/ProgressButtonItem.tsx +1 -1
  317. package/UI/Components/SideMenu/SideMenu.tsx +4 -1
  318. package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +4 -2
  319. package/UI/Components/StatusPage/ResourceList.tsx +6 -6
  320. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +1 -1
  321. package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +1 -1
  322. package/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.tsx +1 -1
  323. package/UI/Components/Workflow/ComponentsModal.tsx +2 -2
  324. package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
  325. package/UI/Styles/Theme.css +8 -1
  326. package/UI/Utils/Navigation.ts +89 -42
  327. package/UI/Utils/Telemetry/TelemetryEntityNames.ts +7 -0
  328. package/UI/Utils/TelemetryService.ts +4 -3
  329. package/Utils/LabelRuleImportExport.ts +2 -0
  330. package/Utils/MetricUnitUtil.ts +103 -11
  331. package/Utils/Monitor/MetricValueFormatter.ts +66 -13
  332. package/Utils/Monitor/PlatformMetricUnitUtil.ts +215 -0
  333. package/Utils/Monitor/PlatformResourceIdentity.ts +514 -0
  334. package/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.ts +425 -0
  335. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +32 -0
  336. package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +73 -0
  337. package/Utils/Telemetry/DatabaseServerEntityKeys.ts +275 -0
  338. package/Utils/Telemetry/EntityKey.ts +176 -0
  339. package/Utils/ValueFormatter.ts +16 -0
  340. package/build/dist/Models/DatabaseModels/Alert.js +54 -0
  341. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  342. package/build/dist/Models/DatabaseModels/DatabaseServer.js +1683 -0
  343. package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -0
  344. package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js +559 -0
  345. package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js.map +1 -0
  346. package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js +648 -0
  347. package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js.map +1 -0
  348. package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js +522 -0
  349. package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js.map +1 -0
  350. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js +603 -0
  351. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js.map +1 -0
  352. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js +506 -0
  353. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js.map +1 -0
  354. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js +505 -0
  355. package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js.map +1 -0
  356. package/build/dist/Models/DatabaseModels/Incident.js +54 -0
  357. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  358. package/build/dist/Models/DatabaseModels/Index.js +16 -0
  359. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  360. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  361. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
  362. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  363. package/build/dist/Models/DatabaseModels/TelemetryException.js +2 -0
  364. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  365. package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js +162 -0
  366. package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js.map +1 -0
  367. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js +240 -0
  368. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js.map +1 -0
  369. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js +26 -0
  370. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js.map +1 -0
  371. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  372. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  373. package/build/dist/Server/Middleware/MultipartFormData.js +1 -1
  374. package/build/dist/Server/Middleware/TelemetryIngest.js +15 -8
  375. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  376. package/build/dist/Server/Services/AlertReminderRuleService.js +72 -23
  377. package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
  378. package/build/dist/Server/Services/DatabaseServerEndpointService.js +694 -0
  379. package/build/dist/Server/Services/DatabaseServerEndpointService.js.map +1 -0
  380. package/build/dist/Server/Services/DatabaseServerFeedService.js +110 -0
  381. package/build/dist/Server/Services/DatabaseServerFeedService.js.map +1 -0
  382. package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js +272 -0
  383. package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js.map +1 -0
  384. package/build/dist/Server/Services/DatabaseServerLabelRuleService.js +13 -0
  385. package/build/dist/Server/Services/DatabaseServerLabelRuleService.js.map +1 -0
  386. package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js +340 -0
  387. package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js.map +1 -0
  388. package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js +13 -0
  389. package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js.map +1 -0
  390. package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js +160 -0
  391. package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js.map +1 -0
  392. package/build/dist/Server/Services/DatabaseServerOwnerUserService.js +153 -0
  393. package/build/dist/Server/Services/DatabaseServerOwnerUserService.js.map +1 -0
  394. package/build/dist/Server/Services/DatabaseServerService.js +3272 -0
  395. package/build/dist/Server/Services/DatabaseServerService.js.map +1 -0
  396. package/build/dist/Server/Services/DatabaseService.js +8 -4
  397. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  398. package/build/dist/Server/Services/DockerResourceService.js +30 -3
  399. package/build/dist/Server/Services/DockerResourceService.js.map +1 -1
  400. package/build/dist/Server/Services/IncidentReminderRuleService.js +73 -23
  401. package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
  402. package/build/dist/Server/Services/Index.js +16 -0
  403. package/build/dist/Server/Services/Index.js.map +1 -1
  404. package/build/dist/Server/Services/InventoryItemService.js +88 -5
  405. package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
  406. package/build/dist/Server/Services/IoTDeviceService.js +111 -24
  407. package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
  408. package/build/dist/Server/Services/OpenTelemetryIngestService.js +24 -9
  409. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  410. package/build/dist/Server/Services/PodmanResourceService.js +30 -3
  411. package/build/dist/Server/Services/PodmanResourceService.js.map +1 -1
  412. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +75 -23
  413. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
  414. package/build/dist/Server/Services/ServiceService.js +1 -1
  415. package/build/dist/Server/Services/ServiceService.js.map +1 -1
  416. package/build/dist/Server/Services/TelemetryUsageBillingService.js +23 -2
  417. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  418. package/build/dist/Server/Services/UserProjectSsoConsentService.js +79 -0
  419. package/build/dist/Server/Services/UserProjectSsoConsentService.js.map +1 -0
  420. package/build/dist/Server/Services/UserService.js +13 -1
  421. package/build/dist/Server/Services/UserService.js.map +1 -1
  422. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +18 -0
  423. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  424. package/build/dist/Server/Types/Database/QueryHelper.js +26 -1
  425. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  426. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +46 -0
  427. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -1
  428. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js +6 -0
  429. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js.map +1 -1
  430. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +134 -13
  431. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
  432. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +22 -6
  433. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  434. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +1489 -524
  435. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  436. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +22 -6
  437. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  438. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +196 -6
  439. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  440. package/build/dist/Server/Utils/Monitor/MonitorResource.js +36 -9
  441. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  442. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +1 -0
  443. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -1
  444. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +175 -17
  445. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -1
  446. package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js +29 -0
  447. package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js.map +1 -0
  448. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +211 -0
  449. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  450. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +82 -10
  451. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
  452. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
  453. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  454. package/build/dist/Server/Utils/StartServer.js +20 -4
  455. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  456. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
  457. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
  458. package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js +442 -0
  459. package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js.map +1 -0
  460. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +5 -1
  461. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  462. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +15 -1
  463. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
  464. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +121 -5
  465. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
  466. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +12 -0
  467. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
  468. package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +438 -36
  469. package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -1
  470. package/build/dist/Server/Utils/Telemetry/Telemetry.js +12 -0
  471. package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
  472. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +17 -18
  473. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  474. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +16 -10
  475. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -1
  476. package/build/dist/Types/AI/AIResourceContext.js +7 -0
  477. package/build/dist/Types/AI/AIResourceContext.js.map +1 -1
  478. package/build/dist/Types/Dashboard/DashboardTemplates.js +2 -1
  479. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  480. package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js +71 -0
  481. package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js.map +1 -0
  482. package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js +1462 -0
  483. package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js.map +1 -0
  484. package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js +691 -0
  485. package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js.map +1 -0
  486. package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js +1407 -0
  487. package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js.map +1 -0
  488. package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js +60 -0
  489. package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js.map +1 -0
  490. package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js +804 -0
  491. package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js.map +1 -0
  492. package/build/dist/Types/DatabaseServer/DatabaseSystem.js +1860 -0
  493. package/build/dist/Types/DatabaseServer/DatabaseSystem.js.map +1 -0
  494. package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js +406 -0
  495. package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js.map +1 -0
  496. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  497. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  498. package/build/dist/Types/Monitor/CephAlertTemplates.js +18 -0
  499. package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -1
  500. package/build/dist/Types/Monitor/DatabaseAlertTemplates.js +1518 -0
  501. package/build/dist/Types/Monitor/DatabaseAlertTemplates.js.map +1 -0
  502. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +57 -24
  503. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  504. package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +104 -18
  505. package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
  506. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +80 -3
  507. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  508. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +10 -3
  509. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  510. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +29 -0
  511. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
  512. package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +21 -6
  513. package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -1
  514. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +25 -0
  515. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
  516. package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js +136 -0
  517. package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js.map +1 -0
  518. package/build/dist/Types/Permission.js +234 -0
  519. package/build/dist/Types/Permission.js.map +1 -1
  520. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +10 -0
  521. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  522. package/build/dist/Types/Rules/RuleRun.js +4 -0
  523. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  524. package/build/dist/Types/Telemetry/EntityType.js +23 -0
  525. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  526. package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +14 -0
  527. package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -1
  528. package/build/dist/Types/Telemetry/ServiceType.js +8 -0
  529. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  530. package/build/dist/UI/Components/Banner/Banner.js +1 -1
  531. package/build/dist/UI/Components/Banner/Banner.js.map +1 -1
  532. package/build/dist/UI/Components/Card/Card.js +1 -1
  533. package/build/dist/UI/Components/Card/Card.js.map +1 -1
  534. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
  535. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  536. package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
  537. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  538. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +1 -1
  539. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
  540. package/build/dist/UI/Components/Date/StartAndEndDate.js +5 -5
  541. package/build/dist/UI/Components/Date/StartAndEndDate.js.map +1 -1
  542. package/build/dist/UI/Components/Diagram/HorizontalStepChain.js +1 -1
  543. package/build/dist/UI/Components/Diagram/HorizontalStepChain.js.map +1 -1
  544. package/build/dist/UI/Components/Feed/FeedOptionsButton.js +1 -1
  545. package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -1
  546. package/build/dist/UI/Components/Forms/BasicForm.js +1 -1
  547. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  548. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
  549. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  550. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +1 -1
  551. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
  552. package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +1 -1
  553. package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
  554. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +1 -1
  555. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  556. package/build/dist/UI/Components/Modal/ModalFooter.js +1 -1
  557. package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
  558. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +2 -2
  559. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  560. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +4 -4
  561. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  562. package/build/dist/UI/Components/Navbar/NavBar.js +9 -2
  563. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  564. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
  565. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  566. package/build/dist/UI/Components/Page/Page.js +1 -1
  567. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  568. package/build/dist/UI/Components/Pagination/Pagination.js +3 -3
  569. package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
  570. package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js +1 -1
  571. package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js.map +1 -1
  572. package/build/dist/UI/Components/SideMenu/SideMenu.js +4 -1
  573. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  574. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +3 -1
  575. package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -1
  576. package/build/dist/UI/Components/StatusPage/ResourceList.js +6 -6
  577. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
  578. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +1 -1
  579. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  580. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +1 -1
  581. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
  582. package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js +1 -1
  583. package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js.map +1 -1
  584. package/build/dist/UI/Components/Workflow/ComponentsModal.js +2 -2
  585. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  586. package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
  587. package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
  588. package/build/dist/UI/Utils/Navigation.js +66 -33
  589. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  590. package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +7 -0
  591. package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
  592. package/build/dist/UI/Utils/TelemetryService.js +3 -2
  593. package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
  594. package/build/dist/Utils/LabelRuleImportExport.js +2 -0
  595. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  596. package/build/dist/Utils/MetricUnitUtil.js +77 -13
  597. package/build/dist/Utils/MetricUnitUtil.js.map +1 -1
  598. package/build/dist/Utils/Monitor/MetricValueFormatter.js +58 -13
  599. package/build/dist/Utils/Monitor/MetricValueFormatter.js.map +1 -1
  600. package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js +161 -0
  601. package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js.map +1 -0
  602. package/build/dist/Utils/Monitor/PlatformResourceIdentity.js +323 -0
  603. package/build/dist/Utils/Monitor/PlatformResourceIdentity.js.map +1 -0
  604. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js +270 -0
  605. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js.map +1 -0
  606. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +23 -0
  607. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
  608. package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +61 -0
  609. package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -1
  610. package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js +178 -0
  611. package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js.map +1 -0
  612. package/build/dist/Utils/Telemetry/EntityKey.js +133 -0
  613. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  614. package/build/dist/Utils/ValueFormatter.js +15 -0
  615. package/build/dist/Utils/ValueFormatter.js.map +1 -1
  616. package/package.json +1 -1
  617. package/tsconfig.tests.json +7 -5
@@ -20,6 +20,7 @@ jest.mock("../../../Server/Utils/PasswordHash", () => {
20
20
 
21
21
  import CephClusterService from "../../../Server/Services/CephClusterService";
22
22
  import CloudResourceService from "../../../Server/Services/CloudResourceService";
23
+ import DatabaseServerService from "../../../Server/Services/DatabaseServerService";
23
24
  import DockerHostService from "../../../Server/Services/DockerHostService";
24
25
  import DockerSwarmClusterService from "../../../Server/Services/DockerSwarmClusterService";
25
26
  import GlobalCache from "../../../Server/Infrastructure/GlobalCache";
@@ -46,9 +47,10 @@ import {
46
47
  /*
47
48
  * Every resource type's liveness heartbeat, pinned together.
48
49
  *
49
- * Twelve services write the same two liveness columns (lastSeenAt +
50
- * otelCollectorStatus) alongside optional columns harvested from
51
- * OpenTelemetry resource attributes, and each has its own markDisconnected*
50
+ * Thirteen services write the same two liveness columns (lastSeenAt +
51
+ * otelCollectorStatus; a database adds collectorLastSeenAt) alongside
52
+ * optional columns harvested from OpenTelemetry resource attributes, and
53
+ * each has its own markDisconnected*
52
54
  * job that flips the resource to "disconnected" 15 minutes after lastSeenAt
53
55
  * stops advancing. They now share one implementation — ResourceHeartbeat —
54
56
  * because eleven hand-copied versions meant eleven copies of the same defect
@@ -109,11 +111,49 @@ type ServiceCase = {
109
111
  * These are what defeated the old throttle — see the header.
110
112
  */
111
113
  churningExtras?: Array<Record<string, unknown>>;
114
+ /**
115
+ * The columns every heartbeat writes, when not just lastSeenAt +
116
+ * otelCollectorStatus. A database also stamps collectorLastSeenAt: an
117
+ * application querying it moves lastSeenAt too, so only that column says
118
+ * the COLLECTOR is alive.
119
+ */
120
+ livenessColumns?: Array<string>;
112
121
  };
113
122
 
114
123
  /** Longer than any bounded column on any of these models. */
115
124
  const OVERSIZED: string = "x".repeat(5000);
116
125
 
126
+ const DEFAULT_LIVENESS_COLUMNS: Array<string> = [
127
+ "lastSeenAt",
128
+ "otelCollectorStatus",
129
+ ];
130
+
131
+ /*
132
+ * The database heartbeat is recordCollectorHeartbeat (a CLIENT span calling
133
+ * the database is a separate, sighting-only heartbeat). This view of the real
134
+ * service gives it the updateLastSeen shape the table drives - `this` stays
135
+ * the view, so the write spies below still see every UPDATE - and answers
136
+ * the one read the heartbeat makes afterwards (the auto-archive restore
137
+ * check) with "no row", so the suite still never reaches Postgres.
138
+ */
139
+ /* eslint-disable @typescript-eslint/no-explicit-any */
140
+ const databaseServerHeartbeat: any = Object.assign(
141
+ Object.create(DatabaseServerService),
142
+ {
143
+ updateLastSeen: function (
144
+ this: typeof DatabaseServerService,
145
+ id: ObjectID,
146
+ extra?: { agentVersion?: string; dbVersion?: string },
147
+ ): Promise<void> {
148
+ return this.recordCollectorHeartbeat(id, extra);
149
+ },
150
+ findOneById: async (): Promise<null> => {
151
+ return null;
152
+ },
153
+ },
154
+ );
155
+ /* eslint-enable @typescript-eslint/no-explicit-any */
156
+
117
157
  /* eslint-disable @typescript-eslint/no-explicit-any */
118
158
  const SERVICE_CASES: Array<ServiceCase> = [
119
159
  {
@@ -257,6 +297,19 @@ const SERVICE_CASES: Array<ServiceCase> = [
257
297
  { osType: "linux", processCount: 413, totalMemoryBytes: 17179869184 },
258
298
  ],
259
299
  },
300
+ {
301
+ name: "DatabaseServerService",
302
+ service: databaseServerHeartbeat,
303
+ namespace: "database-server-last-seen",
304
+ extra: { agentVersion: "0.118.0" },
305
+ otherExtra: { agentVersion: "0.119.0" },
306
+ oversizedExtra: { dbVersion: OVERSIZED },
307
+ livenessColumns: [
308
+ "collectorLastSeenAt",
309
+ "lastSeenAt",
310
+ "otelCollectorStatus",
311
+ ],
312
+ },
260
313
  ];
261
314
  /* eslint-enable @typescript-eslint/no-explicit-any */
262
315
 
@@ -269,7 +322,11 @@ describe.each(SERVICE_CASES)(
269
322
  otherExtra,
270
323
  oversizedExtra,
271
324
  churningExtras,
325
+ livenessColumns,
272
326
  }: ServiceCase) => {
327
+ const liveness: Array<string> = [
328
+ ...(livenessColumns || DEFAULT_LIVENESS_COLUMNS),
329
+ ].sort();
273
330
  let writes: Array<WriteCall>;
274
331
  let cache: Map<string, string>;
275
332
  let deletedCacheKeys: Array<string>;
@@ -329,8 +386,8 @@ describe.each(SERVICE_CASES)(
329
386
  }
330
387
 
331
388
  /**
332
- * Fails any write carrying more than the two liveness columns — the
333
- * shape of a Postgres rejection caused by one bad optional column.
389
+ * Fails any write carrying more than the liveness columns — the shape
390
+ * of a Postgres rejection caused by one bad optional column.
334
391
  */
335
392
  function mockEnrichedWriteFailing(): void {
336
393
  jest
@@ -340,7 +397,7 @@ describe.each(SERVICE_CASES)(
340
397
  ...(input.data as Record<string, unknown>),
341
398
  };
342
399
  writes.push({ id: input.id, data: data });
343
- if (Object.keys(data).length > 2) {
400
+ if (Object.keys(data).length > liveness.length) {
344
401
  throw new Error("value too long for type character varying(100)");
345
402
  }
346
403
  return true;
@@ -505,10 +562,7 @@ describe.each(SERVICE_CASES)(
505
562
  await service.updateLastSeen(RESOURCE_ID, oversizedExtra as never);
506
563
 
507
564
  expect(writes).toHaveLength(2);
508
- expect(Object.keys(lastWrite()).sort()).toEqual([
509
- "lastSeenAt",
510
- "otelCollectorStatus",
511
- ]);
565
+ expect(Object.keys(lastWrite()).sort()).toEqual(liveness);
512
566
  expect(lastWrite()["otelCollectorStatus"]).toBe("connected");
513
567
  expect(lastWrite()["lastSeenAt"]).toBeInstanceOf(Date);
514
568
  });
@@ -553,10 +607,7 @@ describe.each(SERVICE_CASES)(
553
607
 
554
608
  await service.updateLastSeen(RESOURCE_ID, oversizedExtra as never);
555
609
 
556
- expect(Object.keys(lastWrite()).sort()).toEqual([
557
- "lastSeenAt",
558
- "otelCollectorStatus",
559
- ]);
610
+ expect(Object.keys(lastWrite()).sort()).toEqual(liveness);
560
611
  });
561
612
 
562
613
  test("surfaces a genuinely broken database instead of hiding it", async () => {
@@ -617,10 +668,7 @@ describe.each(SERVICE_CASES)(
617
668
  await service.updateLastSeen(RESOURCE_ID, extra as never);
618
669
 
619
670
  expect(writes).toHaveLength(1);
620
- expect(Object.keys(lastWrite()).sort()).toEqual([
621
- "lastSeenAt",
622
- "otelCollectorStatus",
623
- ]);
671
+ expect(Object.keys(lastWrite()).sort()).toEqual(liveness);
624
672
  });
625
673
  });
626
674
 
@@ -668,11 +716,11 @@ describe.each(SERVICE_CASES)(
668
716
  describe("liveness fallback coverage", () => {
669
717
  test("covers every service that writes liveness on the hook-free path", () => {
670
718
  /*
671
- * If a thirteenth resource type grows an updateLastSeen, it belongs in
719
+ * If a fourteenth resource type grows an updateLastSeen, it belongs in
672
720
  * SERVICE_CASES — that is the whole point of this suite. Bumping this
673
721
  * number without adding the case defeats it.
674
722
  */
675
- expect(SERVICE_CASES).toHaveLength(12);
723
+ expect(SERVICE_CASES).toHaveLength(13);
676
724
  });
677
725
 
678
726
  test("no service is listed twice", () => {
@@ -196,9 +196,9 @@ describe("static rule criteria runtime coverage", () => {
196
196
  discoverStaticRuleForms();
197
197
  const inheritedRuleModelNames: Array<string> = getInheritedRuleModelNames();
198
198
 
199
- test("all 64 static match-criteria forms route their 76 rule models through ModelForm", () => {
200
- expect(formFiles).toHaveLength(64);
201
- expect(formsByModel.size).toBe(76);
199
+ test("all 66 static match-criteria forms route their 78 rule models through ModelForm", () => {
200
+ expect(formFiles).toHaveLength(66);
201
+ expect(formsByModel.size).toBe(78);
202
202
  expect([...formsByModel.keys()].sort()).toEqual(inheritedRuleModelNames);
203
203
  expect(Object.keys(RULE_CRITERIA_FIELDS_BY_MODEL).sort()).toEqual(
204
204
  inheritedRuleModelNames,
@@ -109,6 +109,15 @@ describe("resource facet counting covers the whole catalog", () => {
109
109
  );
110
110
  });
111
111
 
112
+ test("databaseServerId is counted under DatabaseServer — the receiver batches primary-keyed on the row", () => {
113
+ const statement: Statement = service.build({
114
+ facetKey: "databaseServerId",
115
+ });
116
+
117
+ expect(paramValues(statement)).toContain(ServiceType.DatabaseServer);
118
+ expect(statement.query).not.toContain("mapContains(attributes");
119
+ });
120
+
112
121
  test("iotFleetId is counted under IoTDevice — ingest stamps the fleet id with that type", () => {
113
122
  const statement: Statement = service.build({ facetKey: "iotFleetId" });
114
123
 
@@ -0,0 +1,153 @@
1
+ import Entities from "../../../Models/DatabaseModels/Index";
2
+ import PostgresAppInstance from "../../../Server/Infrastructure/PostgresDatabase";
3
+ import UserProjectSsoConsentService from "../../../Server/Services/UserProjectSsoConsentService";
4
+ import ObjectID from "../../../Types/ObjectID";
5
+ import { DataSource } from "typeorm";
6
+
7
+ jest.mock("../../../Server/Middleware/UserAuthorization", () => {
8
+ return { getUserMiddleware: jest.fn() };
9
+ });
10
+ jest.mock("../../../Server/Services/ProjectService", () => {
11
+ return { getCurrentPlan: jest.fn() };
12
+ });
13
+ jest.mock("../../../Server/Infrastructure/Postgres/DataSourceOptions", () => {
14
+ return {};
15
+ });
16
+
17
+ /*
18
+ * The consent record against a real, migrated database.
19
+ *
20
+ * UserProjectSsoConsentService.test.ts pins the service's logic with the
21
+ * database faked. What only a database can show is the guarantee that logic
22
+ * leans on: the unique index turns a second, racing insert for the same
23
+ * (user, project) into an error rather than a duplicate row, so two clicks on
24
+ * one confirmation link -- or two links for one project -- end with exactly
25
+ * one consent, and the second click still succeeds.
26
+ *
27
+ * Opt in with RUN_POSTGRES_SSO_CONSENT_TESTS=true and config.env; point it at
28
+ * a migrated database with SSO_CONSENT_TEST_DATABASE_HOST/PORT/NAME
29
+ * (default localhost:5400; the Postgres Schema Drift job runs it). Only the table definition is copied from public, into an
30
+ * isolated schema that is dropped afterwards; every row is synthetic.
31
+ */
32
+ const describePostgres: typeof describe =
33
+ process.env["RUN_POSTGRES_SSO_CONSENT_TESTS"] === "true"
34
+ ? describe
35
+ : describe.skip;
36
+
37
+ describePostgres("UserProjectSsoConsent against Postgres", () => {
38
+ const schema: string = `sso_consent_test_${ObjectID.generate().toString().replace(/-/g, "")}`;
39
+ let database: DataSource;
40
+
41
+ const countRows: (
42
+ userId: ObjectID,
43
+ projectId: ObjectID,
44
+ ) => Promise<number> = async (
45
+ userId: ObjectID,
46
+ projectId: ObjectID,
47
+ ): Promise<number> => {
48
+ const rows: Array<{ count: string }> = await database.query(
49
+ `SELECT COUNT(*)::text AS count FROM "${schema}"."UserProjectSsoConsent" WHERE "userId" = $1 AND "projectId" = $2`,
50
+ [userId.toString(), projectId.toString()],
51
+ );
52
+
53
+ return Number(rows[0]!.count);
54
+ };
55
+
56
+ beforeAll(async () => {
57
+ database = new DataSource({
58
+ type: "postgres",
59
+ host: process.env["SSO_CONSENT_TEST_DATABASE_HOST"] || "localhost",
60
+ port: Number(process.env["SSO_CONSENT_TEST_DATABASE_PORT"] || "5400"),
61
+ username: process.env["DATABASE_USERNAME"] || "postgres",
62
+ password: process.env["DATABASE_PASSWORD"] || "password",
63
+ database:
64
+ process.env["SSO_CONSENT_TEST_DATABASE_NAME"] ||
65
+ process.env["DATABASE_NAME"] ||
66
+ "oneuptimedb",
67
+ entities: Entities,
68
+ schema,
69
+ synchronize: false,
70
+ extra: { options: `-c search_path=${schema},public` },
71
+ });
72
+ await database.initialize();
73
+ await database.query(`CREATE SCHEMA "${schema}"`);
74
+ await database.query(
75
+ `CREATE TABLE "${schema}"."UserProjectSsoConsent" (LIKE public."UserProjectSsoConsent" INCLUDING ALL)`,
76
+ );
77
+
78
+ jest.spyOn(PostgresAppInstance, "isConnected").mockReturnValue(true);
79
+ jest.spyOn(PostgresAppInstance, "getDataSource").mockReturnValue(database);
80
+ });
81
+
82
+ afterAll(async () => {
83
+ if (database?.isInitialized) {
84
+ await database.query(`DROP SCHEMA IF EXISTS "${schema}" CASCADE`);
85
+ await database.destroy();
86
+ }
87
+
88
+ jest.restoreAllMocks();
89
+ });
90
+
91
+ test("records consent once, and finds it for that project only", async () => {
92
+ const userId: ObjectID = ObjectID.generate();
93
+ const projectId: ObjectID = ObjectID.generate();
94
+ const otherProjectId: ObjectID = ObjectID.generate();
95
+
96
+ expect(
97
+ await UserProjectSsoConsentService.hasConsent({ userId, projectId }),
98
+ ).toBe(false);
99
+
100
+ await UserProjectSsoConsentService.recordConsent({ userId, projectId });
101
+
102
+ expect(
103
+ await UserProjectSsoConsentService.hasConsent({ userId, projectId }),
104
+ ).toBe(true);
105
+ expect(
106
+ await UserProjectSsoConsentService.hasConsent({
107
+ userId,
108
+ projectId: otherProjectId,
109
+ }),
110
+ ).toBe(false);
111
+ expect(
112
+ await UserProjectSsoConsentService.hasConsent({
113
+ userId: ObjectID.generate(),
114
+ projectId,
115
+ }),
116
+ ).toBe(false);
117
+ });
118
+
119
+ test("a second confirmation neither fails nor duplicates the row", async () => {
120
+ const userId: ObjectID = ObjectID.generate();
121
+ const projectId: ObjectID = ObjectID.generate();
122
+
123
+ await UserProjectSsoConsentService.recordConsent({ userId, projectId });
124
+ await UserProjectSsoConsentService.recordConsent({ userId, projectId });
125
+
126
+ expect(await countRows(userId, projectId)).toBe(1);
127
+ });
128
+
129
+ test("two confirmations racing each other end with exactly one row", async () => {
130
+ const userId: ObjectID = ObjectID.generate();
131
+ const projectId: ObjectID = ObjectID.generate();
132
+
133
+ await Promise.all([
134
+ UserProjectSsoConsentService.recordConsent({ userId, projectId }),
135
+ UserProjectSsoConsentService.recordConsent({ userId, projectId }),
136
+ UserProjectSsoConsentService.recordConsent({ userId, projectId }),
137
+ ]);
138
+
139
+ expect(await countRows(userId, projectId)).toBe(1);
140
+ });
141
+
142
+ test("the database itself refuses a duplicate live consent", async () => {
143
+ const userId: ObjectID = ObjectID.generate();
144
+ const projectId: ObjectID = ObjectID.generate();
145
+ const insert: string = `INSERT INTO "${schema}"."UserProjectSsoConsent" ("userId", "projectId", "version") VALUES ($1, $2, 1)`;
146
+
147
+ await database.query(insert, [userId.toString(), projectId.toString()]);
148
+
149
+ await expect(
150
+ database.query(insert, [userId.toString(), projectId.toString()]),
151
+ ).rejects.toThrow(/duplicate key value/);
152
+ });
153
+ });
@@ -0,0 +1,192 @@
1
+ import UserProjectSsoConsent from "../../../Models/DatabaseModels/UserProjectSsoConsent";
2
+ import UserProjectSsoConsentService from "../../../Server/Services/UserProjectSsoConsentService";
3
+ import ObjectID from "../../../Types/ObjectID";
4
+ import PositiveNumber from "../../../Types/PositiveNumber";
5
+ import { afterEach, describe, expect, jest, test } from "@jest/globals";
6
+ import { getMetadataArgsStorage } from "typeorm";
7
+ import { IndexMetadataArgs } from "typeorm/metadata-args/IndexMetadataArgs";
8
+
9
+ /*
10
+ * The record that an account's owner agreed, from their mailbox, that a
11
+ * project's single sign-on may sign them in. Read on every hosted project-SSO
12
+ * sign-in; written only by the confirmation link.
13
+ *
14
+ * What has to hold:
15
+ *
16
+ * - consent is per (user, project): the query is scoped to both, so one
17
+ * project's consent can never let another project's IdP in;
18
+ * - recording is idempotent, because the same person can press the button
19
+ * twice, or confirm two emails for the same project, and the second must
20
+ * neither fail nor duplicate the row;
21
+ * - a lost race with a concurrent insert is absorbed, but a real failure is
22
+ * not swallowed.
23
+ */
24
+
25
+ const USER_ID: ObjectID = new ObjectID("88888888-8888-4888-8888-888888888888");
26
+ const PROJECT_ID: ObjectID = new ObjectID(
27
+ "99999999-9999-4999-8999-999999999999",
28
+ );
29
+
30
+ /*
31
+ * Spy handles are held through this rather than a SpiedFunction/SpyInstance
32
+ * type: two such declarations are in scope in this project (the global jest
33
+ * namespace's and @jest/globals'), jest.spyOn returns the latter, and naming
34
+ * the wrong one passes the jest run and fails only in compile-common. These
35
+ * tests read exactly one thing off a spy, so that is all this names.
36
+ */
37
+ interface SpyCalls {
38
+ mock: { calls: Array<Array<unknown>> };
39
+ }
40
+
41
+ afterEach(() => {
42
+ jest.restoreAllMocks();
43
+ });
44
+
45
+ describe("UserProjectSsoConsentService.hasConsent", () => {
46
+ test("asks about this user in this project, as root", async () => {
47
+ const countBy: SpyCalls = jest
48
+ .spyOn(UserProjectSsoConsentService, "countBy")
49
+ .mockResolvedValue(new PositiveNumber(1)) as unknown as SpyCalls;
50
+
51
+ await expect(
52
+ UserProjectSsoConsentService.hasConsent({
53
+ userId: USER_ID,
54
+ projectId: PROJECT_ID,
55
+ }),
56
+ ).resolves.toBe(true);
57
+
58
+ const call: Record<string, any> = countBy.mock.calls[0]![0] as Record<
59
+ string,
60
+ any
61
+ >;
62
+
63
+ expect(call["query"]["userId"].toString()).toBe(USER_ID.toString());
64
+ expect(call["query"]["projectId"].toString()).toBe(PROJECT_ID.toString());
65
+ expect(call["props"]["isRoot"]).toBe(true);
66
+ });
67
+
68
+ test("is false when there is no row", async () => {
69
+ jest
70
+ .spyOn(UserProjectSsoConsentService, "countBy")
71
+ .mockResolvedValue(new PositiveNumber(0));
72
+
73
+ await expect(
74
+ UserProjectSsoConsentService.hasConsent({
75
+ userId: USER_ID,
76
+ projectId: PROJECT_ID,
77
+ }),
78
+ ).resolves.toBe(false);
79
+ });
80
+ });
81
+
82
+ describe("UserProjectSsoConsentService.recordConsent", () => {
83
+ test("writes one row for this user and project", async () => {
84
+ jest
85
+ .spyOn(UserProjectSsoConsentService, "countBy")
86
+ .mockResolvedValue(new PositiveNumber(0));
87
+ const create: SpyCalls = jest
88
+ .spyOn(UserProjectSsoConsentService, "create")
89
+ .mockResolvedValue(new UserProjectSsoConsent()) as unknown as SpyCalls;
90
+
91
+ await UserProjectSsoConsentService.recordConsent({
92
+ userId: USER_ID,
93
+ projectId: PROJECT_ID,
94
+ });
95
+
96
+ expect(create.mock.calls).toHaveLength(1);
97
+
98
+ const call: Record<string, any> = create.mock.calls[0]![0] as Record<
99
+ string,
100
+ any
101
+ >;
102
+
103
+ expect(call["data"]).toBeInstanceOf(UserProjectSsoConsent);
104
+ expect(call["data"]["userId"].toString()).toBe(USER_ID.toString());
105
+ expect(call["data"]["projectId"].toString()).toBe(PROJECT_ID.toString());
106
+ expect(call["props"]["isRoot"]).toBe(true);
107
+ });
108
+
109
+ test("writes nothing when consent is already on record", async () => {
110
+ jest
111
+ .spyOn(UserProjectSsoConsentService, "countBy")
112
+ .mockResolvedValue(new PositiveNumber(1));
113
+ const create: SpyCalls = jest.spyOn(
114
+ UserProjectSsoConsentService,
115
+ "create",
116
+ ) as unknown as SpyCalls;
117
+
118
+ await UserProjectSsoConsentService.recordConsent({
119
+ userId: USER_ID,
120
+ projectId: PROJECT_ID,
121
+ });
122
+
123
+ expect(create.mock.calls).toHaveLength(0);
124
+ });
125
+
126
+ test("absorbs losing an insert race to a concurrent click", async () => {
127
+ // Absent when checked, present by the time the insert was turned away.
128
+ jest
129
+ .spyOn(UserProjectSsoConsentService, "countBy")
130
+ .mockResolvedValueOnce(new PositiveNumber(0))
131
+ .mockResolvedValueOnce(new PositiveNumber(1));
132
+ jest
133
+ .spyOn(UserProjectSsoConsentService, "create")
134
+ .mockRejectedValue(
135
+ new Error("duplicate key value violates unique constraint"),
136
+ );
137
+
138
+ await expect(
139
+ UserProjectSsoConsentService.recordConsent({
140
+ userId: USER_ID,
141
+ projectId: PROJECT_ID,
142
+ }),
143
+ ).resolves.toBeUndefined();
144
+ });
145
+
146
+ test("does not swallow a write that failed for any other reason", async () => {
147
+ jest
148
+ .spyOn(UserProjectSsoConsentService, "countBy")
149
+ .mockResolvedValue(new PositiveNumber(0));
150
+ jest
151
+ .spyOn(UserProjectSsoConsentService, "create")
152
+ .mockRejectedValue(new Error("connection terminated"));
153
+
154
+ await expect(
155
+ UserProjectSsoConsentService.recordConsent({
156
+ userId: USER_ID,
157
+ projectId: PROJECT_ID,
158
+ }),
159
+ ).rejects.toThrow("connection terminated");
160
+ });
161
+ });
162
+
163
+ describe("UserProjectSsoConsent model", () => {
164
+ test("has no API: nobody but the server reads or writes it", () => {
165
+ const model: UserProjectSsoConsent = new UserProjectSsoConsent();
166
+
167
+ expect(model.createRecordPermissions).toEqual([]);
168
+ expect(model.readRecordPermissions).toEqual([]);
169
+ expect(model.updateRecordPermissions).toEqual([]);
170
+ expect(model.deleteRecordPermissions).toEqual([]);
171
+ expect(model.crudApiPath).toBeFalsy();
172
+ });
173
+
174
+ test("is one live row per user and project, enforced by the database", () => {
175
+ /*
176
+ * The unique index is what turns a concurrent second insert into the
177
+ * error recordConsent absorbs, instead of a duplicate row.
178
+ */
179
+ const index: IndexMetadataArgs | undefined = getMetadataArgsStorage()
180
+ .indices.filter((candidate: IndexMetadataArgs) => {
181
+ return candidate.target === UserProjectSsoConsent;
182
+ })
183
+ .find((candidate: IndexMetadataArgs) => {
184
+ return candidate.name === "IDX_UserProjectSsoConsent_userId_projectId";
185
+ });
186
+
187
+ expect(index).toBeDefined();
188
+ expect(index!.unique).toBe(true);
189
+ expect(index!.columns).toEqual(["userId", "projectId"]);
190
+ expect(index!.where).toBe('"deletedAt" IS NULL');
191
+ });
192
+ });
@@ -684,6 +684,77 @@ describe("UserService.createUserOnSignup -- first Master Admin election", () =>
684
684
  });
685
685
  });
686
686
 
687
+ describe("a signup that names an existing row", () => {
688
+ /*
689
+ * TypeORM's save() UPDATEs the row an entity's `_id` names, and this create
690
+ * runs as root, which DatabaseService.create exempts from its supplied-id
691
+ * check. A signup carrying a victim's id therefore rewrote the victim's
692
+ * email and password in place (UserSignupIdTakeoverPostgres.test.ts shows
693
+ * it against a real table). Refused before anything is read or written.
694
+ */
695
+ const VICTIM_ID: string = "33333333-3333-4333-8333-333333333333";
696
+
697
+ type BuildUserWithIdFunction = (modules: LoadedModules) => any;
698
+
699
+ const buildUserWithId: BuildUserWithIdFunction = (
700
+ modules: LoadedModules,
701
+ ): any => {
702
+ const user: any = buildUser({ modules, email: "attacker@example.com" });
703
+ user._id = VICTIM_ID;
704
+ return user;
705
+ };
706
+
707
+ test("self-hosted: refuses it without taking the lock or touching a row", async () => {
708
+ userRows.push({ email: "victim@example.com" });
709
+
710
+ await expect(
711
+ selfHosted.userService.createUserOnSignup({
712
+ user: buildUserWithId(selfHosted),
713
+ props: { isRoot: true },
714
+ }),
715
+ ).rejects.toThrow("An id cannot be supplied when signing up.");
716
+
717
+ expect(events).toEqual([]);
718
+ expect(selfHosted.userService.create).not.toHaveBeenCalled();
719
+ expect(selfHosted.semaphore.lock).not.toHaveBeenCalled();
720
+ expect(userRows).toHaveLength(1);
721
+ });
722
+
723
+ test("self-hosted: refuses it on an empty instance, so the id cannot win the election either", async () => {
724
+ await expect(
725
+ selfHosted.userService.createUserOnSignup({
726
+ user: buildUserWithId(selfHosted),
727
+ props: { isRoot: true },
728
+ }),
729
+ ).rejects.toThrow("An id cannot be supplied when signing up.");
730
+
731
+ expect(selfHosted.userService.create).not.toHaveBeenCalled();
732
+ expect(userRows).toHaveLength(0);
733
+ });
734
+
735
+ test("hosted: refuses it without touching a row", async () => {
736
+ await expect(
737
+ hosted.userService.createUserOnSignup({
738
+ user: buildUserWithId(hosted),
739
+ props: { isRoot: true },
740
+ }),
741
+ ).rejects.toThrow("An id cannot be supplied when signing up.");
742
+
743
+ expect(events).toEqual([]);
744
+ expect(hosted.userService.create).not.toHaveBeenCalled();
745
+ });
746
+
747
+ test("a user with no id is still created", async () => {
748
+ const created: any = await hosted.userService.createUserOnSignup({
749
+ user: buildUser({ modules: hosted, email: "new@example.com" }),
750
+ props: { isRoot: true },
751
+ });
752
+
753
+ expect(created).toBeTruthy();
754
+ expect(hosted.userService.create).toHaveBeenCalledTimes(1);
755
+ });
756
+ });
757
+
687
758
  describe("the race itself", () => {
688
759
  test("two simultaneous signups produce exactly one Master Admin", async () => {
689
760
  const [first, second]: Array<any> = await Promise.all([