@oneuptime/common 12.0.12 → 12.0.14

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 (596) hide show
  1. package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +32 -5
  2. package/Models/DatabaseModels/NetworkDevice.ts +64 -0
  3. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
  4. package/Models/DatabaseModels/StatusPage.ts +59 -0
  5. package/Models/DatabaseModels/StatusPageOidc.ts +2 -0
  6. package/Models/DatabaseModels/UserCall.ts +94 -3
  7. package/Models/DatabaseModels/UserEmail.ts +94 -3
  8. package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
  9. package/Models/DatabaseModels/UserPush.ts +37 -0
  10. package/Models/DatabaseModels/UserSMS.ts +94 -3
  11. package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
  12. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -2
  13. package/Server/API/AIChatAPI.ts +55 -56
  14. package/Server/API/BaseAPI.ts +79 -14
  15. package/Server/API/CommonAPI.ts +89 -0
  16. package/Server/API/MicrosoftTeamsAPI.ts +20 -9
  17. package/Server/API/SlackAPI.ts +13 -10
  18. package/Server/API/StatusPageAPI.ts +2197 -2128
  19. package/Server/API/TelemetryAPI.ts +72 -3
  20. package/Server/API/UserCallAPI.ts +53 -45
  21. package/Server/API/UserEmailAPI.ts +53 -44
  22. package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
  23. package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
  24. package/Server/API/UserPushAPI.ts +126 -2
  25. package/Server/API/UserSmsAPI.ts +53 -44
  26. package/Server/API/UserWhatsAppAPI.ts +53 -50
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.ts +30 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.ts +47 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  33. package/Server/Middleware/UserAuthorization.ts +11 -2
  34. package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
  35. package/Server/Services/AnalyticsDatabaseService.ts +169 -0
  36. package/Server/Services/ApiKeyPermissionService.ts +116 -2
  37. package/Server/Services/DatabaseService.ts +118 -6
  38. package/Server/Services/LogAggregationService.ts +39 -0
  39. package/Server/Services/LogService.ts +21 -0
  40. package/Server/Services/NetworkSiteService.ts +12 -0
  41. package/Server/Services/PushNotificationService.ts +127 -12
  42. package/Server/Services/SpanService.ts +21 -0
  43. package/Server/Services/TeamMemberService.ts +53 -13
  44. package/Server/Services/TraceAggregationService.ts +15 -0
  45. package/Server/Services/UserCallService.ts +55 -24
  46. package/Server/Services/UserEmailService.ts +83 -17
  47. package/Server/Services/UserIncomingCallNumberService.ts +49 -85
  48. package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
  49. package/Server/Services/UserNotificationRuleService.ts +26 -0
  50. package/Server/Services/UserPushService.ts +89 -0
  51. package/Server/Services/UserSmsService.ts +50 -17
  52. package/Server/Services/UserWhatsAppService.ts +48 -15
  53. package/Server/Services/WorkspaceNotificationRuleService.ts +172 -220
  54. package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -0
  55. package/Server/Types/Database/Permissions/AccessControlPermission.ts +47 -16
  56. package/Server/Types/Database/QueryHelper.ts +30 -0
  57. package/Server/Utils/APIKey/AccessPermission.ts +16 -40
  58. package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
  59. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +144 -0
  60. package/Server/Utils/ChannelVerification.ts +510 -0
  61. package/Server/Utils/LogRedaction.ts +576 -0
  62. package/Server/Utils/Logger.ts +123 -46
  63. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
  64. package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +94 -23
  65. package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
  66. package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
  67. package/Server/Utils/Monitor/MonitorResource.ts +29 -9
  68. package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
  69. package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
  70. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +28 -7
  71. package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
  72. package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
  73. package/Server/Utils/SessionReplay/SessionReplayGateCacheStore.ts +56 -10
  74. package/Server/Utils/StartServer.ts +30 -9
  75. package/Server/Utils/StatusPageSearchEngineIndexing.ts +33 -0
  76. package/Server/Utils/Telemetry/ResourceEntityFilter.ts +441 -0
  77. package/Server/Utils/TotpAuth.ts +137 -9
  78. package/Server/Utils/UserRegistrationToken.ts +182 -0
  79. package/Server/Utils/VerificationCode.ts +134 -0
  80. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +488 -46
  81. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
  82. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
  83. package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
  84. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
  85. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
  86. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +328 -0
  87. package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +130 -0
  88. package/Tests/Models/DatabaseModels/DatabaseBaseModelToJSONObjectCache.test.ts +180 -0
  89. package/Tests/Models/StatusPageEnableSearchEngineIndexing.test.ts +157 -0
  90. package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
  91. package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +23 -1
  92. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +785 -0
  93. package/Tests/Server/API/BaseAPIApiKeyAuth.test.ts +21 -8
  94. package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
  95. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +290 -0
  96. package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +7 -1
  97. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
  98. package/Tests/Server/API/StatusPageOverviewCache.test.ts +474 -0
  99. package/Tests/Server/API/StatusPageSeoSearchEngineIndexing.test.ts +189 -0
  100. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
  101. package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
  102. package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
  103. package/Tests/Server/API/UserSmsApi.test.ts +107 -14
  104. package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
  105. package/Tests/Server/Infrastructure/InMemoryTTLCache.test.ts +158 -0
  106. package/Tests/Server/Infrastructure/Postgres/DeviceRoleAndDeclaredLinkParentMigration.test.ts +9 -60
  107. package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +315 -0
  108. package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +24 -15
  109. package/Tests/Server/Middleware/UserAuthorization.test.ts +79 -0
  110. package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
  111. package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +280 -0
  112. package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
  113. package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
  114. package/Tests/Server/Services/ApiKeyPermissionService.test.ts +347 -0
  115. package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
  116. package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
  117. package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
  118. package/Tests/Server/Services/DatabaseServiceUpdateDebugLogging.test.ts +282 -0
  119. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
  120. package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
  121. package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
  122. package/Tests/Server/Services/NetworkSiteService.test.ts +56 -2
  123. package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
  124. package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
  125. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
  126. package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
  127. package/Tests/Server/Services/TelemetryResourceFacetFilters.test.ts +267 -0
  128. package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
  129. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
  130. package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
  131. package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
  132. package/Tests/Server/Services/WorkspaceNotificationRuleTestRuleChannels.test.ts +702 -0
  133. package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
  134. package/Tests/Server/Types/Database/Permissions/AccessControlPermission.test.ts +165 -0
  135. package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
  136. package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
  137. package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
  138. package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
  139. package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
  140. package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +48 -36
  141. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +213 -0
  142. package/Tests/Server/Utils/Browser.test.ts +162 -0
  143. package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
  144. package/Tests/Server/Utils/Express.test.ts +371 -0
  145. package/Tests/Server/Utils/LogRedaction.test.ts +415 -0
  146. package/Tests/Server/Utils/LoggerCredentialLeak.test.ts +245 -0
  147. package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
  148. package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
  149. package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
  150. package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
  151. package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +374 -4
  152. package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
  153. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
  154. package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
  155. package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
  156. package/Tests/Server/Utils/Monitor/MonitorResourceIngestedStepSelection.test.ts +455 -0
  157. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
  158. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
  159. package/Tests/Server/Utils/Monitor/NetworkDeviceReachabilityRoundTrip.test.ts +369 -0
  160. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +86 -8
  161. package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
  162. package/Tests/Server/Utils/PrivacyFilterUtil.test.ts +64 -0
  163. package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
  164. package/Tests/Server/Utils/SessionReplay/SessionReplayGateCacheStore.test.ts +207 -0
  165. package/Tests/Server/Utils/StartServerBodyVerify.test.ts +335 -0
  166. package/Tests/Server/Utils/StatusPageSearchEngineIndexing.test.ts +60 -0
  167. package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
  168. package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +435 -0
  169. package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
  170. package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
  171. package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
  172. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +607 -62
  173. package/Tests/Server/Utils/Workspace/MicrosoftTeamsInstalledTeamIdSpace.test.ts +778 -0
  174. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +44 -10
  175. package/Tests/Types/API/HostnameFromAuthority.test.ts +164 -0
  176. package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
  177. package/Tests/Types/Call/CallRequest.test.ts +189 -0
  178. package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
  179. package/Tests/Types/Database/AccessControl/ColumnAccessControlCache.test.ts +344 -0
  180. package/Tests/Types/Database/DatabasePropertyFindOperator.test.ts +518 -0
  181. package/Tests/Types/Database/TableColumnMetadataCache.test.ts +286 -0
  182. package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
  183. package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
  184. package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
  185. package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
  186. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
  187. package/Tests/Types/Monitor/MonitorStep.test.ts +100 -0
  188. package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +360 -0
  189. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
  190. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
  191. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
  192. package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
  193. package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
  194. package/Tests/Types/StatusPage/SearchEngineIndexing.test.ts +86 -0
  195. package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +254 -0
  196. package/Tests/Types/TextRandomGeneration.test.ts +211 -0
  197. package/Tests/UI/Components/Button.test.tsx +175 -1
  198. package/Tests/UI/Components/CardSelect.test.tsx +1021 -0
  199. package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
  200. package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
  201. package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
  202. package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
  203. package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
  204. package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
  205. package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
  206. package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
  207. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
  208. package/Tests/UI/Components/List.test.tsx +9 -2
  209. package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
  210. package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
  211. package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
  212. package/Tests/UI/Components/MasterPage.test.tsx +36 -1
  213. package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
  214. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
  215. package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
  216. package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
  217. package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
  218. package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
  219. package/Tests/UI/Components/Skeleton.test.tsx +71 -0
  220. package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
  221. package/Tests/UI/Components/Tabs.test.tsx +24 -0
  222. package/Tests/UI/Components/Toast.test.tsx +130 -7
  223. package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
  224. package/Tests/UI/Utils/Dropdown.test.ts +423 -0
  225. package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
  226. package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
  227. package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
  228. package/Tests/Utils/API.test.ts +16 -2
  229. package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
  230. package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
  231. package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
  232. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +66 -1
  233. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +115 -6
  234. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +610 -0
  235. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +114 -45
  236. package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
  237. package/Types/API/Hostname.ts +79 -0
  238. package/Types/Database/AccessControl/ColumnAccessControl.ts +33 -11
  239. package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +33 -11
  240. package/Types/Database/DatabaseProperty.ts +38 -0
  241. package/Types/Database/TableColumn.ts +34 -7
  242. package/Types/Email/EmailTemplateType.ts +1 -0
  243. package/Types/Events/Recurring.ts +16 -1
  244. package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
  245. package/Types/Monitor/MonitorStep.ts +13 -1
  246. package/Types/Monitor/MonitorType.ts +345 -40
  247. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
  248. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
  249. package/Types/Monitor/SSLMonitor/SslMonitorResponse.ts +43 -0
  250. package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
  251. package/Types/Permission.ts +35 -0
  252. package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
  253. package/Types/PushNotification/PushNotificationMessage.ts +15 -0
  254. package/Types/PushNotification/PushNotificationRequest.ts +8 -16
  255. package/Types/Service/ServiceLanguage.ts +144 -0
  256. package/Types/StatusPage/SearchEngineIndexing.ts +61 -0
  257. package/Types/Telemetry/ResourceEntityFacet.ts +211 -0
  258. package/Types/Text.ts +111 -19
  259. package/UI/Components/Button/Button.tsx +27 -14
  260. package/UI/Components/CardSelect/CardSelect.tsx +714 -105
  261. package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
  262. package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
  263. package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
  264. package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
  265. package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
  266. package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
  267. package/UI/Components/CommandPalette/Types.ts +49 -0
  268. package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
  269. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  270. package/UI/Components/EmptyState/EmptyState.tsx +8 -1
  271. package/UI/Components/Feed/FeedItem.tsx +1 -1
  272. package/UI/Components/Footer/Footer.tsx +32 -6
  273. package/UI/Components/Forms/Fields/FormField.tsx +3 -0
  274. package/UI/Components/Forms/Types/Field.ts +8 -0
  275. package/UI/Components/List/List.tsx +37 -5
  276. package/UI/Components/List/ListSkeleton.tsx +54 -0
  277. package/UI/Components/Loader/PageLoader.tsx +29 -8
  278. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +26 -4
  279. package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +23 -2
  280. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
  281. package/UI/Components/MasterPage/MasterPage.tsx +24 -11
  282. package/UI/Components/Modal/Modal.tsx +2 -2
  283. package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
  284. package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
  285. package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
  286. package/UI/Components/Navbar/NavBar.tsx +14 -1
  287. package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
  288. package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
  289. package/UI/Components/SideOver/SideOver.tsx +37 -2
  290. package/UI/Components/Skeleton/Skeleton.tsx +53 -0
  291. package/UI/Components/Table/Table.tsx +74 -44
  292. package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
  293. package/UI/Components/Tabs/Tab.tsx +1 -1
  294. package/UI/Components/Toast/Toast.tsx +118 -53
  295. package/UI/Components/Toast/ToastInit.tsx +82 -32
  296. package/UI/Styles/Theme.css +40 -0
  297. package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
  298. package/UI/Utils/ModelListCache.ts +188 -0
  299. package/UI/Utils/Project.ts +29 -0
  300. package/Utils/API.ts +6 -1
  301. package/Utils/Monitor/MonitorMetricType.ts +16 -1
  302. package/Utils/Monitor/NetworkTopologyUtil.ts +60 -8
  303. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +262 -0
  304. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +41 -24
  305. package/Utils/Telemetry/CrossSignalScope.ts +75 -4
  306. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +20 -4
  307. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
  308. package/build/dist/Models/DatabaseModels/NetworkDevice.js +66 -0
  309. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  310. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
  311. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  312. package/build/dist/Models/DatabaseModels/StatusPage.js +60 -0
  313. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  314. package/build/dist/Models/DatabaseModels/StatusPageOidc.js +2 -0
  315. package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
  316. package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
  317. package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
  318. package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
  319. package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
  320. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
  321. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
  322. package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
  323. package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
  324. package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
  325. package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
  326. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
  327. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
  328. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  329. package/build/dist/Server/API/AIChatAPI.js +48 -35
  330. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  331. package/build/dist/Server/API/BaseAPI.js +69 -13
  332. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  333. package/build/dist/Server/API/CommonAPI.js +59 -0
  334. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  335. package/build/dist/Server/API/MicrosoftTeamsAPI.js +20 -6
  336. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  337. package/build/dist/Server/API/SlackAPI.js +13 -10
  338. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  339. package/build/dist/Server/API/StatusPageAPI.js +745 -673
  340. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  341. package/build/dist/Server/API/TelemetryAPI.js +34 -3
  342. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  343. package/build/dist/Server/API/UserCallAPI.js +42 -38
  344. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  345. package/build/dist/Server/API/UserEmailAPI.js +42 -38
  346. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  347. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
  348. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  349. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
  350. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
  351. package/build/dist/Server/API/UserPushAPI.js +95 -2
  352. package/build/dist/Server/API/UserPushAPI.js.map +1 -1
  353. package/build/dist/Server/API/UserSmsAPI.js +42 -38
  354. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  355. package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
  356. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  357. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
  358. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
  359. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
  360. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
  361. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.js +23 -0
  362. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.js.map +1 -0
  363. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.js +34 -0
  364. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.js.map +1 -0
  365. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
  366. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
  367. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  368. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  369. package/build/dist/Server/Middleware/UserAuthorization.js +6 -2
  370. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  371. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
  372. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
  373. package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
  374. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  375. package/build/dist/Server/Services/ApiKeyPermissionService.js +90 -1
  376. package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
  377. package/build/dist/Server/Services/DatabaseService.js +89 -6
  378. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  379. package/build/dist/Server/Services/LogAggregationService.js +7 -0
  380. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  381. package/build/dist/Server/Services/LogService.js +16 -0
  382. package/build/dist/Server/Services/LogService.js.map +1 -1
  383. package/build/dist/Server/Services/NetworkSiteService.js +12 -0
  384. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  385. package/build/dist/Server/Services/PushNotificationService.js +69 -30
  386. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  387. package/build/dist/Server/Services/SpanService.js +16 -0
  388. package/build/dist/Server/Services/SpanService.js.map +1 -1
  389. package/build/dist/Server/Services/TeamMemberService.js +43 -7
  390. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  391. package/build/dist/Server/Services/TraceAggregationService.js +2 -0
  392. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  393. package/build/dist/Server/Services/UserCallService.js +54 -22
  394. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  395. package/build/dist/Server/Services/UserEmailService.js +78 -17
  396. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  397. package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
  398. package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
  399. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
  400. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
  401. package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
  402. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  403. package/build/dist/Server/Services/UserPushService.js +77 -0
  404. package/build/dist/Server/Services/UserPushService.js.map +1 -1
  405. package/build/dist/Server/Services/UserSmsService.js +50 -17
  406. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  407. package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
  408. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
  409. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +137 -164
  410. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  411. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -0
  412. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
  413. package/build/dist/Server/Types/Database/Permissions/AccessControlPermission.js +21 -13
  414. package/build/dist/Server/Types/Database/Permissions/AccessControlPermission.js.map +1 -1
  415. package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
  416. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  417. package/build/dist/Server/Utils/APIKey/AccessPermission.js +9 -32
  418. package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
  419. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
  420. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
  421. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +87 -0
  422. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  423. package/build/dist/Server/Utils/ChannelVerification.js +348 -0
  424. package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
  425. package/build/dist/Server/Utils/LogRedaction.js +449 -0
  426. package/build/dist/Server/Utils/LogRedaction.js.map +1 -0
  427. package/build/dist/Server/Utils/Logger.js +98 -45
  428. package/build/dist/Server/Utils/Logger.js.map +1 -1
  429. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
  430. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
  431. package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +65 -13
  432. package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js.map +1 -1
  433. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
  434. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  435. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
  436. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  437. package/build/dist/Server/Utils/Monitor/MonitorResource.js +20 -3
  438. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  439. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
  440. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
  441. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
  442. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
  443. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +27 -7
  444. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  445. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
  446. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
  447. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
  448. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js +29 -10
  449. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js.map +1 -1
  450. package/build/dist/Server/Utils/StartServer.js +10 -7
  451. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  452. package/build/dist/Server/Utils/StatusPageSearchEngineIndexing.js +24 -0
  453. package/build/dist/Server/Utils/StatusPageSearchEngineIndexing.js.map +1 -0
  454. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +311 -0
  455. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -0
  456. package/build/dist/Server/Utils/TotpAuth.js +127 -8
  457. package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
  458. package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
  459. package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
  460. package/build/dist/Server/Utils/VerificationCode.js +120 -0
  461. package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
  462. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +366 -37
  463. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  464. package/build/dist/Types/API/Hostname.js +63 -0
  465. package/build/dist/Types/API/Hostname.js.map +1 -1
  466. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +20 -6
  467. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
  468. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +20 -6
  469. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
  470. package/build/dist/Types/Database/DatabaseProperty.js +38 -0
  471. package/build/dist/Types/Database/DatabaseProperty.js.map +1 -1
  472. package/build/dist/Types/Database/TableColumn.js +24 -6
  473. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  474. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  475. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  476. package/build/dist/Types/Events/Recurring.js +13 -1
  477. package/build/dist/Types/Events/Recurring.js.map +1 -1
  478. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
  479. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  480. package/build/dist/Types/Monitor/MonitorStep.js +9 -1
  481. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  482. package/build/dist/Types/Monitor/MonitorType.js +330 -31
  483. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  484. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
  485. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  486. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
  487. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  488. package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
  489. package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
  490. package/build/dist/Types/Permission.js +33 -0
  491. package/build/dist/Types/Permission.js.map +1 -1
  492. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
  493. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
  494. package/build/dist/Types/Service/ServiceLanguage.js +96 -0
  495. package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
  496. package/build/dist/Types/StatusPage/SearchEngineIndexing.js +55 -0
  497. package/build/dist/Types/StatusPage/SearchEngineIndexing.js.map +1 -0
  498. package/build/dist/Types/Telemetry/ResourceEntityFacet.js +156 -0
  499. package/build/dist/Types/Telemetry/ResourceEntityFacet.js.map +1 -0
  500. package/build/dist/Types/Text.js +82 -17
  501. package/build/dist/Types/Text.js.map +1 -1
  502. package/build/dist/UI/Components/Button/Button.js +22 -14
  503. package/build/dist/UI/Components/Button/Button.js.map +1 -1
  504. package/build/dist/UI/Components/CardSelect/CardSelect.js +360 -40
  505. package/build/dist/UI/Components/CardSelect/CardSelect.js.map +1 -1
  506. package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
  507. package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
  508. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
  509. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
  510. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
  511. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
  512. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
  513. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
  514. package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
  515. package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
  516. package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
  517. package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
  518. package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
  519. package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
  520. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
  521. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
  522. package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
  523. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  524. package/build/dist/UI/Components/EmptyState/EmptyState.js +1 -1
  525. package/build/dist/UI/Components/EmptyState/EmptyState.js.map +1 -1
  526. package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
  527. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  528. package/build/dist/UI/Components/Footer/Footer.js +7 -4
  529. package/build/dist/UI/Components/Footer/Footer.js.map +1 -1
  530. package/build/dist/UI/Components/Forms/Fields/FormField.js +1 -1
  531. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  532. package/build/dist/UI/Components/List/List.js +19 -5
  533. package/build/dist/UI/Components/List/List.js.map +1 -1
  534. package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
  535. package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
  536. package/build/dist/UI/Components/Loader/PageLoader.js +15 -5
  537. package/build/dist/UI/Components/Loader/PageLoader.js.map +1 -1
  538. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +16 -3
  539. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  540. package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js +13 -1
  541. package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
  542. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
  543. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  544. package/build/dist/UI/Components/MasterPage/MasterPage.js +10 -2
  545. package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
  546. package/build/dist/UI/Components/Modal/Modal.js +2 -2
  547. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
  548. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  549. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
  550. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
  551. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
  552. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  553. package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
  554. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  555. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
  556. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
  557. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
  558. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
  559. package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
  560. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  561. package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
  562. package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
  563. package/build/dist/UI/Components/Table/Table.js +35 -24
  564. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  565. package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
  566. package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
  567. package/build/dist/UI/Components/Tabs/Tab.js +1 -1
  568. package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
  569. package/build/dist/UI/Components/Toast/Toast.js +77 -23
  570. package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
  571. package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
  572. package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
  573. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
  574. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  575. package/build/dist/UI/Utils/ModelListCache.js +126 -0
  576. package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
  577. package/build/dist/UI/Utils/Project.js +24 -1
  578. package/build/dist/UI/Utils/Project.js.map +1 -1
  579. package/build/dist/Utils/API.js +6 -1
  580. package/build/dist/Utils/API.js.map +1 -1
  581. package/build/dist/Utils/Monitor/MonitorMetricType.js +13 -1
  582. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  583. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +34 -7
  584. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  585. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +177 -0
  586. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -0
  587. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +23 -27
  588. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
  589. package/build/dist/Utils/Telemetry/CrossSignalScope.js +44 -4
  590. package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
  591. package/jest.config.json +1 -1
  592. package/package.json +2 -3
  593. package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
  594. package/Tests/__mocks__/otpauth.js +0 -30
  595. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
  596. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
@@ -6,6 +6,11 @@ import SiteStatusRollupUtil, {
6
6
  /*
7
7
  * MonitorStatus priority is HIGHER = WORSE (seeded: Operational 1,
8
8
  * Degraded 2, Offline 3).
9
+ *
10
+ * The SNMP half of this rollup now asks DeviceReachabilityUtil — "did the
11
+ * last poll succeed" — rather than "was the last success recent". That is
12
+ * what stops a site card going red because its probe is behind on a large
13
+ * fleet while every device under it is answering (issue #3220).
9
14
  */
10
15
  const OPERATIONAL: RollupStatusOption = {
11
16
  monitorStatusId: "status-operational",
@@ -26,12 +31,31 @@ function minutesAgo(minutes: number): Date {
26
31
  return new Date(NOW.getTime() - minutes * 60 * 1000);
27
32
  }
28
33
 
34
+ // A device whose last poll succeeded `minutes` ago.
35
+ function answered(minutes: number): DeviceHealthState {
36
+ return {
37
+ isReachable: true,
38
+ lastPolledAt: minutesAgo(minutes),
39
+ lastSeenAt: minutesAgo(minutes),
40
+ pollingIntervalInMinutes: 5,
41
+ };
42
+ }
43
+
44
+ // A device whose last poll failed `minutes` ago.
45
+ function failed(minutes: number): DeviceHealthState {
46
+ return {
47
+ isReachable: false,
48
+ lastPolledAt: minutesAgo(minutes),
49
+ lastSeenAt: minutesAgo(minutes + 60),
50
+ pollingIntervalInMinutes: 5,
51
+ };
52
+ }
53
+
29
54
  function worst(
30
55
  deviceStates: Array<DeviceHealthState>,
31
56
  overrides?: {
32
57
  operationalStatus?: RollupStatusOption | null;
33
58
  offlineStatus?: RollupStatusOption | null;
34
- freshnessWindowInMinutes?: number;
35
59
  },
36
60
  ): string | null {
37
61
  return SiteStatusRollupUtil.worstStatus({
@@ -45,7 +69,6 @@ function worst(
45
69
  ? overrides.offlineStatus
46
70
  : OFFLINE,
47
71
  now: NOW,
48
- freshnessWindowInMinutes: overrides?.freshnessWindowInMinutes,
49
72
  });
50
73
  }
51
74
 
@@ -84,65 +107,103 @@ describe("SiteStatusRollupUtil.worstStatus", () => {
84
107
  ).toBe(OFFLINE.monitorStatusId);
85
108
  });
86
109
 
87
- it("a fresh unmonitored device maps to the operational equivalent", () => {
88
- expect(worst([{ lastSeenAt: minutesAgo(5) }])).toBe(
110
+ it("a device whose last poll succeeded maps to the operational equivalent", () => {
111
+ expect(worst([answered(5)])).toBe(OPERATIONAL.monitorStatusId);
112
+ });
113
+
114
+ it("a device whose last poll failed maps to the offline equivalent", () => {
115
+ expect(worst([failed(2)])).toBe(OFFLINE.monitorStatusId);
116
+ });
117
+
118
+ /*
119
+ * The rollup half of issue #3220. 21 minutes was the reported lag on a
120
+ * fleet the probe could not get round in 15, and every device under the
121
+ * site was answering.
122
+ */
123
+ it("issue #3220: a site whose devices are all answering, 21 minutes behind, is operational", () => {
124
+ expect(worst([answered(21), answered(19), answered(25)])).toBe(
89
125
  OPERATIONAL.monitorStatusId,
90
126
  );
91
127
  });
92
128
 
93
- it("a stale unmonitored device maps to the offline equivalent", () => {
94
- expect(worst([{ lastSeenAt: minutesAgo(30) }])).toBe(
95
- OFFLINE.monitorStatusId,
96
- );
129
+ it("a slow-polled device is operational right up to its next poll", () => {
130
+ expect(
131
+ worst([
132
+ {
133
+ isReachable: true,
134
+ lastPolledAt: minutesAgo(29),
135
+ lastSeenAt: minutesAgo(29),
136
+ pollingIntervalInMinutes: 30,
137
+ },
138
+ ]),
139
+ ).toBe(OPERATIONAL.monitorStatusId);
97
140
  });
98
141
 
99
- it("a never-seen unmonitored device maps to the offline equivalent", () => {
100
- expect(worst([{}])).toBe(OFFLINE.monitorStatusId);
101
- expect(worst([{ lastSeenAt: null }])).toBe(OFFLINE.monitorStatusId);
142
+ /*
143
+ * A site nothing has polled for hours keeps its last known status rather
144
+ * than flipping offline. Turning "nobody has checked lately" into a red
145
+ * site card is the same inference this change removed from the device
146
+ * pill — and doing it here alone would put the site card at odds with
147
+ * every device under it, which is the inconsistency issue #3220 reported.
148
+ */
149
+ it("a device out of contact past its stale window keeps its last verdict", () => {
150
+ expect(worst([answered(61)])).toBe(OPERATIONAL.monitorStatusId);
151
+ expect(worst([answered(60 * 24)])).toBe(OPERATIONAL.monitorStatusId);
102
152
  });
103
153
 
104
- it("freshness boundary: exactly 15 minutes is still fresh, beyond is not", () => {
105
- expect(worst([{ lastSeenAt: minutesAgo(15) }])).toBe(
106
- OPERATIONAL.monitorStatusId,
107
- );
108
- expect(
109
- worst([{ lastSeenAt: new Date(minutesAgo(15).getTime() - 1) }]),
110
- ).toBe(OFFLINE.monitorStatusId);
154
+ it("...but a device that actually failed its last poll still rolls up offline", () => {
155
+ expect(worst([failed(60 * 24)])).toBe(OFFLINE.monitorStatusId);
156
+ });
157
+
158
+ /*
159
+ * Changed deliberately: a never-polled device used to be counted as
160
+ * offline, which pinned a brand-new site red until its first walk landed
161
+ * — while the device list showed the very same device as a gray
162
+ * "Pending". It now contributes nothing, and the caller reads null as
163
+ * "leave the site's status alone".
164
+ */
165
+ it("a never-polled device contributes nothing at all", () => {
166
+ expect(worst([{}])).toBeNull();
167
+ expect(worst([{ isReachable: null, lastSeenAt: null }])).toBeNull();
168
+ });
169
+
170
+ it("a never-polled device does not drag down a site with healthy devices", () => {
171
+ expect(worst([answered(1), {}])).toBe(OPERATIONAL.monitorStatusId);
111
172
  });
112
173
 
113
- it("mix: a stale unmonitored device outranks a monitored operational one", () => {
174
+ it("mix: a failing device outranks a monitored operational one", () => {
114
175
  expect(
115
176
  worst([
116
177
  {
117
178
  currentMonitorStatusId: OPERATIONAL.monitorStatusId,
118
179
  monitorStatusPriority: OPERATIONAL.priority,
119
180
  },
120
- { lastSeenAt: minutesAgo(60) },
181
+ failed(1),
121
182
  ]),
122
183
  ).toBe(OFFLINE.monitorStatusId);
123
184
  });
124
185
 
125
- it("mix: a monitored offline device outranks fresh unmonitored ones", () => {
186
+ it("mix: a monitored offline device outranks answering ones", () => {
126
187
  expect(
127
188
  worst([
128
- { lastSeenAt: minutesAgo(1) },
189
+ answered(1),
129
190
  {
130
191
  currentMonitorStatusId: OFFLINE.monitorStatusId,
131
192
  monitorStatusPriority: OFFLINE.priority,
132
193
  },
133
- { lastSeenAt: minutesAgo(2) },
194
+ answered(2),
134
195
  ]),
135
196
  ).toBe(OFFLINE.monitorStatusId);
136
197
  });
137
198
 
138
- it("a stamped status whose priority is unknown falls back to freshness", () => {
139
- // The MonitorStatus row was deleted: treat the device by lastSeenAt.
199
+ it("a stamped status whose priority is unknown falls back to reachability", () => {
200
+ // The MonitorStatus row was deleted: treat the device by its last poll.
140
201
  expect(
141
202
  worst([
142
203
  {
143
204
  currentMonitorStatusId: "deleted-status",
144
205
  monitorStatusPriority: undefined,
145
- lastSeenAt: minutesAgo(1),
206
+ ...answered(1),
146
207
  },
147
208
  ]),
148
209
  ).toBe(OPERATIONAL.monitorStatusId);
@@ -151,7 +212,7 @@ describe("SiteStatusRollupUtil.worstStatus", () => {
151
212
  {
152
213
  currentMonitorStatusId: "deleted-status",
153
214
  monitorStatusPriority: null,
154
- lastSeenAt: minutesAgo(120),
215
+ ...failed(1),
155
216
  },
156
217
  ]),
157
218
  ).toBe(OFFLINE.monitorStatusId);
@@ -172,9 +233,9 @@ describe("SiteStatusRollupUtil.worstStatus", () => {
172
233
  ).toBe("status-a");
173
234
  });
174
235
 
175
- it("returns null when only freshness fallbacks apply but the project has no flagged rows", () => {
236
+ it("returns null when only SNMP fallbacks apply but the project has no flagged rows", () => {
176
237
  expect(
177
- worst([{ lastSeenAt: minutesAgo(1) }, { lastSeenAt: minutesAgo(60) }], {
238
+ worst([answered(1), failed(1)], {
178
239
  operationalStatus: null,
179
240
  offlineStatus: null,
180
241
  }),
@@ -185,7 +246,7 @@ describe("SiteStatusRollupUtil.worstStatus", () => {
185
246
  expect(
186
247
  worst(
187
248
  [
188
- { lastSeenAt: minutesAgo(60) }, // offline equivalent missing -> skipped
249
+ failed(1), // offline equivalent missing -> skipped
189
250
  {
190
251
  currentMonitorStatusId: DEGRADED.monitorStatusId,
191
252
  monitorStatusPriority: DEGRADED.priority,
@@ -196,26 +257,34 @@ describe("SiteStatusRollupUtil.worstStatus", () => {
196
257
  ).toBe(DEGRADED.monitorStatusId);
197
258
  });
198
259
 
199
- it("honors a custom freshness window", () => {
260
+ it("a lastPolledAt in the future counts as fresh, not an error", () => {
200
261
  expect(
201
- worst([{ lastSeenAt: minutesAgo(20) }], {
202
- freshnessWindowInMinutes: 30,
203
- }),
262
+ worst([
263
+ {
264
+ isReachable: true,
265
+ lastPolledAt: minutesAgo(-5),
266
+ lastSeenAt: minutesAgo(-5),
267
+ },
268
+ ]),
204
269
  ).toBe(OPERATIONAL.monitorStatusId);
205
- expect(
206
- worst([{ lastSeenAt: minutesAgo(20) }], {
207
- freshnessWindowInMinutes: 10,
208
- }),
209
- ).toBe(OFFLINE.monitorStatusId);
210
270
  });
211
271
 
212
- it("a lastSeenAt in the future counts as fresh, not an error", () => {
213
- expect(worst([{ lastSeenAt: minutesAgo(-5) }])).toBe(
272
+ /*
273
+ * Rows written before the reachability columns existed carry only
274
+ * lastSeenAt. They must keep rolling up sensibly until the upgrade
275
+ * migration (or their next walk) fills the rest in.
276
+ */
277
+ it("legacy rows with only lastSeenAt still roll up by freshness", () => {
278
+ /*
279
+ * The one place freshness survives: a row written before isReachable
280
+ * existed has nothing else to go on. The upgrade migration backfills
281
+ * these, so it is a short-lived path.
282
+ */
283
+ expect(worst([{ lastSeenAt: minutesAgo(5) }])).toBe(
214
284
  OPERATIONAL.monitorStatusId,
215
285
  );
216
- });
217
-
218
- it("exposes the default freshness window as 15 minutes", () => {
219
- expect(SiteStatusRollupUtil.DEFAULT_FRESHNESS_WINDOW_IN_MINUTES).toBe(15);
286
+ expect(worst([{ lastSeenAt: minutesAgo(600) }])).toBe(
287
+ OFFLINE.monitorStatusId,
288
+ );
220
289
  });
221
290
  });
@@ -0,0 +1,362 @@
1
+ import { describe, expect, it } from "@jest/globals";
2
+ import UrlScrubber from "../../../Utils/Rum/UrlScrubber";
3
+
4
+ /*
5
+ * The parent UrlScrubber.test.ts drives the whole pipeline through the
6
+ * public scrub()/getScrubbedPathname() facade. This suite pins the two
7
+ * segment-level primitives directly — scrubPath() and scrubQuery() — so
8
+ * that the branch behaviour each one owns (every redaction pattern and its
9
+ * length boundary, the decode-before-match step, the empty/"/" short
10
+ * circuits, and the allowlist rules) is exercised in isolation rather than
11
+ * only as an emergent property of a full URL round-trip.
12
+ *
13
+ * Everything here is a pure function of its arguments: no network, no clock,
14
+ * no randomness. scrubQuery takes a plain URLSearchParams built inline.
15
+ */
16
+
17
+ const REDACTED: string = "[redacted]";
18
+
19
+ describe("UrlScrubber segment primitives", () => {
20
+ describe("scrubPath", () => {
21
+ describe("empty and boundary inputs", () => {
22
+ it("normalises an empty path to a single slash", () => {
23
+ /*
24
+ * The `pathname || "/"` fallback: an empty string is not passed
25
+ * through as-is, it is turned into the root path.
26
+ */
27
+ expect(UrlScrubber.scrubPath("")).toBe("/");
28
+ });
29
+
30
+ it("returns the root path unchanged", () => {
31
+ expect(UrlScrubber.scrubPath("/")).toBe("/");
32
+ });
33
+
34
+ it("keeps a path whose segments are all ordinary route words", () => {
35
+ expect(UrlScrubber.scrubPath("/blog/how-we-scaled-clickhouse")).toBe(
36
+ "/blog/how-we-scaled-clickhouse",
37
+ );
38
+ });
39
+
40
+ it("preserves the leading empty segment produced by the leading slash", () => {
41
+ /*
42
+ * "/orders/2".split("/") is ["", "orders", "2"]; the empty first
43
+ * element must survive the map so the result stays absolute.
44
+ */
45
+ const scrubbed: string = UrlScrubber.scrubPath("/orders/2");
46
+
47
+ expect(scrubbed).toBe("/orders/2");
48
+ expect(scrubbed.startsWith("/")).toBe(true);
49
+ });
50
+
51
+ it("preserves a trailing slash and collapsed empty segments", () => {
52
+ expect(UrlScrubber.scrubPath("/a//b/")).toBe("/a//b/");
53
+ });
54
+
55
+ it("handles a path that is a single identifier segment", () => {
56
+ expect(
57
+ UrlScrubber.scrubPath("/3f1a9c7e-5b2d-4801-96a3-c9e7b1d5028f"),
58
+ ).toBe(`/${REDACTED}`);
59
+ });
60
+ });
61
+
62
+ describe("uuid segments", () => {
63
+ it("redacts a canonical lowercase uuid while keeping the route shape", () => {
64
+ expect(
65
+ UrlScrubber.scrubPath(
66
+ "/orders/3f1a9c7e-5b2d-4801-96a3-c9e7b1d5028f/items",
67
+ ),
68
+ ).toBe(`/orders/${REDACTED}/items`);
69
+ });
70
+
71
+ it("redacts a uuid case-insensitively", () => {
72
+ expect(
73
+ UrlScrubber.scrubPath("/orders/3F1A9C7E-5B2D-4801-96A3-C9E7B1D5028F"),
74
+ ).toBe(`/orders/${REDACTED}`);
75
+ });
76
+
77
+ it("does not treat a uuid-shaped-but-wrong-length string as a uuid", () => {
78
+ /*
79
+ * A truncated uuid (30 chars): it fails the anchored uuid pattern
80
+ * and, being under the 32-char opaque-token threshold, escapes that
81
+ * rule too, so it survives as ordinary route structure.
82
+ */
83
+ const almost: string = "3f1a9c7e-5b2d-4801-96a3-c9e7b1";
84
+
85
+ expect(almost.length).toBeLessThan(32);
86
+ expect(UrlScrubber.scrubPath(`/x/${almost}`)).toBe(`/x/${almost}`);
87
+ });
88
+ });
89
+
90
+ describe("object id segments", () => {
91
+ it("redacts a 24-character Mongo/BSON object id", () => {
92
+ expect(UrlScrubber.scrubPath("/users/6512f3a9b7c4d2e108f5a3b9")).toBe(
93
+ `/users/${REDACTED}`,
94
+ );
95
+ });
96
+
97
+ it("keeps a 23-character hex string, one short of an object id", () => {
98
+ const shortHex: string = "6512f3a9b7c4d2e108f5a3b";
99
+
100
+ expect(UrlScrubber.scrubPath(`/users/${shortHex}`)).toBe(
101
+ `/users/${shortHex}`,
102
+ );
103
+ });
104
+ });
105
+
106
+ describe("email segments", () => {
107
+ it("redacts a plain email segment", () => {
108
+ expect(UrlScrubber.scrubPath("/u/someone@example.com/profile")).toBe(
109
+ `/u/${REDACTED}/profile`,
110
+ );
111
+ });
112
+
113
+ it("redacts a percent-encoded email by decoding before matching", () => {
114
+ /*
115
+ * name%40example.com decodes to name@example.com; the decode step
116
+ * is what lets the email pattern see it.
117
+ */
118
+ const scrubbed: string = UrlScrubber.scrubPath(
119
+ "/u/someone%40example.com",
120
+ );
121
+
122
+ expect(scrubbed).toBe(`/u/${REDACTED}`);
123
+ expect(scrubbed).not.toContain("%40");
124
+ expect(scrubbed).not.toContain("someone");
125
+ });
126
+
127
+ it("keeps a segment that merely contains an at-sign but is not an address", () => {
128
+ /*
129
+ * A handle like "@acme" has no domain part, so the anchored email
130
+ * pattern rejects it and it is treated as route structure.
131
+ */
132
+ expect(UrlScrubber.scrubPath("/team/@acme")).toBe("/team/@acme");
133
+ });
134
+ });
135
+
136
+ describe("long digit-run segments", () => {
137
+ it("redacts a run of 9 or more digits (card / phone / SSN shaped)", () => {
138
+ expect(UrlScrubber.scrubPath("/account/4111111111111111")).toBe(
139
+ `/account/${REDACTED}`,
140
+ );
141
+ });
142
+
143
+ it("redacts at the 9-digit boundary", () => {
144
+ expect(UrlScrubber.scrubPath("/n/123456789")).toBe(`/n/${REDACTED}`);
145
+ });
146
+
147
+ it("keeps an 8-digit run just under the boundary", () => {
148
+ expect(UrlScrubber.scrubPath("/n/12345678")).toBe("/n/12345678");
149
+ });
150
+
151
+ it("keeps a short numeric id, which is route structure not PII", () => {
152
+ expect(UrlScrubber.scrubPath("/page/2")).toBe("/page/2");
153
+ });
154
+ });
155
+
156
+ describe("opaque token segments", () => {
157
+ it("redacts a 32-or-longer high-entropy token", () => {
158
+ expect(
159
+ UrlScrubber.scrubPath(
160
+ "/s/aVeryLongOpaqueSessionTokenValue1234567890",
161
+ ),
162
+ ).toBe(`/s/${REDACTED}`);
163
+ });
164
+
165
+ it("redacts exactly at the 32-character boundary", () => {
166
+ const token: string = "a".repeat(32);
167
+
168
+ expect(UrlScrubber.scrubPath(`/s/${token}`)).toBe(`/s/${REDACTED}`);
169
+ });
170
+
171
+ it("keeps a 31-character string just under the boundary", () => {
172
+ const slug: string = "a".repeat(31);
173
+
174
+ expect(UrlScrubber.scrubPath(`/s/${slug}`)).toBe(`/s/${slug}`);
175
+ });
176
+
177
+ it("keeps a long slug that carries a dot outside the token charset", () => {
178
+ /*
179
+ * The opaque-token charset is [A-Za-z0-9_-]; a dot disqualifies the
180
+ * whole segment even when it is well over 32 characters, so a
181
+ * dotted asset name survives.
182
+ */
183
+ const dotted: string = "this-is-a-fairly-long-report-name.2024.final";
184
+
185
+ expect(UrlScrubber.scrubPath(`/files/${dotted}`)).toBe(
186
+ `/files/${dotted}`,
187
+ );
188
+ });
189
+ });
190
+
191
+ describe("decode fallback and structure preservation", () => {
192
+ it("never throws and leaves a malformed percent-escape segment intact", () => {
193
+ /*
194
+ * decodeURIComponent("%E0%A4%A") throws; the catch falls back to
195
+ * matching the raw segment, which matches nothing, so the segment
196
+ * is returned exactly as given rather than crashing the mapper.
197
+ */
198
+ const malformed: string = "%E0%A4%A";
199
+
200
+ let scrubbed: string = "";
201
+
202
+ expect((): void => {
203
+ scrubbed = UrlScrubber.scrubPath(`/x/${malformed}`);
204
+ }).not.toThrow();
205
+
206
+ expect(scrubbed).toBe(`/x/${malformed}`);
207
+ });
208
+
209
+ it("returns the raw (still-encoded) form for a non-PII encoded segment", () => {
210
+ /*
211
+ * A kept segment is returned in its original encoded form, not the
212
+ * decoded one: "caf%C3%A9" decodes to "café", matches no pattern,
213
+ * and comes back byte-for-byte as it went in.
214
+ */
215
+ expect(UrlScrubber.scrubPath("/menu/caf%C3%A9")).toBe(
216
+ "/menu/caf%C3%A9",
217
+ );
218
+ });
219
+
220
+ it("redacts only the identifier segments in a mixed path", () => {
221
+ const mixed: string =
222
+ "/org/acme/users/6512f3a9b7c4d2e108f5a3b9/orders/2/token/" +
223
+ "aVeryLongOpaqueSessionTokenValue1234567890";
224
+
225
+ expect(UrlScrubber.scrubPath(mixed)).toBe(
226
+ `/org/acme/users/${REDACTED}/orders/2/token/${REDACTED}`,
227
+ );
228
+ });
229
+
230
+ it("redacts every identifier segment when a path is nothing but ids", () => {
231
+ expect(
232
+ UrlScrubber.scrubPath(
233
+ "/6512f3a9b7c4d2e108f5a3b9/someone@example.com/123456789",
234
+ ),
235
+ ).toBe(`/${REDACTED}/${REDACTED}/${REDACTED}`);
236
+ });
237
+ });
238
+ });
239
+
240
+ describe("scrubQuery", () => {
241
+ describe("empty / missing allowlist drops everything", () => {
242
+ it("returns an empty string when the allowlist is undefined", () => {
243
+ const params: URLSearchParams = new URLSearchParams(
244
+ "plan=growth&coupon=SECRET50",
245
+ );
246
+
247
+ expect(UrlScrubber.scrubQuery(params)).toBe("");
248
+ });
249
+
250
+ it("returns an empty string when the allowlist is empty", () => {
251
+ const params: URLSearchParams = new URLSearchParams("plan=growth");
252
+
253
+ expect(UrlScrubber.scrubQuery(params, [])).toBe("");
254
+ });
255
+
256
+ it("returns an empty string when no parameter matches the allowlist", () => {
257
+ const params: URLSearchParams = new URLSearchParams(
258
+ "coupon=SECRET50&ref=twitter",
259
+ );
260
+
261
+ expect(UrlScrubber.scrubQuery(params, ["plan"])).toBe("");
262
+ });
263
+
264
+ it("returns an empty string for a query with no parameters at all", () => {
265
+ expect(UrlScrubber.scrubQuery(new URLSearchParams(""), ["plan"])).toBe(
266
+ "",
267
+ );
268
+ });
269
+ });
270
+
271
+ describe("allowlisted names are kept with redacted values", () => {
272
+ it("keeps the name and redacts the value of an allowlisted parameter", () => {
273
+ const params: URLSearchParams = new URLSearchParams(
274
+ "plan=growth&coupon=SECRET50",
275
+ );
276
+
277
+ const scrubbed: string = UrlScrubber.scrubQuery(params, ["plan"]);
278
+
279
+ expect(scrubbed).toBe(`plan=${REDACTED}`);
280
+ expect(scrubbed).not.toContain("growth");
281
+ expect(scrubbed).not.toContain("SECRET50");
282
+ expect(scrubbed).not.toContain("coupon");
283
+ });
284
+
285
+ it("redacts the value regardless of how sensitive it looks", () => {
286
+ const params: URLSearchParams = new URLSearchParams();
287
+ params.append("token", "eyJhbGciOiJIUzI1NiJ9.payload.signature");
288
+
289
+ const scrubbed: string = UrlScrubber.scrubQuery(params, ["token"]);
290
+
291
+ expect(scrubbed).toBe(`token=${REDACTED}`);
292
+ expect(scrubbed).not.toContain("eyJ");
293
+ });
294
+
295
+ it("keeps several allowlisted parameters joined by ampersands", () => {
296
+ const params: URLSearchParams = new URLSearchParams(
297
+ "plan=growth&ref=twitter&step=2",
298
+ );
299
+
300
+ expect(UrlScrubber.scrubQuery(params, ["plan", "step"])).toBe(
301
+ `plan=${REDACTED}&step=${REDACTED}`,
302
+ );
303
+ });
304
+
305
+ it("preserves the original query order of the kept parameters", () => {
306
+ const params: URLSearchParams = new URLSearchParams(
307
+ "step=2&plan=growth",
308
+ );
309
+
310
+ expect(UrlScrubber.scrubQuery(params, ["plan", "step"])).toBe(
311
+ `step=${REDACTED}&plan=${REDACTED}`,
312
+ );
313
+ });
314
+ });
315
+
316
+ describe("case-insensitive matching", () => {
317
+ it("matches an allowlist entry against a differently-cased parameter name", () => {
318
+ const params: URLSearchParams = new URLSearchParams("Plan=growth");
319
+
320
+ /*
321
+ * The comparison lowercases both sides, but the emitted name keeps
322
+ * the parameter's original casing.
323
+ */
324
+ expect(UrlScrubber.scrubQuery(params, ["plan"])).toBe(
325
+ `Plan=${REDACTED}`,
326
+ );
327
+ });
328
+
329
+ it("matches when the allowlist entry itself is upper-cased", () => {
330
+ const params: URLSearchParams = new URLSearchParams("plan=growth");
331
+
332
+ expect(UrlScrubber.scrubQuery(params, ["PLAN"])).toBe(
333
+ `plan=${REDACTED}`,
334
+ );
335
+ });
336
+ });
337
+
338
+ describe("edge cases in parameter names", () => {
339
+ it("emits one redacted entry per repeated occurrence of a key", () => {
340
+ /*
341
+ * URLSearchParams keeps duplicate keys, so forEach visits each one;
342
+ * both are kept, and because the value is redacted the two entries
343
+ * are identical.
344
+ */
345
+ const params: URLSearchParams = new URLSearchParams("a=1&a=2&b=3");
346
+
347
+ expect(UrlScrubber.scrubQuery(params, ["a"])).toBe(
348
+ `a=${REDACTED}&a=${REDACTED}`,
349
+ );
350
+ });
351
+
352
+ it("percent-encodes an allowlisted key that contains a space", () => {
353
+ const params: URLSearchParams = new URLSearchParams();
354
+ params.append("user name", "jane");
355
+
356
+ expect(UrlScrubber.scrubQuery(params, ["user name"])).toBe(
357
+ `user%20name=${REDACTED}`,
358
+ );
359
+ });
360
+ });
361
+ });
362
+ });