@oneuptime/common 12.0.33 → 13.0.0

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 (877) hide show
  1. package/Models/AnalyticsModels/RumSession.ts +117 -1
  2. package/Models/AnalyticsModels/RumSessionChunk.ts +13 -0
  3. package/Models/DatabaseModels/AlertCustomField.ts +77 -3
  4. package/Models/DatabaseModels/ApiKeyPermission.ts +3 -27
  5. package/Models/DatabaseModels/GlobalConfig.ts +12 -12
  6. package/Models/DatabaseModels/IncidentCustomField.ts +77 -3
  7. package/Models/DatabaseModels/InventoryItem.ts +44 -1
  8. package/Models/DatabaseModels/InventoryItemCustomField.ts +77 -3
  9. package/Models/DatabaseModels/MonitorCustomField.ts +77 -3
  10. package/Models/DatabaseModels/NetworkDevice.ts +126 -0
  11. package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +77 -3
  12. package/Models/DatabaseModels/RumApplication.ts +6 -6
  13. package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +77 -3
  14. package/Models/DatabaseModels/StatusPageCustomField.ts +77 -3
  15. package/Models/DatabaseModels/TeamCustomField.ts +77 -3
  16. package/Models/DatabaseModels/TeamMember.ts +0 -9
  17. package/Models/DatabaseModels/TeamMemberCustomField.ts +77 -3
  18. package/Models/DatabaseModels/TeamPermission.ts +3 -24
  19. package/Models/DatabaseModels/TelemetryIngestionKey.ts +260 -0
  20. package/Models/DatabaseModels/UserTelegram.ts +0 -4
  21. package/Scripts/benchmark-fanin-capacity.js +181 -0
  22. package/Server/API/TelemetryAPI.ts +1284 -164
  23. package/Server/API/UserNotificationSettingAPI.ts +55 -0
  24. package/Server/API/UserTelegramAPI.ts +48 -4
  25. package/Server/EnvironmentConfig.ts +82 -18
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.ts +91 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.ts +67 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.ts +139 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.ts +121 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1791700000000-AddMacAddressToNetworkDevice.ts +25 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  32. package/Server/Infrastructure/QueueWorker.ts +20 -14
  33. package/Server/Infrastructure/Redis.ts +8 -8
  34. package/Server/Infrastructure/Semaphore.ts +2 -0
  35. package/Server/Infrastructure/Status.ts +10 -4
  36. package/Server/Middleware/TelemetryIngest.ts +453 -7
  37. package/Server/Services/AccessTokenService.ts +1 -0
  38. package/Server/Services/AlertCustomFieldService.ts +98 -0
  39. package/Server/Services/AlertService.ts +37 -0
  40. package/Server/Services/ApiKeyPermissionService.ts +461 -29
  41. package/Server/Services/CustomFieldMappingService.ts +879 -0
  42. package/Server/Services/DatabaseService.ts +65 -13
  43. package/Server/Services/GlobalConfigService.ts +194 -0
  44. package/Server/Services/IncidentCustomFieldService.ts +98 -0
  45. package/Server/Services/IncidentService.ts +35 -0
  46. package/Server/Services/InventoryItemService.ts +31 -1
  47. package/Server/Services/MetricService.ts +194 -0
  48. package/Server/Services/MonitorService.ts +32 -0
  49. package/Server/Services/MonitorTemplateService.ts +140 -19
  50. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +427 -66
  51. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +87 -2
  52. package/Server/Services/NetworkDeviceService.ts +69 -0
  53. package/Server/Services/ProjectService.ts +22 -0
  54. package/Server/Services/RoutineEmailSettingsService.ts +73 -0
  55. package/Server/Services/RumSessionReplayViewService.ts +104 -24
  56. package/Server/Services/ScheduledMaintenanceCustomFieldService.ts +98 -0
  57. package/Server/Services/ScheduledMaintenanceService.ts +32 -0
  58. package/Server/Services/TeamMemberService.ts +78 -0
  59. package/Server/Services/TeamPermissionService.ts +235 -3
  60. package/Server/Services/TelemetryIngestionKeyService.ts +722 -19
  61. package/Server/Services/UserNotificationRuleService.ts +76 -25
  62. package/Server/Services/UserNotificationSettingService.ts +34 -6
  63. package/Server/Services/UserTelegramService.ts +326 -5
  64. package/Server/Types/Database/Permissions/ReadPermission.ts +45 -5
  65. package/Server/Types/Database/QueryHelper.ts +2 -0
  66. package/Server/Types/Database/QueryUtil.ts +56 -0
  67. package/Server/Types/Markdown.ts +93 -1
  68. package/Server/Utils/APIKey/AccessPermission.ts +5 -2
  69. package/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.ts +54 -0
  70. package/Server/Utils/CustomField/CustomFieldMappingRegistry.ts +415 -0
  71. package/Server/Utils/CustomField/CustomFieldMappingValidator.ts +335 -0
  72. package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +82 -17
  73. package/Server/Utils/DataSource/EgressGuard.ts +177 -8
  74. package/Server/Utils/EmailRollup/EmailRollupConstants.ts +38 -5
  75. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +67 -5
  76. package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +2 -2
  77. package/Server/Utils/FrontendEnvironment.ts +40 -0
  78. package/Server/Utils/LogRedaction.ts +20 -0
  79. package/Server/Utils/Logger.ts +11 -0
  80. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +394 -86
  81. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +30 -4
  82. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +31 -5
  83. package/Server/Utils/Monitor/MonitorAlert.ts +29 -6
  84. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +312 -52
  85. package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +82 -9
  86. package/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.ts +16 -7
  87. package/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.ts +29 -17
  88. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +107 -48
  89. package/Server/Utils/Monitor/MonitorIncident.ts +22 -6
  90. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +29 -0
  91. package/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.ts +158 -0
  92. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +27 -0
  93. package/Server/Utils/Monitor/SeriesContextEnricher.ts +304 -0
  94. package/Server/Utils/SSRFProtection.ts +217 -10
  95. package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +239 -138
  96. package/Server/Utils/SessionReplay/SessionReplayHealthCounters.ts +305 -0
  97. package/Server/Utils/SessionReplay/SessionReplayReadService.ts +1430 -289
  98. package/Server/Utils/StartServer.ts +2 -17
  99. package/Server/Utils/TelegramVerificationToken.ts +185 -0
  100. package/Server/Utils/Telemetry/EntityRegistry.ts +11 -1
  101. package/Server/Utils/Telemetry/PinServiceName.ts +197 -0
  102. package/Server/Utils/Telemetry/TelemetryEntity.ts +83 -9
  103. package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +38 -16
  104. package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +92 -0
  105. package/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.ts +217 -0
  106. package/Server/Utils/VM/VMAPI.ts +1 -0
  107. package/Server/Utils/VM/VMRunner.ts +975 -95
  108. package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +202 -0
  109. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +32 -0
  110. package/Tests/App/Dashboard/AdoptedDeviceDrawer.test.tsx +374 -0
  111. package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +404 -0
  112. package/Tests/App/Dashboard/DashboardLabelVariables.test.tsx +580 -0
  113. package/Tests/App/Dashboard/DashboardMonitorLabelVariable.test.tsx +438 -0
  114. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +5 -2
  115. package/Tests/App/Dashboard/DeviceAttachmentCard.test.tsx +273 -0
  116. package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +505 -0
  117. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +468 -0
  118. package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +163 -0
  119. package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +401 -0
  120. package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +232 -0
  121. package/Tests/App/Dashboard/InventoryItems.test.tsx +201 -0
  122. package/Tests/App/Dashboard/InventoryTypeAndStatusFacets.test.tsx +798 -0
  123. package/Tests/App/Dashboard/NetworkTopologyLiveView.test.tsx +320 -0
  124. package/Tests/App/Dashboard/NetworkTopologyToolbar.test.tsx +275 -0
  125. package/Tests/App/Dashboard/OnCallCalendarFeedEmptyState.test.tsx +975 -0
  126. package/Tests/App/Dashboard/OnCallCalendarFeedPlanGate.test.tsx +63 -0
  127. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +626 -0
  128. package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +348 -0
  129. package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +331 -0
  130. package/Tests/App/Dashboard/UserSettingsEmailPreferences.test.tsx +603 -0
  131. package/Tests/App/Dashboard/UserSettingsNotificationSettings.test.tsx +324 -0
  132. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +13 -4
  133. package/Tests/App/StatusPage/StatusPageLastUpdated.test.tsx +263 -0
  134. package/Tests/App/StatusPage/StatusPageOidcOrigin.test.tsx +223 -0
  135. package/Tests/App/StatusPage/StatusPageOverviewLiveAndSearch.test.tsx +753 -0
  136. package/Tests/App/StatusPage/StatusPageResourceSearchBox.test.tsx +224 -0
  137. package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +262 -0
  138. package/Tests/Models/CustomFieldMappingColumns.test.ts +166 -0
  139. package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +20 -6
  140. package/Tests/Models/InventoryItemStatus.test.ts +147 -0
  141. package/Tests/Models/NetworkDeviceMacAddressColumn.test.ts +294 -0
  142. package/Tests/ResponsiveVisibility.test.ts +115 -0
  143. package/Tests/ResponsiveVisibility.ts +183 -0
  144. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +129 -0
  145. package/Tests/Server/API/SessionReplayAPI.test.ts +1940 -216
  146. package/Tests/Server/API/UserNotificationSettingAPI.test.ts +186 -0
  147. package/Tests/Server/API/UserTelegramAPISecurity.test.ts +231 -0
  148. package/Tests/Server/EnvironmentConfigFrontendSecurity.test.ts +234 -0
  149. package/Tests/Server/EnvironmentConfigValkey.test.ts +227 -0
  150. package/Tests/Server/Infrastructure/Postgres/AddMacAddressToNetworkDeviceMigration.test.ts +365 -0
  151. package/Tests/Server/Infrastructure/Postgres/CustomFieldValueMappingMigration.test.ts +241 -0
  152. package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +41 -0
  153. package/Tests/Server/Infrastructure/Postgres/SessionReplayRecordEverySessionByDefaultMigration.test.ts +169 -0
  154. package/Tests/Server/Infrastructure/QueueWorkerTimeout.test.ts +210 -0
  155. package/Tests/Server/Infrastructure/TelemetryExporterDeploymentConfig.test.ts +130 -0
  156. package/Tests/Server/Infrastructure/ValkeyDeploymentConfig.test.ts +265 -0
  157. package/Tests/Server/Middleware/HttpMetricsMiddleware.test.ts +382 -0
  158. package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +4 -1
  159. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +525 -0
  160. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +1163 -0
  161. package/Tests/Server/Middleware/TelemetryIngestTokenLog.test.ts +5 -3
  162. package/Tests/Server/Services/AddTelemetryIngestionKeyTypeMigration.test.ts +555 -0
  163. package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +678 -0
  164. package/Tests/Server/Services/ApiKeyPermissionService.test.ts +276 -28
  165. package/Tests/Server/Services/CustomFieldDropdownOptionsColumnWidth.test.ts +431 -0
  166. package/Tests/Server/Services/CustomFieldMappingService.test.ts +850 -0
  167. package/Tests/Server/Services/DatabaseServiceAggregateBy.test.ts +291 -56
  168. package/Tests/Server/Services/DatabaseServiceSortTiebreaker.test.ts +151 -0
  169. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +32 -0
  170. package/Tests/Server/Services/GlobalConfigService.test.ts +414 -1
  171. package/Tests/Server/Services/InventoryItemManualCreate.test.ts +105 -0
  172. package/Tests/Server/Services/InventoryItemPromotionGate.test.ts +178 -0
  173. package/Tests/Server/Services/MetricRawEntityKeyPrune.test.ts +592 -0
  174. package/Tests/Server/Services/MonitorTemplateServiceCustomFieldSync.test.ts +502 -0
  175. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +1351 -74
  176. package/Tests/Server/Services/NetworkDeviceDiscoveryScanRegistration.test.ts +520 -0
  177. package/Tests/Server/Services/NetworkDeviceMacAddressNormalization.test.ts +572 -0
  178. package/Tests/Server/Services/RoutineEmailSettingsPostgres.test.ts +329 -0
  179. package/Tests/Server/Services/RumSessionReplayViewService.test.ts +267 -0
  180. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +9 -0
  181. package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +9 -0
  182. package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +834 -0
  183. package/Tests/Server/Services/TelemetryIngestionKeyPolicyResolution.test.ts +814 -0
  184. package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +998 -0
  185. package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +141 -0
  186. package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +18 -10
  187. package/Tests/Server/Services/UserTelegramVerificationSecurity.test.ts +688 -0
  188. package/Tests/Server/Types/Database/InventoryStatusPostgres.test.ts +368 -0
  189. package/Tests/Server/Types/Database/Permissions/ReadBlockPermission.test.ts +261 -14
  190. package/Tests/Server/Types/Database/QueryUtilIncludesAnyOfGroups.test.ts +169 -0
  191. package/Tests/Server/Types/Database/QueryUtilIncludesAnyOfGroupsPostgres.test.ts +297 -0
  192. package/Tests/Server/Types/Markdown.test.ts +194 -1
  193. package/Tests/Server/Types/Workflow/Components/IncomingWebhookUtils.test.ts +279 -0
  194. package/Tests/Server/Types/Workflow/Components/TextToJson.test.ts +212 -0
  195. package/Tests/Server/Utils/AI/SRE/Insights/FixRouting.test.ts +497 -0
  196. package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +383 -0
  197. package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +7 -3
  198. package/Tests/Server/Utils/AnalyticsDatabase/ClusterConfig.test.ts +315 -0
  199. package/Tests/Server/Utils/CustomField/CustomFieldMappingRegistry.test.ts +436 -0
  200. package/Tests/Server/Utils/CustomField/CustomFieldMappingValidator.test.ts +437 -0
  201. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +214 -0
  202. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +300 -11
  203. package/Tests/Server/Utils/EmailRollup/EmailRollupBurstWindow.test.ts +83 -0
  204. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +2 -2
  205. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerPreferences.test.ts +362 -0
  206. package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +10 -3
  207. package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +77 -1
  208. package/Tests/Server/Utils/EventLoop.test.ts +359 -0
  209. package/Tests/Server/Utils/FrontendEnvironment.test.ts +190 -0
  210. package/Tests/Server/Utils/JsonWebToken.test.ts +30 -0
  211. package/Tests/Server/Utils/LogRedaction.test.ts +26 -0
  212. package/Tests/Server/Utils/LoggerCredentialLeak.test.ts +23 -9
  213. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteria.test.ts +242 -0
  214. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaAggregation.test.ts +590 -0
  215. package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +29 -0
  216. package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestHeaderCriteria.test.ts +236 -0
  217. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +30 -6
  218. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +246 -0
  219. package/Tests/Server/Utils/Monitor/MonitorCriteriaEmailEvalLogAgreement.test.ts +280 -0
  220. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +659 -8
  221. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +570 -0
  222. package/Tests/Server/Utils/Monitor/MonitorCriteriaExpectationBuilderUnits.test.ts +30 -5
  223. package/Tests/Server/Utils/Monitor/MonitorCriteriaMessageBuilderUnits.test.ts +68 -21
  224. package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +36 -19
  225. package/Tests/Server/Utils/Monitor/MonitorTemplateUtilSeriesContext.test.ts +176 -0
  226. package/Tests/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.test.ts +573 -0
  227. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +317 -0
  228. package/Tests/Server/Utils/Monitor/SeriesContextEnricher.test.ts +356 -0
  229. package/Tests/Server/Utils/SSRFProtectionCloudServiceAddresses.test.ts +595 -0
  230. package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +198 -1
  231. package/Tests/Server/Utils/SessionReplay/SessionReplayHealthCounters.test.ts +453 -0
  232. package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +1378 -0
  233. package/Tests/Server/Utils/SessionReplayOriginAllowListRefactor.test.ts +420 -0
  234. package/Tests/Server/Utils/TelegramVerificationToken.test.ts +253 -0
  235. package/Tests/Server/Utils/Telemetry/ContextSpanProcessor.test.ts +281 -0
  236. package/Tests/Server/Utils/Telemetry/InventoryDuplicateIdentity.test.ts +316 -0
  237. package/Tests/Server/Utils/Telemetry/PinServiceName.test.ts +666 -0
  238. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +111 -8
  239. package/Tests/Server/Utils/Telemetry/TelemetryFanInWriterCapacity.test.ts +458 -0
  240. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +424 -0
  241. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.test.ts +528 -0
  242. package/Tests/Server/Utils/TelemetryExporterEnvironment.test.ts +56 -0
  243. package/Tests/Server/Utils/VM/VMRunnerHostBridgeLatency.test.ts +74 -0
  244. package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +100 -7
  245. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +1176 -6
  246. package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +220 -0
  247. package/Tests/Types/CustomField/CustomFieldValueMapping.test.ts +348 -0
  248. package/Tests/Types/Database/IncludesAnyOfGroups.test.ts +106 -0
  249. package/Tests/Types/JSONFunctions.test.ts +300 -0
  250. package/Tests/Types/Monitor/CephAlertTemplates.test.ts +422 -53
  251. package/Tests/Types/Monitor/DockerAlertTemplates.test.ts +495 -15
  252. package/Tests/Types/Monitor/DockerSwarmAlertTemplates.test.ts +191 -45
  253. package/Tests/Types/Monitor/HostAlertTemplates.test.ts +370 -42
  254. package/Tests/Types/Monitor/IotAlertTemplates.test.ts +375 -20
  255. package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +636 -42
  256. package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +189 -0
  257. package/Tests/Types/Monitor/KubernetesTemplateGroupByKeys.test.ts +95 -14
  258. package/Tests/Types/Monitor/PodmanAlertTemplates.test.ts +190 -21
  259. package/Tests/Types/Monitor/ProxmoxAlertTemplates.test.ts +352 -22
  260. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationAlertDebuggability.test.ts +363 -0
  261. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +93 -18
  262. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +259 -0
  263. package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +476 -0
  264. package/Tests/Types/Monitor/RumAlertTemplates.test.ts +136 -0
  265. package/Tests/Types/Monitor/SeriesContext/SeriesDebugHints.test.ts +661 -0
  266. package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +507 -0
  267. package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +270 -0
  268. package/Tests/Types/Monitor/TemplateGroupByKeys.test.ts +38 -10
  269. package/Tests/Types/Monitor/Utils/RecommendationCriteriaAssertions.ts +102 -0
  270. package/Tests/Types/NetworkAutomation/AutoImportRunMerge.test.ts +235 -0
  271. package/Tests/Types/NetworkAutomation/RuleRunResult.test.ts +66 -0
  272. package/Tests/Types/NetworkAutomation/RuleRunResultDescribe.test.ts +309 -1
  273. package/Tests/Types/NotificationSetting/RoutineEmailEvents.test.ts +47 -0
  274. package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +608 -0
  275. package/Tests/Types/Rum/SessionReplayCustomEvents.test.ts +434 -0
  276. package/Tests/Types/Telemetry/InventoryLiveness.test.ts +99 -0
  277. package/Tests/Types/WebsiteRequest.test.ts +285 -3
  278. package/Tests/UI/Components/Charts/ChartBucketIdentity.test.ts +16 -3
  279. package/Tests/UI/Components/Charts/ChartTrailingBucketGap.test.ts +691 -0
  280. package/Tests/UI/Components/ComponentsModal.test.tsx +12 -4
  281. package/Tests/UI/Components/ComponentsModalUsability.test.tsx +518 -0
  282. package/Tests/UI/Components/CustomFields/CustomFieldsDetail.test.tsx +160 -0
  283. package/Tests/UI/Components/CustomFields/CustomFieldsDetailMapping.test.tsx +324 -0
  284. package/Tests/UI/Components/CustomFields/MapFromCustomFieldInput.test.tsx +176 -0
  285. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +484 -0
  286. package/Tests/UI/Components/HeaderRightRail.test.tsx +157 -0
  287. package/Tests/UI/Components/IconDropdownItem.test.tsx +102 -0
  288. package/Tests/UI/Components/JSONTablePrototypePollution.test.tsx +117 -0
  289. package/Tests/UI/Components/KeyboardShortcutsModal.test.tsx +214 -0
  290. package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +561 -0
  291. package/Tests/UI/Components/MonitorGraphs/UptimeBarDayModal.test.tsx +302 -0
  292. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +28 -12
  293. package/Tests/UI/Components/ShortcutDialogGuard.test.tsx +74 -0
  294. package/Tests/UI/Components/StatusPage/ResourceGroupSectionAutoExpand.test.tsx +248 -0
  295. package/Tests/UI/Components/TableCellWrapping.test.tsx +625 -0
  296. package/Tests/UI/Components/TableLoadingStates.test.tsx +205 -0
  297. package/Tests/UI/Components/Workflow/NodePlacement.test.ts +148 -0
  298. package/Tests/UI/Components/Workflow/Workflow.test.tsx +981 -0
  299. package/Tests/UI/ConfigBrowserTelemetry.test.ts +70 -0
  300. package/Tests/UI/ReactRouterSingletonBuild.test.ts +133 -0
  301. package/Tests/UI/Rum/ChunkLoader.test.ts +1036 -2
  302. package/Tests/UI/Rum/FidelityNotices.test.ts +187 -0
  303. package/Tests/UI/Rum/InactivityMap.test.ts +341 -0
  304. package/Tests/UI/Rum/PrivacySummaryCard.test.tsx +259 -0
  305. package/Tests/UI/Rum/RecordingHealthCard.test.tsx +855 -0
  306. package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +594 -0
  307. package/Tests/UI/Rum/ReplayCard.test.tsx +451 -0
  308. package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +536 -0
  309. package/Tests/UI/Rum/ReplayEngine.test.ts +2503 -0
  310. package/Tests/UI/Rum/ReplayEngineTypes.test.ts +171 -0
  311. package/Tests/UI/Rum/ReplayHeader.test.tsx +719 -0
  312. package/Tests/UI/Rum/ReplayLink.test.tsx +119 -0
  313. package/Tests/UI/Rum/ReplayPinControl.test.tsx +408 -0
  314. package/Tests/UI/Rum/ReplayPlaybackIntent.test.ts +152 -0
  315. package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +514 -0
  316. package/Tests/UI/Rum/ReplayRail.test.tsx +1296 -0
  317. package/Tests/UI/Rum/ReplayRailDetail.test.tsx +900 -0
  318. package/Tests/UI/Rum/ReplayScrubber.test.tsx +763 -147
  319. package/Tests/UI/Rum/ReplaySignalTypes.test.ts +189 -0
  320. package/Tests/UI/Rum/ReplaySignals.test.ts +1579 -0
  321. package/Tests/UI/Rum/ReplayStage.test.tsx +396 -473
  322. package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +918 -0
  323. package/Tests/UI/Rum/ReplayTimeFormat.test.ts +94 -0
  324. package/Tests/UI/Rum/ReplayTimeline.test.tsx +696 -0
  325. package/Tests/UI/Rum/ReplayUi.test.tsx +559 -0
  326. package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +499 -0
  327. package/Tests/UI/Rum/SessionReplaySearchBar.test.tsx +346 -0
  328. package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +545 -0
  329. package/Tests/UI/Rum/SessionReplayTable.test.tsx +991 -0
  330. package/Tests/UI/Rum/TargetedCapturePanel.test.tsx +254 -0
  331. package/Tests/UI/Telemetry/BrowserExporterIsolation.test.ts +71 -0
  332. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +5 -0
  333. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +1 -0
  334. package/Tests/UI/Utils/GlobalKeyboardShortcut.test.ts +344 -0
  335. package/Tests/Utils/API.test.ts +308 -0
  336. package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +11 -1
  337. package/Tests/Utils/Dashboard/LabelVariable.test.ts +257 -0
  338. package/Tests/Utils/Dashboard/VariableUrlState.test.ts +144 -14
  339. package/Tests/Utils/HTTPResponseBodyReader.test.ts +323 -0
  340. package/Tests/Utils/MetricUnitUtil.test.ts +81 -0
  341. package/Tests/Utils/Monitor/DeviceMacLearningUtil.test.ts +497 -0
  342. package/Tests/Utils/Monitor/MetricValueFormatter.test.ts +546 -0
  343. package/Tests/Utils/Monitor/MonitorTemplateCustomFieldUtil.test.ts +218 -0
  344. package/Tests/Utils/Monitor/NetworkTopologyEndpointAdoption.test.ts +1755 -0
  345. package/Tests/Utils/NetworkAutomation/AutoImportRunChain.test.ts +320 -0
  346. package/Tests/Utils/NetworkDiscovery/DiscoveryScanStatus.test.ts +117 -0
  347. package/Tests/Utils/Rum/ChunkMath.test.ts +83 -0
  348. package/Tests/Utils/Rum/SessionReplayHealthDiagnosis.test.ts +993 -0
  349. package/Tests/Utils/Rum/SessionReplayStringMap.test.ts +245 -0
  350. package/Tests/Utils/StatusPage/ResourceSearch.test.ts +631 -0
  351. package/Tests/Utils/Telemetry/OriginAllowList.test.ts +633 -0
  352. package/Tests/Utils/Uptime/DayUptimeGraphUtil.test.ts +461 -0
  353. package/Tests/Utils/ValueFormatter.test.ts +148 -0
  354. package/Types/BaseDatabase/IncludesAnyOfGroups.ts +77 -0
  355. package/Types/CustomField/CustomFieldMappingCatalog.ts +161 -0
  356. package/Types/CustomField/CustomFieldMappingSourceResource.ts +19 -0
  357. package/Types/CustomField/CustomFieldValueMapping.ts +288 -0
  358. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  359. package/Types/Dashboard/DashboardComponents/DashboardMonitorListComponent.ts +1 -0
  360. package/Types/Dashboard/DashboardVariable.ts +8 -0
  361. package/Types/Icon/IconProp.ts +1 -0
  362. package/Types/JSON.ts +4 -0
  363. package/Types/JSONFunctions.ts +205 -43
  364. package/Types/Monitor/CephAlertTemplates.ts +157 -195
  365. package/Types/Monitor/DockerAlertTemplates.ts +338 -128
  366. package/Types/Monitor/DockerSwarmAlertTemplates.ts +95 -112
  367. package/Types/Monitor/HostAlertTemplates.ts +302 -130
  368. package/Types/Monitor/IotAlertTemplates.ts +112 -104
  369. package/Types/Monitor/KubernetesAlertTemplates.ts +415 -224
  370. package/Types/Monitor/KubernetesMetricCatalog.ts +23 -19
  371. package/Types/Monitor/PodmanAlertTemplates.ts +116 -163
  372. package/Types/Monitor/ProxmoxAlertTemplates.ts +217 -99
  373. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +98 -6
  374. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +44 -7
  375. package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +383 -0
  376. package/Types/Monitor/RumAlertTemplates.ts +46 -7
  377. package/Types/Monitor/SeriesContext/SeriesDebugHints.ts +596 -0
  378. package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +554 -0
  379. package/Types/Monitor/ServiceAlertTemplates.ts +98 -11
  380. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +13 -0
  381. package/Types/Monitor/UptimeHistoryLabels.ts +56 -0
  382. package/Types/NetworkAutomation/RuleRunResult.ts +402 -13
  383. package/Types/NotificationSetting/RoutineEmailEvents.ts +30 -0
  384. package/Types/Rum/SessionReplay.ts +209 -0
  385. package/Types/Rum/SessionReplayApi.ts +722 -0
  386. package/Types/Rum/SessionReplayCaptureTrigger.ts +21 -12
  387. package/Types/Rum/SessionReplayConsentMode.ts +11 -7
  388. package/Types/Rum/SessionReplayCustomEvents.ts +549 -0
  389. package/Types/Rum/SessionReplayHealth.ts +238 -0
  390. package/Types/SerializableObjectDictionary.ts +4 -0
  391. package/Types/Telemetry/InventoryLiveness.ts +56 -0
  392. package/Types/Telemetry/TelemetryIngestSurface.ts +95 -0
  393. package/Types/Telemetry/TelemetryIngestionKeyPolicy.ts +75 -0
  394. package/Types/Telemetry/TelemetryIngestionKeyType.ts +29 -0
  395. package/Types/WebsiteRequest.ts +85 -3
  396. package/UI/Components/CSVFileUpload/CSVFileUpload.tsx +9 -2
  397. package/UI/Components/Charts/Area/AreaChart.tsx +13 -2
  398. package/UI/Components/Charts/Bar/BarChart.tsx +6 -2
  399. package/UI/Components/Charts/Line/LineChart.tsx +13 -2
  400. package/UI/Components/Charts/Types/XAxis/XAxis.ts +29 -0
  401. package/UI/Components/Charts/Utils/DataPoint.ts +22 -3
  402. package/UI/Components/Charts/Utils/TimeAnnotation.ts +76 -9
  403. package/UI/Components/Charts/Utils/XAxis.ts +217 -0
  404. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +189 -46
  405. package/UI/Components/CustomFields/MapFromCustomFieldInput.tsx +216 -0
  406. package/UI/Components/Dashboard/DashboardVariableControl.tsx +285 -0
  407. package/UI/Components/Graphs/DayUptimeGraph.tsx +173 -8
  408. package/UI/Components/Graphs/UptimeBarTooltip.tsx +22 -278
  409. package/UI/Components/Graphs/UptimeDaySummary.tsx +327 -0
  410. package/UI/Components/Header/Header.tsx +25 -9
  411. package/UI/Components/Header/IconDropdown/IconDropdownItem.tsx +10 -1
  412. package/UI/Components/Header/IconDropdown/IconDropdownMenu.tsx +6 -1
  413. package/UI/Components/Header/ProjectPicker/ProjectPicker.tsx +6 -1
  414. package/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.tsx +6 -1
  415. package/UI/Components/Icon/Icon.tsx +11 -0
  416. package/UI/Components/JSONTable/JSONTable.tsx +2 -2
  417. package/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.tsx +125 -0
  418. package/UI/Components/KeyboardShortcut/Screenshots/README.md +19 -0
  419. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-command-palette.png +0 -0
  420. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-dialog-dark.png +0 -0
  421. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-dialog.png +0 -0
  422. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-help-menu.png +0 -0
  423. package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-narrow.png +0 -0
  424. package/UI/Components/ModelTable/Column.ts +15 -0
  425. package/UI/Components/Monitor/SeriesDebugCommandsViewer.tsx +64 -0
  426. package/UI/Components/Monitor/SeriesLabelsViewer.tsx +93 -0
  427. package/UI/Components/MonitorGraphs/Uptime.tsx +14 -2
  428. package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +63 -10
  429. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
  430. package/UI/Components/StatusPage/ResourceGroupSection.tsx +40 -0
  431. package/UI/Components/Table/CellClassName.ts +81 -0
  432. package/UI/Components/Table/TableRow.tsx +20 -14
  433. package/UI/Components/Table/TableSkeletonRows.tsx +9 -9
  434. package/UI/Components/Table/Types/Column.ts +36 -0
  435. package/UI/Components/Tooltip/Tooltip.tsx +11 -1
  436. package/UI/Components/Workflow/ComponentsModal.tsx +60 -39
  437. package/UI/Components/Workflow/NodePlacement.ts +57 -0
  438. package/UI/Components/Workflow/Workflow.tsx +47 -18
  439. package/UI/Config.ts +15 -33
  440. package/UI/Utils/GlobalKeyboardShortcut.ts +208 -0
  441. package/UI/Utils/Telemetry/BrowserTelemetryConfig.ts +28 -0
  442. package/UI/Utils/Telemetry/Telemetry.ts +10 -8
  443. package/UI/esbuild-config.js +6 -0
  444. package/Utils/API.ts +129 -3
  445. package/Utils/Dashboard/Components/DashboardMonitorListComponent.ts +12 -1
  446. package/Utils/Dashboard/LabelVariable.ts +152 -0
  447. package/Utils/Dashboard/VariableUrlState.ts +27 -5
  448. package/Utils/HTTPResponseBodyReader.ts +221 -0
  449. package/Utils/MetricUnitUtil.ts +34 -0
  450. package/Utils/Monitor/DeviceMacLearningUtil.ts +177 -0
  451. package/Utils/Monitor/MetricValueFormatter.ts +342 -0
  452. package/Utils/Monitor/MonitorTemplateCustomFieldUtil.ts +124 -0
  453. package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +7 -2
  454. package/Utils/Monitor/NetworkTopologyUtil.ts +693 -0
  455. package/Utils/NetworkAutomation/AutoImportRunChain.ts +138 -0
  456. package/Utils/NetworkDiscovery/DiscoveryScanStatus.ts +77 -0
  457. package/Utils/Rum/ChunkMath.ts +106 -0
  458. package/Utils/Rum/SessionReplayHealth.ts +732 -0
  459. package/Utils/Rum/SessionReplayStringMap.ts +226 -0
  460. package/Utils/Schema/ModelSchema.ts +1 -0
  461. package/Utils/StatusPage/ResourceSearch.ts +290 -0
  462. package/Utils/Telemetry/OriginAllowList.ts +355 -0
  463. package/Utils/Uptime/DayUptimeGraphUtil.ts +205 -0
  464. package/Utils/ValueFormatter.ts +35 -1
  465. package/build/dist/Models/AnalyticsModels/RumSession.js +102 -19
  466. package/build/dist/Models/AnalyticsModels/RumSession.js.map +1 -1
  467. package/build/dist/Models/AnalyticsModels/RumSessionChunk.js +11 -9
  468. package/build/dist/Models/AnalyticsModels/RumSessionChunk.js.map +1 -1
  469. package/build/dist/Models/DatabaseModels/AlertCustomField.js +79 -3
  470. package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
  471. package/build/dist/Models/DatabaseModels/ApiKeyPermission.js +3 -27
  472. package/build/dist/Models/DatabaseModels/ApiKeyPermission.js.map +1 -1
  473. package/build/dist/Models/DatabaseModels/GlobalConfig.js +12 -12
  474. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  475. package/build/dist/Models/DatabaseModels/IncidentCustomField.js +79 -3
  476. package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
  477. package/build/dist/Models/DatabaseModels/InventoryItem.js +34 -1
  478. package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -1
  479. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +79 -3
  480. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js.map +1 -1
  481. package/build/dist/Models/DatabaseModels/MonitorCustomField.js +79 -3
  482. package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
  483. package/build/dist/Models/DatabaseModels/NetworkDevice.js +128 -0
  484. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  485. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +79 -3
  486. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
  487. package/build/dist/Models/DatabaseModels/RumApplication.js +6 -6
  488. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  489. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +79 -3
  490. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
  491. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +79 -3
  492. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
  493. package/build/dist/Models/DatabaseModels/TeamCustomField.js +79 -3
  494. package/build/dist/Models/DatabaseModels/TeamCustomField.js.map +1 -1
  495. package/build/dist/Models/DatabaseModels/TeamMember.js +0 -9
  496. package/build/dist/Models/DatabaseModels/TeamMember.js.map +1 -1
  497. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +79 -3
  498. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
  499. package/build/dist/Models/DatabaseModels/TeamPermission.js +3 -24
  500. package/build/dist/Models/DatabaseModels/TeamPermission.js.map +1 -1
  501. package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js +267 -0
  502. package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js.map +1 -1
  503. package/build/dist/Models/DatabaseModels/UserTelegram.js +0 -4
  504. package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
  505. package/build/dist/Server/API/TelemetryAPI.js +769 -109
  506. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  507. package/build/dist/Server/API/UserNotificationSettingAPI.js +35 -0
  508. package/build/dist/Server/API/UserNotificationSettingAPI.js.map +1 -0
  509. package/build/dist/Server/API/UserTelegramAPI.js +28 -6
  510. package/build/dist/Server/API/UserTelegramAPI.js.map +1 -1
  511. package/build/dist/Server/EnvironmentConfig.js +73 -14
  512. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  513. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.js +60 -0
  514. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.js.map +1 -0
  515. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.js +53 -0
  516. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.js.map +1 -0
  517. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.js +82 -0
  518. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.js.map +1 -0
  519. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.js +46 -0
  520. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.js.map +1 -0
  521. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791700000000-AddMacAddressToNetworkDevice.js +14 -0
  522. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791700000000-AddMacAddressToNetworkDevice.js.map +1 -0
  523. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  524. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  525. package/build/dist/Server/Infrastructure/QueueWorker.js +19 -7
  526. package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
  527. package/build/dist/Server/Infrastructure/Redis.js +8 -8
  528. package/build/dist/Server/Infrastructure/Redis.js.map +1 -1
  529. package/build/dist/Server/Infrastructure/Semaphore.js +1 -0
  530. package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
  531. package/build/dist/Server/Infrastructure/Status.js +10 -4
  532. package/build/dist/Server/Infrastructure/Status.js.map +1 -1
  533. package/build/dist/Server/Middleware/TelemetryIngest.js +315 -8
  534. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  535. package/build/dist/Server/Services/AccessTokenService.js +1 -0
  536. package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
  537. package/build/dist/Server/Services/AlertCustomFieldService.js +93 -0
  538. package/build/dist/Server/Services/AlertCustomFieldService.js.map +1 -1
  539. package/build/dist/Server/Services/AlertService.js +34 -0
  540. package/build/dist/Server/Services/AlertService.js.map +1 -1
  541. package/build/dist/Server/Services/ApiKeyPermissionService.js +331 -28
  542. package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
  543. package/build/dist/Server/Services/CustomFieldMappingService.js +614 -0
  544. package/build/dist/Server/Services/CustomFieldMappingService.js.map +1 -0
  545. package/build/dist/Server/Services/DatabaseService.js +58 -13
  546. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  547. package/build/dist/Server/Services/GlobalConfigService.js +133 -0
  548. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  549. package/build/dist/Server/Services/IncidentCustomFieldService.js +93 -0
  550. package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
  551. package/build/dist/Server/Services/IncidentService.js +32 -0
  552. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  553. package/build/dist/Server/Services/InventoryItemService.js +28 -1
  554. package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
  555. package/build/dist/Server/Services/MetricService.js +163 -0
  556. package/build/dist/Server/Services/MetricService.js.map +1 -1
  557. package/build/dist/Server/Services/MonitorService.js +29 -0
  558. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  559. package/build/dist/Server/Services/MonitorTemplateService.js +116 -17
  560. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  561. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +349 -64
  562. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  563. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +65 -0
  564. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  565. package/build/dist/Server/Services/NetworkDeviceService.js +54 -0
  566. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  567. package/build/dist/Server/Services/ProjectService.js +22 -0
  568. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  569. package/build/dist/Server/Services/RoutineEmailSettingsService.js +69 -0
  570. package/build/dist/Server/Services/RoutineEmailSettingsService.js.map +1 -0
  571. package/build/dist/Server/Services/RumSessionReplayViewService.js +86 -24
  572. package/build/dist/Server/Services/RumSessionReplayViewService.js.map +1 -1
  573. package/build/dist/Server/Services/ScheduledMaintenanceCustomFieldService.js +93 -0
  574. package/build/dist/Server/Services/ScheduledMaintenanceCustomFieldService.js.map +1 -1
  575. package/build/dist/Server/Services/ScheduledMaintenanceService.js +29 -0
  576. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  577. package/build/dist/Server/Services/TeamMemberService.js +62 -2
  578. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  579. package/build/dist/Server/Services/TeamPermissionService.js +166 -3
  580. package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
  581. package/build/dist/Server/Services/TelemetryIngestionKeyService.js +562 -18
  582. package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
  583. package/build/dist/Server/Services/UserNotificationRuleService.js +60 -25
  584. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  585. package/build/dist/Server/Services/UserNotificationSettingService.js +26 -6
  586. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  587. package/build/dist/Server/Services/UserTelegramService.js +257 -4
  588. package/build/dist/Server/Services/UserTelegramService.js.map +1 -1
  589. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js +29 -4
  590. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js.map +1 -1
  591. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  592. package/build/dist/Server/Types/Database/QueryUtil.js +36 -0
  593. package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
  594. package/build/dist/Server/Types/Markdown.js +75 -0
  595. package/build/dist/Server/Types/Markdown.js.map +1 -1
  596. package/build/dist/Server/Utils/APIKey/AccessPermission.js +2 -2
  597. package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
  598. package/build/dist/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.js +27 -0
  599. package/build/dist/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.js.map +1 -0
  600. package/build/dist/Server/Utils/CustomField/CustomFieldMappingRegistry.js +226 -0
  601. package/build/dist/Server/Utils/CustomField/CustomFieldMappingRegistry.js.map +1 -0
  602. package/build/dist/Server/Utils/CustomField/CustomFieldMappingValidator.js +189 -0
  603. package/build/dist/Server/Utils/CustomField/CustomFieldMappingValidator.js.map +1 -0
  604. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +53 -18
  605. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
  606. package/build/dist/Server/Utils/DataSource/EgressGuard.js +121 -7
  607. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
  608. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +38 -5
  609. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -1
  610. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +54 -3
  611. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
  612. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +2 -2
  613. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -1
  614. package/build/dist/Server/Utils/FrontendEnvironment.js +33 -0
  615. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -0
  616. package/build/dist/Server/Utils/LogRedaction.js +20 -0
  617. package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
  618. package/build/dist/Server/Utils/Logger.js +10 -0
  619. package/build/dist/Server/Utils/Logger.js.map +1 -1
  620. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +323 -81
  621. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  622. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +20 -4
  623. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
  624. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +29 -5
  625. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
  626. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +29 -6
  627. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  628. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +254 -48
  629. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  630. package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +58 -9
  631. package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js.map +1 -1
  632. package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js +9 -3
  633. package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js.map +1 -1
  634. package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js +26 -12
  635. package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js.map +1 -1
  636. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +74 -33
  637. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  638. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +22 -6
  639. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  640. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +22 -0
  641. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  642. package/build/dist/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.js +114 -0
  643. package/build/dist/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.js.map +1 -0
  644. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +25 -0
  645. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  646. package/build/dist/Server/Utils/Monitor/SeriesContextEnricher.js +237 -0
  647. package/build/dist/Server/Utils/Monitor/SeriesContextEnricher.js.map +1 -0
  648. package/build/dist/Server/Utils/SSRFProtection.js +136 -9
  649. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  650. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +174 -89
  651. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
  652. package/build/dist/Server/Utils/SessionReplay/SessionReplayHealthCounters.js +223 -0
  653. package/build/dist/Server/Utils/SessionReplay/SessionReplayHealthCounters.js.map +1 -0
  654. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +945 -164
  655. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
  656. package/build/dist/Server/Utils/StartServer.js +3 -14
  657. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  658. package/build/dist/Server/Utils/TelegramVerificationToken.js +129 -0
  659. package/build/dist/Server/Utils/TelegramVerificationToken.js.map +1 -0
  660. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +9 -1
  661. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  662. package/build/dist/Server/Utils/Telemetry/PinServiceName.js +163 -0
  663. package/build/dist/Server/Utils/Telemetry/PinServiceName.js.map +1 -0
  664. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +70 -13
  665. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  666. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +28 -15
  667. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -1
  668. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +64 -0
  669. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -0
  670. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.js +171 -0
  671. package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.js.map +1 -0
  672. package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
  673. package/build/dist/Server/Utils/VM/VMRunner.js +780 -69
  674. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  675. package/build/dist/Types/BaseDatabase/IncludesAnyOfGroups.js +54 -0
  676. package/build/dist/Types/BaseDatabase/IncludesAnyOfGroups.js.map +1 -0
  677. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +60 -0
  678. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -0
  679. package/build/dist/Types/CustomField/CustomFieldMappingSourceResource.js +20 -0
  680. package/build/dist/Types/CustomField/CustomFieldMappingSourceResource.js.map +1 -0
  681. package/build/dist/Types/CustomField/CustomFieldValueMapping.js +141 -0
  682. package/build/dist/Types/CustomField/CustomFieldValueMapping.js.map +1 -0
  683. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  684. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  685. package/build/dist/Types/Dashboard/DashboardVariable.js +1 -0
  686. package/build/dist/Types/Dashboard/DashboardVariable.js.map +1 -1
  687. package/build/dist/Types/Icon/IconProp.js +1 -0
  688. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  689. package/build/dist/Types/JSON.js +1 -0
  690. package/build/dist/Types/JSON.js.map +1 -1
  691. package/build/dist/Types/JSONFunctions.js +131 -37
  692. package/build/dist/Types/JSONFunctions.js.map +1 -1
  693. package/build/dist/Types/Monitor/CephAlertTemplates.js +130 -171
  694. package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -1
  695. package/build/dist/Types/Monitor/DockerAlertTemplates.js +286 -121
  696. package/build/dist/Types/Monitor/DockerAlertTemplates.js.map +1 -1
  697. package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js +84 -105
  698. package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js.map +1 -1
  699. package/build/dist/Types/Monitor/HostAlertTemplates.js +250 -122
  700. package/build/dist/Types/Monitor/HostAlertTemplates.js.map +1 -1
  701. package/build/dist/Types/Monitor/IotAlertTemplates.js +81 -81
  702. package/build/dist/Types/Monitor/IotAlertTemplates.js.map +1 -1
  703. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +375 -215
  704. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  705. package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +19 -19
  706. package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
  707. package/build/dist/Types/Monitor/PodmanAlertTemplates.js +104 -153
  708. package/build/dist/Types/Monitor/PodmanAlertTemplates.js.map +1 -1
  709. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +156 -91
  710. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
  711. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +67 -6
  712. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
  713. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +38 -7
  714. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
  715. package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +261 -0
  716. package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -0
  717. package/build/dist/Types/Monitor/RumAlertTemplates.js +46 -7
  718. package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
  719. package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js +422 -0
  720. package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js.map +1 -0
  721. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +441 -0
  722. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -0
  723. package/build/dist/Types/Monitor/ServiceAlertTemplates.js +79 -15
  724. package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -1
  725. package/build/dist/Types/Monitor/UptimeHistoryLabels.js +17 -0
  726. package/build/dist/Types/Monitor/UptimeHistoryLabels.js.map +1 -0
  727. package/build/dist/Types/NetworkAutomation/RuleRunResult.js +291 -6
  728. package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
  729. package/build/dist/Types/NotificationSetting/RoutineEmailEvents.js +29 -0
  730. package/build/dist/Types/NotificationSetting/RoutineEmailEvents.js.map +1 -0
  731. package/build/dist/Types/Rum/SessionReplay.js +117 -0
  732. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  733. package/build/dist/Types/Rum/SessionReplayApi.js +181 -0
  734. package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -0
  735. package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js +21 -12
  736. package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js.map +1 -1
  737. package/build/dist/Types/Rum/SessionReplayConsentMode.js +11 -7
  738. package/build/dist/Types/Rum/SessionReplayConsentMode.js.map +1 -1
  739. package/build/dist/Types/Rum/SessionReplayCustomEvents.js +172 -0
  740. package/build/dist/Types/Rum/SessionReplayCustomEvents.js.map +1 -0
  741. package/build/dist/Types/Rum/SessionReplayHealth.js +37 -0
  742. package/build/dist/Types/Rum/SessionReplayHealth.js.map +1 -0
  743. package/build/dist/Types/SerializableObjectDictionary.js +4 -0
  744. package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
  745. package/build/dist/Types/Telemetry/InventoryLiveness.js +37 -0
  746. package/build/dist/Types/Telemetry/InventoryLiveness.js.map +1 -0
  747. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +85 -0
  748. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -0
  749. package/build/dist/Types/Telemetry/TelemetryIngestionKeyPolicy.js +15 -0
  750. package/build/dist/Types/Telemetry/TelemetryIngestionKeyPolicy.js.map +1 -0
  751. package/build/dist/Types/Telemetry/TelemetryIngestionKeyType.js +30 -0
  752. package/build/dist/Types/Telemetry/TelemetryIngestionKeyType.js.map +1 -0
  753. package/build/dist/Types/WebsiteRequest.js +55 -3
  754. package/build/dist/Types/WebsiteRequest.js.map +1 -1
  755. package/build/dist/UI/Components/CSVFileUpload/CSVFileUpload.js +7 -0
  756. package/build/dist/UI/Components/CSVFileUpload/CSVFileUpload.js.map +1 -1
  757. package/build/dist/UI/Components/Charts/Area/AreaChart.js +13 -2
  758. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  759. package/build/dist/UI/Components/Charts/Bar/BarChart.js +6 -2
  760. package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
  761. package/build/dist/UI/Components/Charts/Line/LineChart.js +13 -2
  762. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  763. package/build/dist/UI/Components/Charts/Types/XAxis/XAxis.js.map +1 -1
  764. package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -3
  765. package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
  766. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +40 -9
  767. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -1
  768. package/build/dist/UI/Components/Charts/Utils/XAxis.js +186 -0
  769. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  770. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +89 -8
  771. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  772. package/build/dist/UI/Components/CustomFields/MapFromCustomFieldInput.js +118 -0
  773. package/build/dist/UI/Components/CustomFields/MapFromCustomFieldInput.js.map +1 -0
  774. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js +137 -0
  775. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js.map +1 -0
  776. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +112 -7
  777. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  778. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +5 -162
  779. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
  780. package/build/dist/UI/Components/Graphs/UptimeDaySummary.js +181 -0
  781. package/build/dist/UI/Components/Graphs/UptimeDaySummary.js.map +1 -0
  782. package/build/dist/UI/Components/Header/Header.js +2 -3
  783. package/build/dist/UI/Components/Header/Header.js.map +1 -1
  784. package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js +2 -1
  785. package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js.map +1 -1
  786. package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js +7 -1
  787. package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js.map +1 -1
  788. package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js +7 -1
  789. package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js.map +1 -1
  790. package/build/dist/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.js +7 -1
  791. package/build/dist/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.js.map +1 -1
  792. package/build/dist/UI/Components/Icon/Icon.js +5 -0
  793. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  794. package/build/dist/UI/Components/JSONTable/JSONTable.js +2 -2
  795. package/build/dist/UI/Components/JSONTable/JSONTable.js.map +1 -1
  796. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.js +35 -0
  797. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.js.map +1 -0
  798. package/build/dist/UI/Components/Monitor/SeriesDebugCommandsViewer.js +34 -0
  799. package/build/dist/UI/Components/Monitor/SeriesDebugCommandsViewer.js.map +1 -0
  800. package/build/dist/UI/Components/Monitor/SeriesLabelsViewer.js +49 -0
  801. package/build/dist/UI/Components/Monitor/SeriesLabelsViewer.js.map +1 -0
  802. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +1 -1
  803. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  804. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +32 -6
  805. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
  806. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +38 -0
  807. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  808. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +22 -1
  809. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -1
  810. package/build/dist/UI/Components/Table/CellClassName.js +55 -0
  811. package/build/dist/UI/Components/Table/CellClassName.js.map +1 -0
  812. package/build/dist/UI/Components/Table/TableRow.js +16 -13
  813. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  814. package/build/dist/UI/Components/Table/TableSkeletonRows.js +9 -8
  815. package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -1
  816. package/build/dist/UI/Components/Tooltip/Tooltip.js +25 -1
  817. package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
  818. package/build/dist/UI/Components/Workflow/ComponentsModal.js +47 -30
  819. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  820. package/build/dist/UI/Components/Workflow/NodePlacement.js +37 -0
  821. package/build/dist/UI/Components/Workflow/NodePlacement.js.map +1 -0
  822. package/build/dist/UI/Components/Workflow/Workflow.js +35 -18
  823. package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
  824. package/build/dist/UI/Config.js +10 -20
  825. package/build/dist/UI/Config.js.map +1 -1
  826. package/build/dist/UI/Utils/GlobalKeyboardShortcut.js +138 -0
  827. package/build/dist/UI/Utils/GlobalKeyboardShortcut.js.map +1 -0
  828. package/build/dist/UI/Utils/Telemetry/BrowserTelemetryConfig.js +14 -0
  829. package/build/dist/UI/Utils/Telemetry/BrowserTelemetryConfig.js.map +1 -0
  830. package/build/dist/UI/Utils/Telemetry/Telemetry.js +7 -5
  831. package/build/dist/UI/Utils/Telemetry/Telemetry.js.map +1 -1
  832. package/build/dist/Utils/API.js +67 -5
  833. package/build/dist/Utils/API.js.map +1 -1
  834. package/build/dist/Utils/Dashboard/Components/DashboardMonitorListComponent.js +9 -1
  835. package/build/dist/Utils/Dashboard/Components/DashboardMonitorListComponent.js.map +1 -1
  836. package/build/dist/Utils/Dashboard/LabelVariable.js +96 -0
  837. package/build/dist/Utils/Dashboard/LabelVariable.js.map +1 -0
  838. package/build/dist/Utils/Dashboard/VariableUrlState.js +19 -4
  839. package/build/dist/Utils/Dashboard/VariableUrlState.js.map +1 -1
  840. package/build/dist/Utils/HTTPResponseBodyReader.js +157 -0
  841. package/build/dist/Utils/HTTPResponseBodyReader.js.map +1 -0
  842. package/build/dist/Utils/MetricUnitUtil.js +26 -0
  843. package/build/dist/Utils/MetricUnitUtil.js.map +1 -1
  844. package/build/dist/Utils/Monitor/DeviceMacLearningUtil.js +112 -0
  845. package/build/dist/Utils/Monitor/DeviceMacLearningUtil.js.map +1 -0
  846. package/build/dist/Utils/Monitor/MetricValueFormatter.js +276 -0
  847. package/build/dist/Utils/Monitor/MetricValueFormatter.js.map +1 -0
  848. package/build/dist/Utils/Monitor/MonitorTemplateCustomFieldUtil.js +101 -0
  849. package/build/dist/Utils/Monitor/MonitorTemplateCustomFieldUtil.js.map +1 -0
  850. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +7 -2
  851. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -1
  852. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +484 -0
  853. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  854. package/build/dist/Utils/NetworkAutomation/AutoImportRunChain.js +59 -0
  855. package/build/dist/Utils/NetworkAutomation/AutoImportRunChain.js.map +1 -0
  856. package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js +69 -0
  857. package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js.map +1 -0
  858. package/build/dist/Utils/Rum/ChunkMath.js +76 -0
  859. package/build/dist/Utils/Rum/ChunkMath.js.map +1 -1
  860. package/build/dist/Utils/Rum/SessionReplayHealth.js +534 -0
  861. package/build/dist/Utils/Rum/SessionReplayHealth.js.map +1 -0
  862. package/build/dist/Utils/Rum/SessionReplayStringMap.js +165 -0
  863. package/build/dist/Utils/Rum/SessionReplayStringMap.js.map +1 -0
  864. package/build/dist/Utils/Schema/ModelSchema.js +1 -0
  865. package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
  866. package/build/dist/Utils/StatusPage/ResourceSearch.js +200 -0
  867. package/build/dist/Utils/StatusPage/ResourceSearch.js.map +1 -0
  868. package/build/dist/Utils/Telemetry/OriginAllowList.js +299 -0
  869. package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -0
  870. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js +147 -0
  871. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js.map +1 -0
  872. package/build/dist/Utils/ValueFormatter.js +32 -1
  873. package/build/dist/Utils/ValueFormatter.js.map +1 -1
  874. package/jest.config.json +2 -0
  875. package/package.json +1 -1
  876. package/test-setup.sh +9 -9
  877. package/tsconfig.json +51 -11
@@ -0,0 +1,1163 @@
1
+ import { describe, expect, test, beforeEach, afterEach } from "@jest/globals";
2
+ import TelemetryIngest, {
3
+ getEffectiveRequestsPerMinuteLimit,
4
+ TelemetryRequest,
5
+ } from "../../../Server/Middleware/TelemetryIngest";
6
+ import TelemetryIngestionKeyService from "../../../Server/Services/TelemetryIngestionKeyService";
7
+ import Response from "../../../Server/Utils/Response";
8
+ import logger from "../../../Server/Utils/Logger";
9
+ import TelemetryIngestionKeyRateLimiter, {
10
+ TelemetryIngestionKeyLimitDecision,
11
+ TelemetryIngestionKeyLimitOutcome,
12
+ } from "../../../Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter";
13
+ import {
14
+ ExpressRequest,
15
+ ExpressResponse,
16
+ NextFunction,
17
+ } from "../../../Server/Utils/Express";
18
+ import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
19
+ import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
20
+ import TooManyRequestsException from "../../../Types/Exception/TooManyRequestsException";
21
+ import ObjectID from "../../../Types/ObjectID";
22
+ import TelemetryIngestionKeyPolicy, {
23
+ DEFAULT_BROWSER_KEY_REQUESTS_PER_MINUTE,
24
+ } from "../../../Types/Telemetry/TelemetryIngestionKeyPolicy";
25
+ import TelemetryIngestionKeyType from "../../../Types/Telemetry/TelemetryIngestionKeyType";
26
+ import TelemetryIngestSurface, {
27
+ BROWSER_ALLOWED_INGEST_SURFACES,
28
+ getIngestSurfaceReadableName,
29
+ } from "../../../Types/Telemetry/TelemetryIngestSurface";
30
+
31
+ /*
32
+ * The ingest guard is the ONLY thing standing between a telemetry ingestion
33
+ * key that is deliberately published in a customer's page source and the write
34
+ * side of their project. Everything else about browser keys - the origin
35
+ * allowlist column, the surface enum, the expiry, the kill switch - is inert
36
+ * configuration until this middleware reads it, so every constraint the
37
+ * feature claims has to be pinned HERE or it is not enforced anywhere.
38
+ *
39
+ * Four properties, in order of how expensive they are to get wrong:
40
+ *
41
+ * 1. A BROWSER KEY FAILS CLOSED ON EVERY AXIS. Wrong surface, wrong origin,
42
+ * missing Origin header and - the one that matters most - an EMPTY
43
+ * allowlist are all refusals. Empty-means-any-origin is the reading
44
+ * SessionReplayGateCache deliberately takes for its own column, and
45
+ * taking it here would recreate exactly the unbounded public write
46
+ * credential this feature exists to delete. The legacy unnamed-surface
47
+ * alias refuses browser keys too, so a route someone forgets to migrate
48
+ * is a support ticket rather than a hole.
49
+ *
50
+ * 2. A SERVER KEY BEHAVES EXACTLY AS IT DID BEFORE THIS SHIPPED. Every key
51
+ * that predates the feature resolves as Server, enabled, no expiry, no
52
+ * limit, and it must reach every surface, ignore the Origin header
53
+ * entirely, and - asserted explicitly - never touch the rate limiter,
54
+ * because that path fronts every OTLP payload the product accepts and is
55
+ * not allowed to grow a Redis round trip.
56
+ *
57
+ * 3. THE LIMITER FAILS OPEN. CounterUnavailable admits the request. That is
58
+ * a deliberate trade - a Redis blip must not become permanent,
59
+ * unreplayable customer data loss with their incident dashboards dark -
60
+ * and a future "hardening" pass would otherwise flip it silently.
61
+ *
62
+ * 4. THE TOKEN NEVER LEAKS. Ingestion keys are secrets; a refusal that
63
+ * echoes the presented value into a log line or a response body is a
64
+ * credential disclosure. Asserted across every refusal branch at once.
65
+ *
66
+ * Nothing here touches Postgres or Redis: the key resolver, the limiter and
67
+ * the responder are all mocked at the module boundary.
68
+ */
69
+
70
+ /*
71
+ * The token resolver is mocked so every key shape - disabled, expired,
72
+ * browser, server - can be forced without a database.
73
+ */
74
+ jest.mock("../../../Server/Services/TelemetryIngestionKeyService", () => {
75
+ return {
76
+ __esModule: true,
77
+ default: {
78
+ getPolicyFromSecretKey: jest.fn(),
79
+ getProjectIdFromSecretKey: jest.fn(),
80
+ markUsed: jest.fn(),
81
+ },
82
+ };
83
+ });
84
+
85
+ jest.mock("../../../Server/Utils/Response", () => {
86
+ return {
87
+ __esModule: true,
88
+ default: {
89
+ sendErrorResponse: jest.fn(),
90
+ },
91
+ };
92
+ });
93
+
94
+ /*
95
+ * Only the default export (the class with consume()) is replaced. The real
96
+ * outcome enum is kept, because the middleware compares against it by value
97
+ * and a hand-rolled copy in the mock would let a renamed member pass this
98
+ * suite while breaking production.
99
+ */
100
+ jest.mock(
101
+ "../../../Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter",
102
+ () => {
103
+ const actual: Record<string, unknown> = jest.requireActual(
104
+ "../../../Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter",
105
+ ) as Record<string, unknown>;
106
+
107
+ return {
108
+ __esModule: true,
109
+ ...actual,
110
+ default: {
111
+ consume: jest.fn(),
112
+ },
113
+ };
114
+ },
115
+ );
116
+
117
+ type MockFn = jest.Mock;
118
+
119
+ const PROJECT_ID: string = "5d3b0f1a-0000-4000-8000-000000000001";
120
+ const INGESTION_KEY_ID: string = "5d3b0f1a-0000-4000-8000-000000000002";
121
+
122
+ /*
123
+ * Shaped like a real (mistyped) ingestion key so the substring checks in the
124
+ * hygiene suite are meaningful.
125
+ */
126
+ const SENTINEL_TOKEN: string = "sentinel-secret-ingestion-key-12345";
127
+
128
+ const ALLOWED_ORIGIN: string = "https://app.example.com";
129
+
130
+ const ALL_SURFACES: Array<TelemetryIngestSurface> = Object.values(
131
+ TelemetryIngestSurface,
132
+ ) as Array<TelemetryIngestSurface>;
133
+
134
+ const BROWSER_DISALLOWED_SURFACES: Array<TelemetryIngestSurface> =
135
+ ALL_SURFACES.filter((surface: TelemetryIngestSurface): boolean => {
136
+ return !BROWSER_ALLOWED_INGEST_SURFACES.has(surface);
137
+ });
138
+
139
+ type BuildPolicyFunction = (
140
+ overrides: Partial<TelemetryIngestionKeyPolicy>,
141
+ ) => TelemetryIngestionKeyPolicy;
142
+
143
+ const buildPolicy: BuildPolicyFunction = (
144
+ overrides: Partial<TelemetryIngestionKeyPolicy>,
145
+ ): TelemetryIngestionKeyPolicy => {
146
+ return {
147
+ ingestionKeyId: new ObjectID(INGESTION_KEY_ID),
148
+ projectId: new ObjectID(PROJECT_ID),
149
+ keyType: TelemetryIngestionKeyType.Server,
150
+ allowedOrigins: [],
151
+ pinnedServiceName: null,
152
+ isEnabled: true,
153
+ expiresAt: null,
154
+ requestsPerMinuteLimit: null,
155
+ ...overrides,
156
+ };
157
+ };
158
+
159
+ const buildBrowserPolicy: BuildPolicyFunction = (
160
+ overrides: Partial<TelemetryIngestionKeyPolicy>,
161
+ ): TelemetryIngestionKeyPolicy => {
162
+ return buildPolicy({
163
+ keyType: TelemetryIngestionKeyType.Browser,
164
+ allowedOrigins: [ALLOWED_ORIGIN],
165
+ ...overrides,
166
+ });
167
+ };
168
+
169
+ type ResolveToFunction = (policy: TelemetryIngestionKeyPolicy | null) => void;
170
+
171
+ const resolveTo: ResolveToFunction = (
172
+ policy: TelemetryIngestionKeyPolicy | null,
173
+ ): void => {
174
+ (
175
+ TelemetryIngestionKeyService.getPolicyFromSecretKey as MockFn
176
+ ).mockResolvedValue(policy as never);
177
+ };
178
+
179
+ interface RunResult {
180
+ req: ExpressRequest;
181
+ res: ExpressResponse;
182
+ next: MockFn;
183
+ setHeader: MockFn;
184
+ }
185
+
186
+ type RunFunction = (
187
+ surface: TelemetryIngestSurface | null,
188
+ headers: Record<string, string>,
189
+ ) => Promise<RunResult>;
190
+
191
+ /*
192
+ * `surface === null` runs the legacy isAuthorizedServiceMiddleware alias,
193
+ * which is the un-migrated-route case rather than a separate code path.
194
+ */
195
+ const run: RunFunction = async (
196
+ surface: TelemetryIngestSurface | null,
197
+ headers: Record<string, string>,
198
+ ): Promise<RunResult> => {
199
+ const req: ExpressRequest = {
200
+ headers,
201
+ id: "test-request-id",
202
+ } as unknown as ExpressRequest;
203
+
204
+ const setHeader: MockFn = jest.fn();
205
+ const res: ExpressResponse = {
206
+ setHeader,
207
+ } as unknown as ExpressResponse;
208
+ const next: MockFn = jest.fn();
209
+
210
+ if (surface === null) {
211
+ await TelemetryIngest.isAuthorizedServiceMiddleware(
212
+ req,
213
+ res,
214
+ next as unknown as NextFunction,
215
+ );
216
+ } else {
217
+ await TelemetryIngest.forSurface(surface)(
218
+ req,
219
+ res,
220
+ next as unknown as NextFunction,
221
+ );
222
+ }
223
+
224
+ return { req, res, next, setHeader };
225
+ };
226
+
227
+ type TokenHeadersFunction = (
228
+ extra?: Record<string, string>,
229
+ ) => Record<string, string>;
230
+
231
+ const tokenHeaders: TokenHeadersFunction = (
232
+ extra?: Record<string, string>,
233
+ ): Record<string, string> => {
234
+ return {
235
+ "x-oneuptime-token": SENTINEL_TOKEN,
236
+ ...(extra || {}),
237
+ };
238
+ };
239
+
240
+ type RefusalFunction = () => Error;
241
+
242
+ /*
243
+ * The exception handed to Response.sendErrorResponse IS the status code:
244
+ * NotAuthenticatedException is 401, NotAuthorizedException 403,
245
+ * TooManyRequestsException 429. Asserting on the class is asserting on what
246
+ * the caller receives.
247
+ */
248
+ const refusal: RefusalFunction = (): Error => {
249
+ const sendErrorResponse: MockFn = Response.sendErrorResponse as MockFn;
250
+
251
+ expect(sendErrorResponse).toHaveBeenCalledTimes(1);
252
+
253
+ return sendErrorResponse.mock.calls[0]?.[2] as Error;
254
+ };
255
+
256
+ type LimiterAnswersFunction = (
257
+ outcome: TelemetryIngestionKeyLimitOutcome,
258
+ extra?: Partial<TelemetryIngestionKeyLimitDecision>,
259
+ ) => void;
260
+
261
+ const limiterAnswers: LimiterAnswersFunction = (
262
+ outcome: TelemetryIngestionKeyLimitOutcome,
263
+ extra?: Partial<TelemetryIngestionKeyLimitDecision>,
264
+ ): void => {
265
+ (TelemetryIngestionKeyRateLimiter.consume as MockFn).mockResolvedValue({
266
+ outcome,
267
+ ...(extra || {}),
268
+ } as never);
269
+ };
270
+
271
+ type ConsumeArgsFunction = () => Record<string, unknown>;
272
+
273
+ const firstConsumeCallArgs: ConsumeArgsFunction = (): Record<
274
+ string,
275
+ unknown
276
+ > => {
277
+ return (TelemetryIngestionKeyRateLimiter.consume as MockFn).mock
278
+ .calls[0]?.[0] as Record<string, unknown>;
279
+ };
280
+
281
+ type ArrangeDefaultsFunction = () => void;
282
+
283
+ const arrangeDefaults: ArrangeDefaultsFunction = (): void => {
284
+ /*
285
+ * markUsed is fire-and-forget with a .catch() attached, so it has to return
286
+ * a promise or the success path throws before it ever reaches next().
287
+ */
288
+ (TelemetryIngestionKeyService.markUsed as MockFn).mockResolvedValue(
289
+ undefined as never,
290
+ );
291
+
292
+ limiterAnswers(TelemetryIngestionKeyLimitOutcome.Allowed);
293
+ };
294
+
295
+ describe("TelemetryIngest browser ingestion key guard", () => {
296
+ beforeEach(() => {
297
+ jest.clearAllMocks();
298
+ arrangeDefaults();
299
+ });
300
+
301
+ describe("token resolution", () => {
302
+ test("a request with no ingestion token is refused 401 without consulting the resolver", async () => {
303
+ const result: RunResult = await run(
304
+ TelemetryIngestSurface.OtelTraces,
305
+ {},
306
+ );
307
+
308
+ expect(
309
+ TelemetryIngestionKeyService.getPolicyFromSecretKey as MockFn,
310
+ ).not.toHaveBeenCalled();
311
+ expect(result.next).not.toHaveBeenCalled();
312
+
313
+ const error: Error = refusal();
314
+ expect(error).toBeInstanceOf(NotAuthenticatedException);
315
+ expect(error.message).toBe(
316
+ "Missing ingestion token. Send your OneUptime telemetry ingestion key in the x-oneuptime-token header.",
317
+ );
318
+ });
319
+
320
+ test("a token that resolves to no key is refused 401 with the unchanged invalid-token message", async () => {
321
+ resolveTo(null);
322
+
323
+ const result: RunResult = await run(
324
+ TelemetryIngestSurface.OtelTraces,
325
+ tokenHeaders(),
326
+ );
327
+
328
+ expect(result.next).not.toHaveBeenCalled();
329
+
330
+ const error: Error = refusal();
331
+ expect(error).toBeInstanceOf(NotAuthenticatedException);
332
+ expect(error.message).toBe(
333
+ "Invalid ingestion token. Send a valid OneUptime telemetry ingestion key in the x-oneuptime-token header.",
334
+ );
335
+ });
336
+
337
+ test("all three accepted header names still carry the ingestion token", async () => {
338
+ for (const headerName of [
339
+ "x-oneuptime-token",
340
+ "x-oneuptime-service-token",
341
+ "x-oneuptime-ingestion-key",
342
+ ]) {
343
+ jest.clearAllMocks();
344
+ arrangeDefaults();
345
+ resolveTo(buildPolicy({}));
346
+
347
+ const result: RunResult = await run(TelemetryIngestSurface.OtelTraces, {
348
+ [headerName]: SENTINEL_TOKEN,
349
+ });
350
+
351
+ expect(
352
+ TelemetryIngestionKeyService.getPolicyFromSecretKey as MockFn,
353
+ ).toHaveBeenCalledWith(SENTINEL_TOKEN);
354
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
355
+ expect(result.next).toHaveBeenCalledTimes(1);
356
+ }
357
+ });
358
+ });
359
+
360
+ /*
361
+ * Everything in this block is behaviour that existed before browser keys
362
+ * did. A failure here is a regression for every installation on upgrade day,
363
+ * not a gap in a new feature.
364
+ */
365
+ describe("server key backwards compatibility", () => {
366
+ test("an enabled server key is admitted on every ingest surface, with the project and policy put on the request", async () => {
367
+ for (const surface of ALL_SURFACES) {
368
+ jest.clearAllMocks();
369
+ arrangeDefaults();
370
+
371
+ const policy: TelemetryIngestionKeyPolicy = buildPolicy({});
372
+ resolveTo(policy);
373
+
374
+ const result: RunResult = await run(surface, tokenHeaders());
375
+
376
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
377
+ expect(result.next).toHaveBeenCalledTimes(1);
378
+ expect((result.req as TelemetryRequest).projectId.toString()).toBe(
379
+ PROJECT_ID,
380
+ );
381
+ expect((result.req as TelemetryRequest).ingestionKeyPolicy).toBe(
382
+ policy,
383
+ );
384
+ }
385
+ });
386
+
387
+ test("a server key with no configured limit never reaches the rate limiter at all", async () => {
388
+ resolveTo(buildPolicy({ requestsPerMinuteLimit: null }));
389
+
390
+ const result: RunResult = await run(
391
+ TelemetryIngestSurface.OtelTraces,
392
+ tokenHeaders(),
393
+ );
394
+
395
+ /*
396
+ * Not "is allowed" - never CALLED. The overwhelmingly common request in
397
+ * production is exactly this shape, and a Redis round trip added to it
398
+ * is latency on every OTLP payload the product accepts.
399
+ */
400
+ expect(
401
+ TelemetryIngestionKeyRateLimiter.consume as MockFn,
402
+ ).not.toHaveBeenCalled();
403
+ expect(result.next).toHaveBeenCalledTimes(1);
404
+ });
405
+
406
+ test("a server key is admitted when the request sends no Origin header", async () => {
407
+ resolveTo(buildPolicy({ allowedOrigins: [ALLOWED_ORIGIN] }));
408
+
409
+ const result: RunResult = await run(
410
+ TelemetryIngestSurface.OtelTraces,
411
+ tokenHeaders(),
412
+ );
413
+
414
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
415
+ expect(result.next).toHaveBeenCalledTimes(1);
416
+ });
417
+
418
+ test("a server key is admitted even when the request carries an Origin outside its allowlist", async () => {
419
+ resolveTo(buildPolicy({ allowedOrigins: [ALLOWED_ORIGIN] }));
420
+
421
+ const result: RunResult = await run(
422
+ TelemetryIngestSurface.OtelTraces,
423
+ tokenHeaders({ origin: "https://not-on-the-list.example.com" }),
424
+ );
425
+
426
+ /*
427
+ * A server key is never published, so an Origin header on a request
428
+ * carrying one says nothing about who is calling. Enforcing it would
429
+ * break every proxy and browser-adjacent server client that sends one.
430
+ */
431
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
432
+ expect(result.next).toHaveBeenCalledTimes(1);
433
+ });
434
+
435
+ test("a policy whose key type is absent is treated as a server key, not as a browser key", async () => {
436
+ /*
437
+ * Every key that predates this feature reads back with keyType NULL.
438
+ * TelemetryIngestionKeyService resolves that to Server, but the guard
439
+ * carries its own copy of the rule (`keyType === Browser`), and that is
440
+ * the one that decides. Pinned here because getting it backwards - a
441
+ * missing type treated as Browser - would refuse every existing
442
+ * customer's server ingest the moment they upgraded: wrong surface,
443
+ * missing Origin header, closed allowlist, all at once.
444
+ */
445
+ resolveTo(
446
+ buildPolicy({
447
+ keyType: null as unknown as TelemetryIngestionKeyType,
448
+ }),
449
+ );
450
+
451
+ const result: RunResult = await run(
452
+ TelemetryIngestSurface.Syslog,
453
+ tokenHeaders(),
454
+ );
455
+
456
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
457
+ expect(result.next).toHaveBeenCalledTimes(1);
458
+ expect(
459
+ TelemetryIngestionKeyRateLimiter.consume as MockFn,
460
+ ).not.toHaveBeenCalled();
461
+ });
462
+
463
+ test("a server key with an explicitly configured limit is rate limited like any other key", async () => {
464
+ resolveTo(buildPolicy({ requestsPerMinuteLimit: 120 }));
465
+
466
+ const result: RunResult = await run(
467
+ TelemetryIngestSurface.OtelTraces,
468
+ tokenHeaders(),
469
+ );
470
+
471
+ expect(
472
+ TelemetryIngestionKeyRateLimiter.consume as MockFn,
473
+ ).toHaveBeenCalledTimes(1);
474
+
475
+ const call: Record<string, unknown> = firstConsumeCallArgs();
476
+ expect(call["limitPerMinute"]).toBe(120);
477
+ expect(String(call["ingestionKeyId"])).toBe(INGESTION_KEY_ID);
478
+ expect(result.next).toHaveBeenCalledTimes(1);
479
+ });
480
+ });
481
+
482
+ describe("kill switch and expiry", () => {
483
+ test("a disabled key is refused 403 whatever its type", async () => {
484
+ for (const keyType of [
485
+ TelemetryIngestionKeyType.Server,
486
+ TelemetryIngestionKeyType.Browser,
487
+ ]) {
488
+ jest.clearAllMocks();
489
+ arrangeDefaults();
490
+ resolveTo(
491
+ buildPolicy({
492
+ keyType,
493
+ isEnabled: false,
494
+ allowedOrigins: [ALLOWED_ORIGIN],
495
+ }),
496
+ );
497
+
498
+ const result: RunResult = await run(
499
+ TelemetryIngestSurface.OtelTraces,
500
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
501
+ );
502
+
503
+ expect(result.next).not.toHaveBeenCalled();
504
+
505
+ const error: Error = refusal();
506
+ expect(error).toBeInstanceOf(NotAuthorizedException);
507
+ expect(error.message).toBe(
508
+ "This telemetry ingestion key has been disabled.",
509
+ );
510
+ }
511
+ });
512
+
513
+ test("the kill switch is checked before the surface and origin rules, so disabling a leaked key always reports as disabled", async () => {
514
+ resolveTo(
515
+ buildBrowserPolicy({
516
+ isEnabled: false,
517
+ allowedOrigins: ["https://only-this.example.com"],
518
+ }),
519
+ );
520
+
521
+ /*
522
+ * Disallowed surface AND a disallowed origin AND disabled. Whichever
523
+ * refusal wins is what a customer sees while working out whether their
524
+ * kill switch actually took effect, so it has to be the disable.
525
+ */
526
+ await run(
527
+ TelemetryIngestSurface.Syslog,
528
+ tokenHeaders({ origin: "https://somewhere-else.example.com" }),
529
+ );
530
+
531
+ const error: Error = refusal();
532
+ expect(error).toBeInstanceOf(NotAuthorizedException);
533
+ expect(error.message).toBe(
534
+ "This telemetry ingestion key has been disabled.",
535
+ );
536
+ });
537
+
538
+ test("a key whose expiry is in the past is refused 401", async () => {
539
+ resolveTo(buildPolicy({ expiresAt: new Date(Date.now() - 60 * 1000) }));
540
+
541
+ const result: RunResult = await run(
542
+ TelemetryIngestSurface.OtelTraces,
543
+ tokenHeaders(),
544
+ );
545
+
546
+ expect(result.next).not.toHaveBeenCalled();
547
+
548
+ const error: Error = refusal();
549
+ expect(error).toBeInstanceOf(NotAuthenticatedException);
550
+ expect(error.message).toBe("This telemetry ingestion key expired.");
551
+ });
552
+
553
+ test("a key whose expiry is exactly now is refused rather than admitted on the boundary", async () => {
554
+ const frozenNow: number = new Date("2026-01-01T00:00:00.000Z").getTime();
555
+ const nowSpy: { mockRestore: () => void } = jest
556
+ .spyOn(Date, "now")
557
+ .mockReturnValue(frozenNow) as unknown as { mockRestore: () => void };
558
+
559
+ try {
560
+ resolveTo(buildPolicy({ expiresAt: new Date(frozenNow) }));
561
+
562
+ const result: RunResult = await run(
563
+ TelemetryIngestSurface.OtelTraces,
564
+ tokenHeaders(),
565
+ );
566
+
567
+ expect(result.next).not.toHaveBeenCalled();
568
+ expect(refusal()).toBeInstanceOf(NotAuthenticatedException);
569
+ } finally {
570
+ nowSpy.mockRestore();
571
+ }
572
+ });
573
+
574
+ test("a key whose expiry is in the future is admitted", async () => {
575
+ resolveTo(
576
+ buildPolicy({ expiresAt: new Date(Date.now() + 60 * 60 * 1000) }),
577
+ );
578
+
579
+ const result: RunResult = await run(
580
+ TelemetryIngestSurface.OtelTraces,
581
+ tokenHeaders(),
582
+ );
583
+
584
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
585
+ expect(result.next).toHaveBeenCalledTimes(1);
586
+ });
587
+
588
+ test("a key with no expiry set never expires", async () => {
589
+ resolveTo(buildPolicy({ expiresAt: null }));
590
+
591
+ const result: RunResult = await run(
592
+ TelemetryIngestSurface.OtelTraces,
593
+ tokenHeaders(),
594
+ );
595
+
596
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
597
+ expect(result.next).toHaveBeenCalledTimes(1);
598
+ });
599
+
600
+ test("the expired-key refusal does not disclose when the key expired", async () => {
601
+ const expiredAt: Date = new Date("2021-03-04T05:06:07.000Z");
602
+ resolveTo(buildPolicy({ expiresAt: expiredAt }));
603
+
604
+ await run(TelemetryIngestSurface.OtelTraces, tokenHeaders());
605
+
606
+ const message: string = refusal().message;
607
+
608
+ /*
609
+ * Whoever is holding a dead key is not entitled to details of the
610
+ * project's credentials; the owner reads the expiry in the dashboard.
611
+ */
612
+ expect(message).not.toContain(expiredAt.toISOString());
613
+ expect(message).not.toContain(String(expiredAt.getTime()));
614
+ expect(message).not.toContain("2021");
615
+ });
616
+ });
617
+
618
+ describe("browser key surface allowlist", () => {
619
+ test("a browser key is admitted on exactly the four surfaces a real browser agent emits", async () => {
620
+ expect(Array.from(BROWSER_ALLOWED_INGEST_SURFACES).sort()).toEqual(
621
+ [
622
+ TelemetryIngestSurface.OtelLogs,
623
+ TelemetryIngestSurface.OtelMetrics,
624
+ TelemetryIngestSurface.OtelTraces,
625
+ TelemetryIngestSurface.SessionReplay,
626
+ ].sort(),
627
+ );
628
+
629
+ for (const surface of Array.from(BROWSER_ALLOWED_INGEST_SURFACES)) {
630
+ jest.clearAllMocks();
631
+ arrangeDefaults();
632
+ resolveTo(buildBrowserPolicy({}));
633
+
634
+ const result: RunResult = await run(
635
+ surface,
636
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
637
+ );
638
+
639
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
640
+ expect(result.next).toHaveBeenCalledTimes(1);
641
+ }
642
+ });
643
+
644
+ test("a browser key is refused 403 on every other surface, naming the surface and pointing at a server key", async () => {
645
+ expect(BROWSER_DISALLOWED_SURFACES.length).toBe(10);
646
+
647
+ for (const surface of BROWSER_DISALLOWED_SURFACES) {
648
+ jest.clearAllMocks();
649
+ arrangeDefaults();
650
+ resolveTo(buildBrowserPolicy({}));
651
+
652
+ const result: RunResult = await run(
653
+ surface,
654
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
655
+ );
656
+
657
+ expect(result.next).not.toHaveBeenCalled();
658
+
659
+ const error: Error = refusal();
660
+ expect(error).toBeInstanceOf(NotAuthorizedException);
661
+ expect(error.message).toBe(
662
+ `A browser ingestion key cannot be used for ${getIngestSurfaceReadableName(
663
+ surface,
664
+ )}. Use a server ingestion key.`,
665
+ );
666
+ }
667
+ });
668
+ });
669
+
670
+ describe("browser key origin allowlist", () => {
671
+ test("a browser key is admitted from an origin on its allowlist", async () => {
672
+ resolveTo(buildBrowserPolicy({ allowedOrigins: [ALLOWED_ORIGIN] }));
673
+
674
+ const result: RunResult = await run(
675
+ TelemetryIngestSurface.OtelTraces,
676
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
677
+ );
678
+
679
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
680
+ expect(result.next).toHaveBeenCalledTimes(1);
681
+ });
682
+
683
+ test("a browser key is admitted from a subdomain covered by a wildcard entry", async () => {
684
+ resolveTo(
685
+ buildBrowserPolicy({ allowedOrigins: ["https://*.example.com"] }),
686
+ );
687
+
688
+ const result: RunResult = await run(
689
+ TelemetryIngestSurface.OtelTraces,
690
+ tokenHeaders({ origin: "https://tenant-42.example.com" }),
691
+ );
692
+
693
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
694
+ expect(result.next).toHaveBeenCalledTimes(1);
695
+ });
696
+
697
+ test("a browser key is refused 403 from an origin outside its allowlist, and the refusal echoes the offending origin", async () => {
698
+ const offendingOrigin: string = "https://attacker.example.net";
699
+ resolveTo(buildBrowserPolicy({ allowedOrigins: [ALLOWED_ORIGIN] }));
700
+
701
+ const result: RunResult = await run(
702
+ TelemetryIngestSurface.OtelTraces,
703
+ tokenHeaders({ origin: offendingOrigin }),
704
+ );
705
+
706
+ expect(result.next).not.toHaveBeenCalled();
707
+
708
+ const error: Error = refusal();
709
+ expect(error).toBeInstanceOf(NotAuthorizedException);
710
+ /*
711
+ * The origin is the caller's own value and never a secret, and a
712
+ * scheme / port / trailing-slash mismatch stays invisible until the two
713
+ * strings are put side by side.
714
+ */
715
+ expect(error.message).toContain(offendingOrigin);
716
+ });
717
+
718
+ test("a browser key request with no Origin header is refused 403 and told the header was missing", async () => {
719
+ resolveTo(buildBrowserPolicy({ allowedOrigins: [ALLOWED_ORIGIN] }));
720
+
721
+ const result: RunResult = await run(
722
+ TelemetryIngestSurface.OtelTraces,
723
+ tokenHeaders(),
724
+ );
725
+
726
+ expect(result.next).not.toHaveBeenCalled();
727
+
728
+ const error: Error = refusal();
729
+ expect(error).toBeInstanceOf(NotAuthorizedException);
730
+ expect(error.message).toContain("did not send an Origin header");
731
+ // "Origin is not allowed" reads like a bug and helps nobody.
732
+ expect(error.message).not.toContain("Origin is not allowed");
733
+ });
734
+
735
+ test("a browser key with an EMPTY allowlist is refused - empty fails closed, it does not mean any origin", async () => {
736
+ resolveTo(buildBrowserPolicy({ allowedOrigins: [] }));
737
+
738
+ const result: RunResult = await run(
739
+ TelemetryIngestSurface.OtelTraces,
740
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
741
+ );
742
+
743
+ /*
744
+ * THE most important assertion in this file. SessionReplayGateCache
745
+ * reads an empty allowlist as "any origin" because that feature shipped
746
+ * that way; reading it the same way here would make a key published in
747
+ * a page usable from anywhere on the internet, which is precisely the
748
+ * credential this feature exists to remove.
749
+ */
750
+ expect(result.next).not.toHaveBeenCalled();
751
+
752
+ const error: Error = refusal();
753
+ expect(error).toBeInstanceOf(NotAuthorizedException);
754
+ });
755
+ });
756
+
757
+ describe("per-key rate limit", () => {
758
+ test("a browser key with no configured limit is held to the shipped browser default", async () => {
759
+ resolveTo(buildBrowserPolicy({ requestsPerMinuteLimit: null }));
760
+
761
+ await run(
762
+ TelemetryIngestSurface.OtelTraces,
763
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
764
+ );
765
+
766
+ expect(
767
+ TelemetryIngestionKeyRateLimiter.consume as MockFn,
768
+ ).toHaveBeenCalledTimes(1);
769
+ expect(firstConsumeCallArgs()["limitPerMinute"]).toBe(
770
+ DEFAULT_BROWSER_KEY_REQUESTS_PER_MINUTE,
771
+ );
772
+ expect(DEFAULT_BROWSER_KEY_REQUESTS_PER_MINUTE).toBe(6000);
773
+ });
774
+
775
+ test("an explicitly configured limit wins for both key types", async () => {
776
+ for (const keyType of [
777
+ TelemetryIngestionKeyType.Server,
778
+ TelemetryIngestionKeyType.Browser,
779
+ ]) {
780
+ jest.clearAllMocks();
781
+ arrangeDefaults();
782
+ resolveTo(
783
+ buildPolicy({
784
+ keyType,
785
+ allowedOrigins: [ALLOWED_ORIGIN],
786
+ requestsPerMinuteLimit: 42,
787
+ }),
788
+ );
789
+
790
+ await run(
791
+ TelemetryIngestSurface.OtelTraces,
792
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
793
+ );
794
+
795
+ expect(firstConsumeCallArgs()["limitPerMinute"]).toBe(42);
796
+ }
797
+ });
798
+
799
+ test("a key over its limit is refused 429 and told when to come back", async () => {
800
+ resolveTo(buildBrowserPolicy({ requestsPerMinuteLimit: 10 }));
801
+ limiterAnswers(TelemetryIngestionKeyLimitOutcome.RateLimited, {
802
+ retryAfterSeconds: 37,
803
+ isFirstRejectionInWindow: true,
804
+ });
805
+
806
+ const result: RunResult = await run(
807
+ TelemetryIngestSurface.OtelTraces,
808
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
809
+ );
810
+
811
+ expect(result.next).not.toHaveBeenCalled();
812
+
813
+ const error: Error = refusal();
814
+ expect(error).toBeInstanceOf(TooManyRequestsException);
815
+ expect(error.message).toBe(
816
+ "Too many telemetry requests for this ingestion key. Please retry later.",
817
+ );
818
+
819
+ /*
820
+ * Without Retry-After every refused client backs off by whatever
821
+ * constant it picked, in lockstep, and re-collides on the next window.
822
+ */
823
+ expect(result.setHeader).toHaveBeenCalledWith("Retry-After", "37");
824
+ });
825
+
826
+ test("an unavailable rate limit counter FAILS OPEN and the telemetry is still accepted", async () => {
827
+ resolveTo(buildBrowserPolicy({ requestsPerMinuteLimit: 10 }));
828
+ limiterAnswers(TelemetryIngestionKeyLimitOutcome.CounterUnavailable);
829
+
830
+ const result: RunResult = await run(
831
+ TelemetryIngestSurface.OtelTraces,
832
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
833
+ );
834
+
835
+ /*
836
+ * Deliberate and documented: a Redis blip must not become permanent,
837
+ * unreplayable customer data loss with their incident dashboards dark
838
+ * at exactly the wrong moment. A future "hardening" change that flips
839
+ * this to a refusal has to fail here first, loudly, rather than in a
840
+ * customer's outage.
841
+ */
842
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
843
+ expect(result.next).toHaveBeenCalledTimes(1);
844
+ expect((result.req as TelemetryRequest).projectId.toString()).toBe(
845
+ PROJECT_ID,
846
+ );
847
+ });
848
+ });
849
+
850
+ /*
851
+ * The limit resolution is exported so its branches can be pinned without an
852
+ * Express request, a mocked service and a fake Redis standing between the
853
+ * test and an arithmetic decision.
854
+ */
855
+ describe("getEffectiveRequestsPerMinuteLimit", () => {
856
+ test("a server key with no configured limit is unlimited", () => {
857
+ expect(
858
+ getEffectiveRequestsPerMinuteLimit(
859
+ buildPolicy({ requestsPerMinuteLimit: null }),
860
+ ),
861
+ ).toBeNull();
862
+ });
863
+
864
+ test("a server key with a configured limit gets the limit it asked for", () => {
865
+ expect(
866
+ getEffectiveRequestsPerMinuteLimit(
867
+ buildPolicy({ requestsPerMinuteLimit: 250 }),
868
+ ),
869
+ ).toBe(250);
870
+ });
871
+
872
+ test("a browser key with no configured limit falls back to the shipped default rather than to unlimited", () => {
873
+ expect(
874
+ getEffectiveRequestsPerMinuteLimit(
875
+ buildBrowserPolicy({ requestsPerMinuteLimit: null }),
876
+ ),
877
+ ).toBe(DEFAULT_BROWSER_KEY_REQUESTS_PER_MINUTE);
878
+ });
879
+
880
+ test("a browser key with a configured limit gets the limit it asked for", () => {
881
+ expect(
882
+ getEffectiveRequestsPerMinuteLimit(
883
+ buildBrowserPolicy({ requestsPerMinuteLimit: 3 }),
884
+ ),
885
+ ).toBe(3);
886
+ });
887
+
888
+ test("a zero, negative, infinite, NaN or non-numeric limit falls back to the key type's default instead of blocking the key", () => {
889
+ const degenerateValues: Array<number> = [
890
+ 0,
891
+ -1,
892
+ Number.NaN,
893
+ Number.POSITIVE_INFINITY,
894
+ "100" as unknown as number,
895
+ ];
896
+
897
+ for (const value of degenerateValues) {
898
+ /*
899
+ * A bad row must not be read as "block everything": that would black
900
+ * out a customer's ingest on a data problem. A Server key falls back
901
+ * to unlimited (its historical behaviour), a Browser key to the
902
+ * shipped ceiling - never to unlimited.
903
+ */
904
+ expect(
905
+ getEffectiveRequestsPerMinuteLimit(
906
+ buildPolicy({ requestsPerMinuteLimit: value }),
907
+ ),
908
+ ).toBeNull();
909
+
910
+ expect(
911
+ getEffectiveRequestsPerMinuteLimit(
912
+ buildBrowserPolicy({ requestsPerMinuteLimit: value }),
913
+ ),
914
+ ).toBe(DEFAULT_BROWSER_KEY_REQUESTS_PER_MINUTE);
915
+ }
916
+ });
917
+ });
918
+
919
+ describe("legacy unnamed-surface alias", () => {
920
+ test("a route that has not been migrated to forSurface refuses a browser key", async () => {
921
+ resolveTo(buildBrowserPolicy({}));
922
+
923
+ const result: RunResult = await run(
924
+ null,
925
+ tokenHeaders({ origin: ALLOWED_ORIGIN }),
926
+ );
927
+
928
+ /*
929
+ * Fail closed on the default. A missed browser-capable route is a
930
+ * public credential reaching an endpoint nobody decided it should
931
+ * reach; a missed server-only route is a support ticket.
932
+ */
933
+ expect(result.next).not.toHaveBeenCalled();
934
+
935
+ const error: Error = refusal();
936
+ expect(error).toBeInstanceOf(NotAuthorizedException);
937
+ expect(error.message).toBe(
938
+ "A browser ingestion key cannot be used for this ingest endpoint. Use a server ingestion key.",
939
+ );
940
+ });
941
+
942
+ test("a route that has not been migrated still works with a server key", async () => {
943
+ resolveTo(buildPolicy({}));
944
+
945
+ const result: RunResult = await run(null, tokenHeaders());
946
+
947
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
948
+ expect(result.next).toHaveBeenCalledTimes(1);
949
+ expect((result.req as TelemetryRequest).projectId.toString()).toBe(
950
+ PROJECT_ID,
951
+ );
952
+ });
953
+ });
954
+
955
+ /*
956
+ * An ingestion key is a secret. Every branch below refuses a request that
957
+ * PRESENTED one, and none of them may write it to a log line (which also
958
+ * lands in the in-process recentLogs ring buffer surfaced on the admin
959
+ * health pages) or echo it back in a response body.
960
+ */
961
+ describe("token hygiene across every refusal branch", () => {
962
+ interface RefusalBranch {
963
+ name: string;
964
+ arrange: () => void;
965
+ surface: TelemetryIngestSurface | null;
966
+ headers: Record<string, string>;
967
+ }
968
+
969
+ const branches: Array<RefusalBranch> = [
970
+ {
971
+ name: "unknown token",
972
+ arrange: (): void => {
973
+ resolveTo(null);
974
+ },
975
+ surface: TelemetryIngestSurface.OtelTraces,
976
+ headers: tokenHeaders(),
977
+ },
978
+ {
979
+ name: "disabled key",
980
+ arrange: (): void => {
981
+ resolveTo(buildPolicy({ isEnabled: false }));
982
+ },
983
+ surface: TelemetryIngestSurface.OtelTraces,
984
+ headers: tokenHeaders(),
985
+ },
986
+ {
987
+ name: "expired key",
988
+ arrange: (): void => {
989
+ resolveTo(
990
+ buildPolicy({ expiresAt: new Date(Date.now() - 60 * 1000) }),
991
+ );
992
+ },
993
+ surface: TelemetryIngestSurface.OtelTraces,
994
+ headers: tokenHeaders(),
995
+ },
996
+ {
997
+ name: "browser key on a disallowed surface",
998
+ arrange: (): void => {
999
+ resolveTo(buildBrowserPolicy({}));
1000
+ },
1001
+ surface: TelemetryIngestSurface.Syslog,
1002
+ headers: tokenHeaders({ origin: ALLOWED_ORIGIN }),
1003
+ },
1004
+ {
1005
+ name: "browser key from a disallowed origin",
1006
+ arrange: (): void => {
1007
+ resolveTo(buildBrowserPolicy({}));
1008
+ },
1009
+ surface: TelemetryIngestSurface.OtelTraces,
1010
+ headers: tokenHeaders({ origin: "https://attacker.example.net" }),
1011
+ },
1012
+ {
1013
+ name: "browser key with no Origin header",
1014
+ arrange: (): void => {
1015
+ resolveTo(buildBrowserPolicy({}));
1016
+ },
1017
+ surface: TelemetryIngestSurface.OtelTraces,
1018
+ headers: tokenHeaders(),
1019
+ },
1020
+ {
1021
+ name: "browser key with an empty allowlist",
1022
+ arrange: (): void => {
1023
+ resolveTo(buildBrowserPolicy({ allowedOrigins: [] }));
1024
+ },
1025
+ surface: TelemetryIngestSurface.OtelTraces,
1026
+ headers: tokenHeaders({ origin: ALLOWED_ORIGIN }),
1027
+ },
1028
+ {
1029
+ name: "rate limited key",
1030
+ arrange: (): void => {
1031
+ resolveTo(buildBrowserPolicy({ requestsPerMinuteLimit: 1 }));
1032
+ limiterAnswers(TelemetryIngestionKeyLimitOutcome.RateLimited, {
1033
+ retryAfterSeconds: 12,
1034
+ isFirstRejectionInWindow: true,
1035
+ });
1036
+ },
1037
+ surface: TelemetryIngestSurface.OtelTraces,
1038
+ headers: tokenHeaders({ origin: ALLOWED_ORIGIN }),
1039
+ },
1040
+ {
1041
+ name: "browser key on the legacy unnamed-surface alias",
1042
+ arrange: (): void => {
1043
+ resolveTo(buildBrowserPolicy({}));
1044
+ },
1045
+ surface: null,
1046
+ headers: tokenHeaders({ origin: ALLOWED_ORIGIN }),
1047
+ },
1048
+ ];
1049
+
1050
+ let loggedArgs: Array<Array<unknown>>;
1051
+ let spies: Array<{ mockRestore: () => void }>;
1052
+
1053
+ beforeEach(() => {
1054
+ loggedArgs = [];
1055
+ spies = ["error", "warn", "info", "debug", "trace"].map(
1056
+ (level: string): { mockRestore: () => void } => {
1057
+ return jest
1058
+ .spyOn(logger, level as "error")
1059
+ .mockImplementation((...args: Array<unknown>) => {
1060
+ loggedArgs.push(args);
1061
+ return undefined as never;
1062
+ }) as unknown as { mockRestore: () => void };
1063
+ },
1064
+ );
1065
+ });
1066
+
1067
+ afterEach(() => {
1068
+ for (const spy of spies) {
1069
+ spy.mockRestore();
1070
+ }
1071
+ });
1072
+
1073
+ test("no refusal branch writes the presented ingestion key to a log line or a response message", async () => {
1074
+ for (const branch of branches) {
1075
+ jest.clearAllMocks();
1076
+ arrangeDefaults();
1077
+ loggedArgs = [];
1078
+ branch.arrange();
1079
+
1080
+ const result: RunResult = await run(branch.surface, branch.headers);
1081
+
1082
+ // Every branch listed here must actually refuse.
1083
+ expect(result.next).not.toHaveBeenCalled();
1084
+
1085
+ const error: Error = refusal();
1086
+ expect(error.message).not.toContain(SENTINEL_TOKEN);
1087
+
1088
+ for (const args of loggedArgs) {
1089
+ expect(JSON.stringify(args)).not.toContain(SENTINEL_TOKEN);
1090
+ }
1091
+ }
1092
+ });
1093
+ });
1094
+
1095
+ describe("last-used bookkeeping", () => {
1096
+ test("markUsed is recorded for the admitting key on success", async () => {
1097
+ resolveTo(buildPolicy({}));
1098
+
1099
+ await run(TelemetryIngestSurface.OtelTraces, tokenHeaders());
1100
+
1101
+ expect(
1102
+ TelemetryIngestionKeyService.markUsed as MockFn,
1103
+ ).toHaveBeenCalledTimes(1);
1104
+ expect(
1105
+ String(
1106
+ (TelemetryIngestionKeyService.markUsed as MockFn).mock.calls[0]?.[0],
1107
+ ),
1108
+ ).toBe(INGESTION_KEY_ID);
1109
+ });
1110
+
1111
+ test("the request is not held up waiting for markUsed to finish", async () => {
1112
+ resolveTo(buildPolicy({}));
1113
+
1114
+ /*
1115
+ * A promise that never settles. If the middleware awaited the
1116
+ * bookkeeping write, next() would never be called and every ingested
1117
+ * payload would carry a database round trip for a column nobody reads
1118
+ * in real time.
1119
+ */
1120
+ (TelemetryIngestionKeyService.markUsed as MockFn).mockReturnValue(
1121
+ new Promise<void>((): void => {}) as never,
1122
+ );
1123
+
1124
+ const result: RunResult = await run(
1125
+ TelemetryIngestSurface.OtelTraces,
1126
+ tokenHeaders(),
1127
+ );
1128
+
1129
+ expect(result.next).toHaveBeenCalledTimes(1);
1130
+ });
1131
+
1132
+ test("a failed markUsed write does not fail the ingest request", async () => {
1133
+ resolveTo(buildPolicy({}));
1134
+ (TelemetryIngestionKeyService.markUsed as MockFn).mockRejectedValue(
1135
+ new Error("database is having a bad day") as never,
1136
+ );
1137
+
1138
+ const warnSpy: { mockRestore: () => void } = jest
1139
+ .spyOn(logger, "warn")
1140
+ .mockImplementation(() => {
1141
+ return undefined as never;
1142
+ }) as unknown as { mockRestore: () => void };
1143
+
1144
+ try {
1145
+ const result: RunResult = await run(
1146
+ TelemetryIngestSurface.OtelTraces,
1147
+ tokenHeaders(),
1148
+ );
1149
+
1150
+ expect(Response.sendErrorResponse as MockFn).not.toHaveBeenCalled();
1151
+ expect(result.next).toHaveBeenCalledTimes(1);
1152
+ // next() with no arguments - an argument would be an Express error.
1153
+ expect(result.next.mock.calls[0]?.length || 0).toBe(0);
1154
+
1155
+ // Let the swallowed rejection settle so it cannot surface elsewhere.
1156
+ await Promise.resolve();
1157
+ await Promise.resolve();
1158
+ } finally {
1159
+ warnSpy.mockRestore();
1160
+ }
1161
+ });
1162
+ });
1163
+ });