@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
@@ -0,0 +1,427 @@
1
+ import UserTotpAuthAPI from "../../../Server/API/UserTotpAuthAPI";
2
+ import UserTotpAuthService from "../../../Server/Services/UserTotpAuthService";
3
+ import UserService from "../../../Server/Services/UserService";
4
+ import TotpAuth from "../../../Server/Utils/TotpAuth";
5
+ import {
6
+ NextFunction,
7
+ OneUptimeRequest,
8
+ OneUptimeResponse,
9
+ } from "../../../Server/Utils/Express";
10
+ import Response from "../../../Server/Utils/Response";
11
+ import { mockRouter } from "./Helpers";
12
+ import Email from "../../../Types/Email";
13
+ import BadDataException from "../../../Types/Exception/BadDataException";
14
+ import Exception from "../../../Types/Exception/Exception";
15
+ import ObjectID from "../../../Types/ObjectID";
16
+ import UserTotpAuth from "../../../Models/DatabaseModels/UserTotpAuth";
17
+ import User from "../../../Models/DatabaseModels/User";
18
+ import * as OTPAuth from "otpauth";
19
+ import { afterEach, beforeEach, describe, expect, test } from "@jest/globals";
20
+
21
+ /*
22
+ * POST /user-totp-auth/validate — the endpoint that turns a scanned QR code
23
+ * into a working second factor.
24
+ *
25
+ * TotpAuth itself is deliberately NOT mocked here. The bug this endpoint
26
+ * failed on (issue #3275) lived precisely in the seam between what the QR code
27
+ * told the authenticator app and what the server recomputed, so a test that
28
+ * stubs the verifier proves nothing about it. The secret is generated by the
29
+ * real service path, the code is produced by parsing the stored otpauth:// URI
30
+ * exactly as an authenticator app would, and the endpoint gets the real thing.
31
+ *
32
+ * The second concern is ownership. `id` comes from the request body, so
33
+ * without the userId comparison any signed-in user could mark a stranger's
34
+ * pending TOTP row as verified using a code from their own phone — a second
35
+ * factor the victim does not hold. That check is asserted directly, and the
36
+ * assertion that matters is that isVerified is never written.
37
+ */
38
+
39
+ jest.mock("../../../Server/Utils/Express", () => {
40
+ return {
41
+ getRouter: () => {
42
+ return mockRouter;
43
+ },
44
+ };
45
+ });
46
+
47
+ jest.mock("../../../Server/Utils/Response", () => {
48
+ return {
49
+ sendEntityArrayResponse: jest.fn(),
50
+ sendJsonArrayResponse: jest.fn(),
51
+ sendJsonObjectResponse: jest.fn(),
52
+ sendEmptySuccessResponse: jest.fn(),
53
+ sendEntityResponse: jest.fn(),
54
+ sendErrorResponse: jest.fn(),
55
+ setNoCacheHeaders: jest.fn(),
56
+ };
57
+ });
58
+
59
+ jest.mock("../../../Server/Services/UserTotpAuthService");
60
+ jest.mock("../../../Server/Services/UserService");
61
+
62
+ const VALIDATE_ROUTE: string = "/user-totp-auth/validate";
63
+
64
+ const TOTP_ID: ObjectID = new ObjectID("11111111-1111-4111-8111-111111111111");
65
+ const OWNER_ID: ObjectID = new ObjectID("22222222-2222-4222-8222-222222222222");
66
+ const ATTACKER_ID: ObjectID = new ObjectID(
67
+ "33333333-3333-4333-8333-333333333333",
68
+ );
69
+
70
+ const OWNER_EMAIL: Email = new Email("owner@example.com");
71
+
72
+ type CallValidateResult = {
73
+ thrown: unknown;
74
+ nextCallCount: number;
75
+ };
76
+
77
+ type CallValidateFunction = (data: {
78
+ body: Record<string, unknown>;
79
+ signedInUserId?: ObjectID | undefined;
80
+ }) => Promise<CallValidateResult>;
81
+
82
+ const callValidate: CallValidateFunction = async (data: {
83
+ body: Record<string, unknown>;
84
+ signedInUserId?: ObjectID | undefined;
85
+ }): Promise<CallValidateResult> => {
86
+ const req: OneUptimeRequest = {
87
+ body: data.body,
88
+ params: {},
89
+ query: {},
90
+ headers: {},
91
+ userAuthorization: {
92
+ userId: data.signedInUserId || OWNER_ID,
93
+ },
94
+ } as unknown as OneUptimeRequest;
95
+
96
+ const res: OneUptimeResponse = {
97
+ send: jest.fn(),
98
+ json: jest.fn(),
99
+ setHeader: jest.fn(),
100
+ status: jest.fn().mockReturnThis(),
101
+ } as unknown as OneUptimeResponse;
102
+
103
+ const next: NextFunction = jest.fn() as unknown as NextFunction;
104
+
105
+ await mockRouter
106
+ .match("post", VALIDATE_ROUTE)
107
+ .handlerFunction(req, res, next);
108
+
109
+ const nextMock: jest.Mock = next as unknown as jest.Mock;
110
+
111
+ return {
112
+ thrown: nextMock.mock.calls[0]?.[0],
113
+ nextCallCount: nextMock.mock.calls.length,
114
+ };
115
+ };
116
+
117
+ /*
118
+ * A pending enrolment, built the way the service builds one: a real secret and
119
+ * the real otpauth:// URI derived from it.
120
+ */
121
+ type PendingEnrolmentFunction = (options?: { ownerId?: ObjectID }) => {
122
+ row: UserTotpAuth;
123
+ secret: string;
124
+ codeFromTheAuthenticatorApp: () => string;
125
+ };
126
+
127
+ const pendingEnrolment: PendingEnrolmentFunction = (options?: {
128
+ ownerId?: ObjectID;
129
+ }) => {
130
+ const secret: string = TotpAuth.generateSecret();
131
+
132
+ const otpUrl: string = TotpAuth.generateUri({
133
+ secret: secret,
134
+ userEmail: OWNER_EMAIL,
135
+ });
136
+
137
+ const row: UserTotpAuth = new UserTotpAuth();
138
+ row.id = TOTP_ID;
139
+ row.userId = options?.ownerId || OWNER_ID;
140
+ row.twoFactorSecret = secret;
141
+ row.twoFactorOtpUrl = otpUrl;
142
+ row.isVerified = false;
143
+
144
+ return {
145
+ row: row,
146
+ secret: secret,
147
+ codeFromTheAuthenticatorApp: (): string => {
148
+ return (OTPAuth.URI.parse(otpUrl) as OTPAuth.TOTP).generate();
149
+ },
150
+ };
151
+ };
152
+
153
+ let findTotpById: jest.Mock;
154
+ let updateTotpById: jest.Mock;
155
+ let findUserById: jest.Mock;
156
+
157
+ describe("POST /user-totp-auth/validate", () => {
158
+ beforeEach(() => {
159
+ mockRouter.routes.length = 0;
160
+
161
+ findTotpById = jest.fn();
162
+ updateTotpById = jest.fn(async () => {
163
+ return undefined;
164
+ });
165
+ findUserById = jest.fn();
166
+
167
+ UserTotpAuthService.findOneById = findTotpById as never;
168
+ UserTotpAuthService.updateOneById = updateTotpById as never;
169
+ UserTotpAuthService.getModel = jest
170
+ .fn()
171
+ .mockReturnValue({ tableName: "UserTotpAuth" }) as never;
172
+
173
+ UserService.findOneById = findUserById as never;
174
+
175
+ const owner: User = new User();
176
+ owner.id = OWNER_ID;
177
+ owner.email = OWNER_EMAIL;
178
+ findUserById.mockResolvedValue(owner as never);
179
+
180
+ new UserTotpAuthAPI();
181
+ });
182
+
183
+ afterEach(() => {
184
+ jest.restoreAllMocks();
185
+ });
186
+
187
+ describe("the route itself", () => {
188
+ test("is registered as a POST", () => {
189
+ expect(() => {
190
+ return mockRouter.match("post", VALIDATE_ROUTE);
191
+ }).not.toThrow();
192
+ });
193
+
194
+ /*
195
+ * Without an authentication middleware the handler would read
196
+ * `userAuthorization` off an unauthenticated request, the ownership
197
+ * comparison below would compare against `undefined`, and anybody could
198
+ * verify anybody's TOTP row.
199
+ */
200
+ test("is behind an authentication middleware", () => {
201
+ expect(mockRouter.match("post", VALIDATE_ROUTE).middlewares.length).toBe(
202
+ 1,
203
+ );
204
+ });
205
+ });
206
+
207
+ describe("when the code is the one the user's app is showing", () => {
208
+ test("marks the enrolment verified", async () => {
209
+ const enrolment: ReturnType<PendingEnrolmentFunction> =
210
+ pendingEnrolment();
211
+
212
+ findTotpById.mockResolvedValue(enrolment.row as never);
213
+
214
+ const result: CallValidateResult = await callValidate({
215
+ body: {
216
+ id: TOTP_ID.toString(),
217
+ code: enrolment.codeFromTheAuthenticatorApp(),
218
+ },
219
+ });
220
+
221
+ expect(result.thrown).toBeUndefined();
222
+
223
+ expect(updateTotpById).toHaveBeenCalledWith(
224
+ expect.objectContaining({
225
+ id: TOTP_ID,
226
+ data: { isVerified: true },
227
+ }),
228
+ );
229
+
230
+ expect(Response.sendEmptySuccessResponse).toHaveBeenCalled();
231
+ });
232
+
233
+ /*
234
+ * Google Authenticator renders the code as "123 456" and the phone
235
+ * clipboard keeps the space. This is the same enrolment, pasted.
236
+ */
237
+ test("accepts the code as the phone's clipboard hands it over", async () => {
238
+ const enrolment: ReturnType<PendingEnrolmentFunction> =
239
+ pendingEnrolment();
240
+
241
+ findTotpById.mockResolvedValue(enrolment.row as never);
242
+
243
+ const code: string = enrolment.codeFromTheAuthenticatorApp();
244
+
245
+ const result: CallValidateResult = await callValidate({
246
+ body: {
247
+ id: TOTP_ID.toString(),
248
+ code: `${code.slice(0, 3)} ${code.slice(3)}`,
249
+ },
250
+ });
251
+
252
+ expect(result.thrown).toBeUndefined();
253
+ expect(updateTotpById).toHaveBeenCalled();
254
+ });
255
+
256
+ test("reads the secret with root privileges, since the column is unreadable otherwise", async () => {
257
+ const enrolment: ReturnType<PendingEnrolmentFunction> =
258
+ pendingEnrolment();
259
+
260
+ findTotpById.mockResolvedValue(enrolment.row as never);
261
+
262
+ await callValidate({
263
+ body: {
264
+ id: TOTP_ID.toString(),
265
+ code: enrolment.codeFromTheAuthenticatorApp(),
266
+ },
267
+ });
268
+
269
+ expect(findTotpById).toHaveBeenCalledWith(
270
+ expect.objectContaining({
271
+ select: expect.objectContaining({ twoFactorSecret: true }),
272
+ props: { isRoot: true },
273
+ }),
274
+ );
275
+ });
276
+ });
277
+
278
+ describe("when the code is wrong", () => {
279
+ test("fails with Invalid code and leaves the enrolment unverified", async () => {
280
+ const enrolment: ReturnType<PendingEnrolmentFunction> =
281
+ pendingEnrolment();
282
+
283
+ findTotpById.mockResolvedValue(enrolment.row as never);
284
+
285
+ const result: CallValidateResult = await callValidate({
286
+ body: { id: TOTP_ID.toString(), code: "000000" },
287
+ });
288
+
289
+ expect(result.thrown).toBeInstanceOf(BadDataException);
290
+ expect((result.thrown as Exception).message).toBe("Invalid code");
291
+ expect(updateTotpById).not.toHaveBeenCalled();
292
+ });
293
+
294
+ test.each([
295
+ ["a missing code", undefined],
296
+ ["an empty code", ""],
297
+ ["a truncated code", "1234"],
298
+ ])(
299
+ "rejects %s without verifying anything",
300
+ async (_name: string, code: string | undefined) => {
301
+ const enrolment: ReturnType<PendingEnrolmentFunction> =
302
+ pendingEnrolment();
303
+
304
+ findTotpById.mockResolvedValue(enrolment.row as never);
305
+
306
+ const result: CallValidateResult = await callValidate({
307
+ body: { id: TOTP_ID.toString(), code: code },
308
+ });
309
+
310
+ expect(result.thrown).toBeInstanceOf(BadDataException);
311
+ expect(updateTotpById).not.toHaveBeenCalled();
312
+ },
313
+ );
314
+
315
+ /*
316
+ * A code that is valid for a DIFFERENT enrolment. This is what an attacker
317
+ * with their own authenticator would submit.
318
+ */
319
+ test("rejects a code that is valid for somebody else's secret", async () => {
320
+ const victim: ReturnType<PendingEnrolmentFunction> = pendingEnrolment();
321
+ const attacker: ReturnType<PendingEnrolmentFunction> = pendingEnrolment();
322
+
323
+ findTotpById.mockResolvedValue(victim.row as never);
324
+
325
+ const result: CallValidateResult = await callValidate({
326
+ body: {
327
+ id: TOTP_ID.toString(),
328
+ code: attacker.codeFromTheAuthenticatorApp(),
329
+ },
330
+ });
331
+
332
+ expect(result.thrown).toBeInstanceOf(BadDataException);
333
+ expect(updateTotpById).not.toHaveBeenCalled();
334
+ });
335
+ });
336
+
337
+ describe("ownership", () => {
338
+ /*
339
+ * `id` is attacker-controlled. If the handler stopped comparing userId, a
340
+ * signed-in attacker could point this endpoint at any pending enrolment in
341
+ * the database and verify it with a code from their own phone.
342
+ */
343
+ test("refuses to verify an enrolment belonging to another user", async () => {
344
+ const enrolment: ReturnType<PendingEnrolmentFunction> = pendingEnrolment({
345
+ ownerId: OWNER_ID,
346
+ });
347
+
348
+ findTotpById.mockResolvedValue(enrolment.row as never);
349
+
350
+ const result: CallValidateResult = await callValidate({
351
+ body: {
352
+ id: TOTP_ID.toString(),
353
+ code: enrolment.codeFromTheAuthenticatorApp(),
354
+ },
355
+ signedInUserId: ATTACKER_ID,
356
+ });
357
+
358
+ expect(result.thrown).toBeInstanceOf(BadDataException);
359
+ expect(updateTotpById).not.toHaveBeenCalled();
360
+ });
361
+
362
+ test("does not reveal that the enrolment exists", async () => {
363
+ const enrolment: ReturnType<PendingEnrolmentFunction> = pendingEnrolment({
364
+ ownerId: OWNER_ID,
365
+ });
366
+
367
+ findTotpById.mockResolvedValue(enrolment.row as never);
368
+
369
+ const result: CallValidateResult = await callValidate({
370
+ body: {
371
+ id: TOTP_ID.toString(),
372
+ code: enrolment.codeFromTheAuthenticatorApp(),
373
+ },
374
+ signedInUserId: ATTACKER_ID,
375
+ });
376
+
377
+ expect((result.thrown as Exception).message).toBe(
378
+ "Two factor auth not found",
379
+ );
380
+ });
381
+ });
382
+
383
+ describe("when the record is not usable", () => {
384
+ test("fails when no such enrolment exists", async () => {
385
+ findTotpById.mockResolvedValue(null as never);
386
+
387
+ const result: CallValidateResult = await callValidate({
388
+ body: { id: TOTP_ID.toString(), code: "123456" },
389
+ });
390
+
391
+ expect(result.thrown).toBeInstanceOf(BadDataException);
392
+ expect(updateTotpById).not.toHaveBeenCalled();
393
+ });
394
+
395
+ test("fails when the owning user has no email to label the entry with", async () => {
396
+ const enrolment: ReturnType<PendingEnrolmentFunction> =
397
+ pendingEnrolment();
398
+
399
+ findTotpById.mockResolvedValue(enrolment.row as never);
400
+
401
+ const emailless: User = new User();
402
+ emailless.id = OWNER_ID;
403
+ findUserById.mockResolvedValue(emailless as never);
404
+
405
+ const result: CallValidateResult = await callValidate({
406
+ body: {
407
+ id: TOTP_ID.toString(),
408
+ code: enrolment.codeFromTheAuthenticatorApp(),
409
+ },
410
+ });
411
+
412
+ expect(result.thrown).toBeInstanceOf(BadDataException);
413
+ expect(updateTotpById).not.toHaveBeenCalled();
414
+ });
415
+
416
+ test("surfaces the failure through next() rather than crashing the request", async () => {
417
+ findTotpById.mockRejectedValue(new Error("database is on fire") as never);
418
+
419
+ const result: CallValidateResult = await callValidate({
420
+ body: { id: TOTP_ID.toString(), code: "123456" },
421
+ });
422
+
423
+ expect(result.nextCallCount).toBe(1);
424
+ expect(result.thrown).toBeInstanceOf(Error);
425
+ });
426
+ });
427
+ });
@@ -0,0 +1,158 @@
1
+ import InMemoryTTLCache from "../../../Server/Infrastructure/InMemoryTTLCache";
2
+ import { afterEach, describe, expect, jest, test } from "@jest/globals";
3
+
4
+ /*
5
+ * Contract under test — the bounded TTL cache the telemetry ingest rule
6
+ * caches (log/trace pipelines, drop filters, scrub rules, metric rules)
7
+ * sit on. Two properties matter for those callers:
8
+ *
9
+ * 1. Expiry physically deletes: a read past the TTL must both miss AND
10
+ * shrink the store, or per-project entries accumulate for every tenant
11
+ * ever seen by a long-lived ingest process.
12
+ * 2. Capacity is a hard cap with oldest-write eviction, so the cache can
13
+ * never grow past maxEntries no matter how many distinct keys arrive.
14
+ */
15
+
16
+ /*
17
+ * Minimal structural view of a jest spy — the @jest/globals and @types/jest
18
+ * spy types disagree in this repo, so annotate with just the surface these
19
+ * tests use.
20
+ */
21
+ type NowSpyLike = {
22
+ mockReturnValue: (value: number) => unknown;
23
+ mockRestore: () => void;
24
+ };
25
+
26
+ function spyNow(value: number): NowSpyLike {
27
+ const spy: NowSpyLike = jest.spyOn(Date, "now") as unknown as NowSpyLike;
28
+ spy.mockReturnValue(value);
29
+ return spy;
30
+ }
31
+
32
+ afterEach(() => {
33
+ jest.restoreAllMocks();
34
+ });
35
+
36
+ describe("InMemoryTTLCache TTL behavior", () => {
37
+ test("get returns the value within its TTL", () => {
38
+ const cache: InMemoryTTLCache<string> = new InMemoryTTLCache<string>(3);
39
+
40
+ cache.set("a", "value-a", 60_000);
41
+
42
+ expect(cache.get("a")).toBe("value-a");
43
+ expect(cache.has("a")).toBe(true);
44
+ expect(cache.size()).toBe(1);
45
+ });
46
+
47
+ test("get past the TTL misses AND physically deletes the entry", () => {
48
+ const t0: number = 1_000_000;
49
+ const nowSpy: NowSpyLike = spyNow(t0);
50
+
51
+ const cache: InMemoryTTLCache<string> = new InMemoryTTLCache<string>(3);
52
+ cache.set("a", "value-a", 1_000);
53
+ expect(cache.size()).toBe(1);
54
+
55
+ // Boundary: at exactly expiresAt the entry is still valid (strict >).
56
+ nowSpy.mockReturnValue(t0 + 1_000);
57
+ expect(cache.get("a")).toBe("value-a");
58
+ expect(cache.size()).toBe(1);
59
+
60
+ nowSpy.mockReturnValue(t0 + 1_001);
61
+ expect(cache.get("a")).toBeUndefined();
62
+ expect(cache.size()).toBe(0);
63
+ });
64
+
65
+ test("has() reports false for an expired entry and deletes it", () => {
66
+ const t0: number = 1_000_000;
67
+ const nowSpy: NowSpyLike = spyNow(t0);
68
+
69
+ const cache: InMemoryTTLCache<string> = new InMemoryTTLCache<string>(3);
70
+ cache.set("a", "value-a", 1_000);
71
+
72
+ nowSpy.mockReturnValue(t0 + 5_000);
73
+ expect(cache.has("a")).toBe(false);
74
+ expect(cache.size()).toBe(0);
75
+ });
76
+ });
77
+
78
+ describe("InMemoryTTLCache capacity eviction", () => {
79
+ test("insert beyond capacity evicts the oldest key", () => {
80
+ const cache: InMemoryTTLCache<string> = new InMemoryTTLCache<string>(3);
81
+
82
+ cache.set("a", "value-a", 60_000);
83
+ cache.set("b", "value-b", 60_000);
84
+ cache.set("c", "value-c", 60_000);
85
+ cache.set("d", "value-d", 60_000);
86
+
87
+ expect(cache.size()).toBe(3);
88
+ expect(cache.get("a")).toBeUndefined();
89
+ expect(cache.get("b")).toBe("value-b");
90
+ expect(cache.get("c")).toBe("value-c");
91
+ expect(cache.get("d")).toBe("value-d");
92
+ });
93
+
94
+ test("re-setting an existing key refreshes insertion order so it is not the eviction victim", () => {
95
+ const cache: InMemoryTTLCache<string> = new InMemoryTTLCache<string>(3);
96
+
97
+ cache.set("a", "value-a", 60_000);
98
+ cache.set("b", "value-b", 60_000);
99
+ cache.set("c", "value-c", 60_000);
100
+
101
+ // Overwrite at capacity: no eviction, "a" moves to newest position.
102
+ cache.set("a", "value-a2", 60_000);
103
+ expect(cache.size()).toBe(3);
104
+ expect(cache.get("b")).toBe("value-b");
105
+ expect(cache.get("c")).toBe("value-c");
106
+
107
+ // Next new key evicts "b" (now the oldest), not the refreshed "a".
108
+ cache.set("d", "value-d", 60_000);
109
+ expect(cache.size()).toBe(3);
110
+ expect(cache.get("a")).toBe("value-a2");
111
+ expect(cache.get("b")).toBeUndefined();
112
+ expect(cache.get("c")).toBe("value-c");
113
+ expect(cache.get("d")).toBe("value-d");
114
+ });
115
+ });
116
+
117
+ describe("InMemoryTTLCache basics", () => {
118
+ test("values are stored by reference", () => {
119
+ const cache: InMemoryTTLCache<Array<string>> = new InMemoryTTLCache<
120
+ Array<string>
121
+ >(3);
122
+
123
+ const value: Array<string> = [];
124
+ cache.set("a", value, 60_000);
125
+
126
+ expect(cache.get("a")).toBe(value);
127
+ });
128
+
129
+ test("delete removes an entry", () => {
130
+ const cache: InMemoryTTLCache<string> = new InMemoryTTLCache<string>(3);
131
+
132
+ cache.set("a", "value-a", 60_000);
133
+ cache.delete("a");
134
+
135
+ expect(cache.get("a")).toBeUndefined();
136
+ expect(cache.has("a")).toBe(false);
137
+ expect(cache.size()).toBe(0);
138
+ });
139
+
140
+ test("clear empties the cache", () => {
141
+ const cache: InMemoryTTLCache<string> = new InMemoryTTLCache<string>(3);
142
+
143
+ cache.set("a", "value-a", 60_000);
144
+ cache.set("b", "value-b", 60_000);
145
+ cache.clear();
146
+
147
+ expect(cache.size()).toBe(0);
148
+ expect(cache.get("a")).toBeUndefined();
149
+ expect(cache.get("b")).toBeUndefined();
150
+ });
151
+
152
+ test("has returns false for a key that was never set", () => {
153
+ const cache: InMemoryTTLCache<string> = new InMemoryTTLCache<string>(3);
154
+
155
+ expect(cache.has("missing")).toBe(false);
156
+ expect(cache.get("missing")).toBeUndefined();
157
+ });
158
+ });
@@ -20,16 +20,14 @@ import { AddDeviceRoleAndDeclaredLinkParent1787400000000 } from "../../../../Ser
20
20
  * either would silently restate every device and every link in every
21
21
  * project as something an operator had chosen.
22
22
  *
23
- * The second is ORDERING. This is the newest registered migration, so it
24
- * inherits the guard that used to live in
25
- * EpisodeMemberNotifyIndexesMigration.test.ts: its timestamp must sort
26
- * above every other. A migration generated with `generate-postgres-
27
- * migration` carries a WALL-CLOCK timestamp, and the recent migrations in
28
- * this repo use hand-picked round numbers that run ahead of it so the
29
- * generated file lands below several already-registered migrations unless
30
- * somebody renumbers it. That is exactly what happened to this one.
31
- * Whoever adds the next migration should move this test's ordering block
32
- * to theirs.
23
+ * The second is REGISTRATION: an import that never reaches the default
24
+ * export array leaves the migration unregistered, and it silently never
25
+ * runs.
26
+ *
27
+ * The ordering guard this file used to carry "this is the newest
28
+ * migration, so its timestamp must sort above every other" has moved on
29
+ * to AddNetworkDeviceReachabilityColumnsMigration.test.ts, which is now the
30
+ * newest. Whoever adds the next migration should move it again.
33
31
  */
34
32
 
35
33
  const MIGRATION_PATH: string = path.join(
@@ -39,15 +37,6 @@ const MIGRATION_PATH: string = path.join(
39
37
 
40
38
  const SOURCE: string = fs.readFileSync(MIGRATION_PATH, "utf8");
41
39
 
42
- interface MigrationClass {
43
- name: string;
44
- }
45
-
46
- function timestampOf(migrationClass: MigrationClass): number | null {
47
- const match: RegExpMatchArray | null = migrationClass.name.match(/(\d+)$/);
48
- return match ? Number(match[1]) : null;
49
- }
50
-
51
40
  describe("the columns it adds", () => {
52
41
  test("NetworkDevice gains deviceRole", () => {
53
42
  expect(SOURCE).toContain(
@@ -190,50 +179,10 @@ describe("the migration runs", () => {
190
179
  );
191
180
  });
192
181
 
193
- // The guard described in the header. Hand it to the next migration.
194
- test("its timestamp sorts after every other registered migration", () => {
195
- const ourTimestamp: number | null = timestampOf(
196
- AddDeviceRoleAndDeclaredLinkParent1787400000000,
197
- );
198
-
199
- expect(ourTimestamp).not.toBeNull();
200
-
201
- const otherTimestamps: Array<number> = [];
202
-
203
- for (const migrationClass of SchemaMigrations) {
204
- if (migrationClass === AddDeviceRoleAndDeclaredLinkParent1787400000000) {
205
- continue;
206
- }
207
-
208
- const timestamp: number | null = timestampOf(
209
- migrationClass as MigrationClass,
210
- );
211
-
212
- if (timestamp !== null) {
213
- otherTimestamps.push(timestamp);
214
- }
215
- }
216
-
217
- /*
218
- * Math.max() of an empty list is -Infinity, which every timestamp beats.
219
- * Prove the list was actually enumerated before leaning on the maximum.
220
- */
221
- expect(otherTimestamps.length).toBeGreaterThan(100);
222
-
223
- expect(ourTimestamp).toBeGreaterThan(Math.max(...otherTimestamps));
224
- });
225
-
226
- test("it is registered last, matching that timestamp", () => {
227
- expect(SchemaMigrations[SchemaMigrations.length - 1]).toBe(
228
- AddDeviceRoleAndDeclaredLinkParent1787400000000,
229
- );
230
- });
231
-
232
182
  /*
233
183
  * ...and the timestamp in the class name is the one on disk. A class
234
184
  * renamed without renaming its file (or two migrations landing on the
235
- * same timestamp) leaves the ordering above asserting something that is
236
- * not what actually runs.
185
+ * same timestamp) runs in an order nobody declared.
237
186
  */
238
187
  test("exactly one file on disk carries its timestamp, and it is this one", () => {
239
188
  const directory: string = path.dirname(MIGRATION_PATH);