@oneuptime/common 12.0.13 → 12.0.15

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 (561) hide show
  1. package/Models/DatabaseModels/GlobalOidc.ts +20 -0
  2. package/Models/DatabaseModels/GlobalSso.ts +20 -0
  3. package/Models/DatabaseModels/MarketingConversion.ts +19 -9
  4. package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +46 -0
  5. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
  6. package/Models/DatabaseModels/StatusPage.ts +7 -4
  7. package/Models/DatabaseModels/UserCall.ts +94 -3
  8. package/Models/DatabaseModels/UserEmail.ts +94 -3
  9. package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
  10. package/Models/DatabaseModels/UserPush.ts +37 -0
  11. package/Models/DatabaseModels/UserSMS.ts +94 -3
  12. package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
  13. package/Server/API/BaseAPI.ts +79 -14
  14. package/Server/API/StatusPageAPI.ts +29 -4
  15. package/Server/API/UserCallAPI.ts +53 -45
  16. package/Server/API/UserEmailAPI.ts +53 -44
  17. package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
  18. package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
  19. package/Server/API/UserPushAPI.ts +126 -2
  20. package/Server/API/UserSmsAPI.ts +53 -44
  21. package/Server/API/UserWhatsAppAPI.ts +53 -50
  22. package/Server/EnvironmentConfig.ts +7 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.ts +19 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.ts +40 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  29. package/Server/Middleware/SlackAuthorization.ts +43 -6
  30. package/Server/Middleware/UserAuthorization.ts +236 -26
  31. package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
  32. package/Server/Middleware/WhatsAppAuthorization.ts +43 -3
  33. package/Server/Services/AnalyticsDatabaseService.ts +169 -0
  34. package/Server/Services/DatabaseService.ts +101 -0
  35. package/Server/Services/GlobalOidcProjectService.ts +126 -1
  36. package/Server/Services/GlobalOidcService.ts +132 -0
  37. package/Server/Services/GlobalSsoProjectService.ts +126 -1
  38. package/Server/Services/GlobalSsoService.ts +132 -0
  39. package/Server/Services/LogAggregationService.ts +5 -0
  40. package/Server/Services/PushNotificationService.ts +127 -12
  41. package/Server/Services/TeamMemberService.ts +53 -13
  42. package/Server/Services/UserCallService.ts +55 -24
  43. package/Server/Services/UserEmailService.ts +83 -17
  44. package/Server/Services/UserIncomingCallNumberService.ts +49 -85
  45. package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
  46. package/Server/Services/UserNotificationRuleService.ts +26 -0
  47. package/Server/Services/UserPushService.ts +89 -0
  48. package/Server/Services/UserSmsService.ts +50 -17
  49. package/Server/Services/UserWhatsAppService.ts +48 -15
  50. package/Server/Types/Database/QueryHelper.ts +30 -0
  51. package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
  52. package/Server/Utils/ChannelVerification.ts +510 -0
  53. package/Server/Utils/CronTab.ts +73 -0
  54. package/Server/Utils/GlobalSsoAuthorization.ts +175 -0
  55. package/Server/Utils/Marketing/ConversionUploadProvider.ts +35 -5
  56. package/Server/Utils/Marketing/Providers/GoogleAds.ts +1 -1
  57. package/Server/Utils/Marketing/Providers/LinkedIn.ts +1 -1
  58. package/Server/Utils/Marketing/Providers/Meta.ts +1 -1
  59. package/Server/Utils/Marketing/Providers/MicrosoftAds.ts +1 -1
  60. package/Server/Utils/Marketing/Providers/Reddit.ts +1 -1
  61. package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +48 -33
  62. package/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.ts +35 -30
  63. package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +33 -28
  64. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +475 -47
  65. package/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.ts +35 -30
  66. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +47 -44
  67. package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +33 -28
  68. package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +69 -40
  69. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +35 -29
  70. package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
  71. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +8 -0
  72. package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
  73. package/Server/Utils/Monitor/MonitorResource.ts +161 -21
  74. package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
  75. package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
  76. package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
  77. package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
  78. package/Server/Utils/StatusPageContentSecurityPolicy.ts +56 -0
  79. package/Server/Utils/StatusPageCustomizationAccess.ts +117 -0
  80. package/Server/Utils/TotpAuth.ts +137 -9
  81. package/Server/Utils/UserRegistrationToken.ts +182 -0
  82. package/Server/Utils/VerificationCode.ts +134 -0
  83. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
  84. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
  85. package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
  86. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
  87. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
  88. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
  89. package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
  90. package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
  91. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
  92. package/Tests/Server/API/StatusPageCustomizationOrigin.test.ts +348 -0
  93. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
  94. package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
  95. package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
  96. package/Tests/Server/API/UserSmsApi.test.ts +107 -14
  97. package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
  98. package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +265 -0
  99. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +227 -0
  100. package/Tests/Server/Middleware/SlackAuthorization.test.ts +149 -0
  101. package/Tests/Server/Middleware/UserAuthorization.test.ts +27 -13
  102. package/Tests/Server/Middleware/UserAuthorizationGlobalSsoGovernance.test.ts +1455 -0
  103. package/Tests/Server/Middleware/UserAuthorizationSSOProvider.test.ts +91 -2
  104. package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
  105. package/Tests/Server/Middleware/WhatsAppAuthorization.test.ts +233 -0
  106. package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
  107. package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
  108. package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
  109. package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
  110. package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
  111. package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
  112. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
  113. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +21 -8
  114. package/Tests/Server/Services/GlobalSsoProviderAuthorization.test.ts +1242 -0
  115. package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
  116. package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
  117. package/Tests/Server/Services/MonitorResourceProbeAgreementHydration.test.ts +459 -0
  118. package/Tests/Server/Services/MonitorResourceProbeAgreementReuse.test.ts +10 -0
  119. package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
  120. package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
  121. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
  122. package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
  123. package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
  124. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
  125. package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
  126. package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
  127. package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
  128. package/Tests/Server/Types/AnalyticsDatabase/AggregateUtilBucketTimestamp.test.ts +416 -0
  129. package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
  130. package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
  131. package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
  132. package/Tests/Server/Types/Database/QueryHelperManyToManyAndEmptyValues.test.ts +551 -0
  133. package/Tests/Server/Types/Database/SelectUtil.test.ts +348 -0
  134. package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
  135. package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
  136. package/Tests/Server/Utils/Browser.test.ts +162 -0
  137. package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
  138. package/Tests/Server/Utils/CronTab.test.ts +116 -0
  139. package/Tests/Server/Utils/Express.test.ts +371 -0
  140. package/Tests/Server/Utils/GlobalSSOToken.test.ts +581 -0
  141. package/Tests/Server/Utils/GlobalSsoAuthorization.test.ts +1401 -0
  142. package/Tests/Server/Utils/Marketing/AdUploadableConversionTypes.test.ts +254 -0
  143. package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +1 -1
  144. package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaEvaluateOverTime.test.ts +508 -0
  145. package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +30 -9
  146. package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
  147. package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
  148. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +987 -0
  149. package/Tests/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.test.ts +916 -0
  150. package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
  151. package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
  152. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +382 -0
  153. package/Tests/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.test.ts +1219 -0
  154. package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
  155. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
  156. package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
  157. package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
  158. package/Tests/Server/Utils/Monitor/MonitorResourceIngestedStepSelection.test.ts +86 -0
  159. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
  160. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
  161. package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
  162. package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
  163. package/Tests/Server/Utils/StatusPageContentSecurityPolicy.test.ts +136 -0
  164. package/Tests/Server/Utils/StatusPageCustomizationAccess.test.ts +223 -0
  165. package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
  166. package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
  167. package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
  168. package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
  169. package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
  170. package/Tests/Types/Call/CallRequest.test.ts +189 -0
  171. package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
  172. package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
  173. package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
  174. package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
  175. package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
  176. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
  177. package/Tests/Types/Monitor/MonitorStepConfigHelpers.test.ts +165 -0
  178. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
  179. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
  180. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
  181. package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
  182. package/Tests/Types/NetworkDevice/NetworkDeviceLinkRuleScope.test.ts +215 -0
  183. package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
  184. package/Tests/Types/TextRandomGeneration.test.ts +211 -0
  185. package/Tests/UI/Components/Button.test.tsx +175 -1
  186. package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
  187. package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
  188. package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
  189. package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
  190. package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
  191. package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
  192. package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
  193. package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
  194. package/Tests/UI/Components/Forms/FormSubmitAnalytics.test.tsx +206 -0
  195. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
  196. package/Tests/UI/Components/List.test.tsx +9 -2
  197. package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
  198. package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
  199. package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
  200. package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
  201. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
  202. package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
  203. package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
  204. package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
  205. package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
  206. package/Tests/UI/Components/Skeleton.test.tsx +71 -0
  207. package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
  208. package/Tests/UI/Components/Tabs.test.tsx +24 -0
  209. package/Tests/UI/Components/Toast.test.tsx +130 -7
  210. package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
  211. package/Tests/UI/Utils/AIChatExport/ConversationMarkdown.test.ts +774 -0
  212. package/Tests/UI/Utils/AIChatExport/MarkdownBlocks.test.ts +791 -0
  213. package/Tests/UI/Utils/AIChatExport/MarkdownSafety.test.ts +544 -0
  214. package/Tests/UI/Utils/Dropdown.test.ts +423 -0
  215. package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
  216. package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
  217. package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
  218. package/Tests/Utils/API.test.ts +16 -2
  219. package/Tests/Utils/Analytics.test.ts +187 -0
  220. package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
  221. package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
  222. package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
  223. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +80 -0
  224. package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +1291 -0
  225. package/Tests/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.test.ts +214 -0
  226. package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
  227. package/Types/Email/EmailTemplateType.ts +1 -0
  228. package/Types/Marketing/MarketingConversion.ts +12 -0
  229. package/Types/Monitor/CriteriaFilter.ts +9 -0
  230. package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
  231. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
  232. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
  233. package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
  234. package/Types/NetworkDevice/NetworkDeviceLinkRuleScope.ts +51 -0
  235. package/Types/Permission.ts +35 -0
  236. package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
  237. package/Types/PushNotification/PushNotificationMessage.ts +15 -0
  238. package/Types/PushNotification/PushNotificationRequest.ts +8 -16
  239. package/Types/Service/ServiceLanguage.ts +144 -0
  240. package/Types/Text.ts +111 -19
  241. package/UI/Components/Button/Button.tsx +27 -14
  242. package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
  243. package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
  244. package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
  245. package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
  246. package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
  247. package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
  248. package/UI/Components/CommandPalette/Types.ts +49 -0
  249. package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
  250. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  251. package/UI/Components/Feed/FeedItem.tsx +1 -1
  252. package/UI/Components/FormModal/BasicFormModal.tsx +12 -0
  253. package/UI/Components/Forms/BasicForm.tsx +13 -1
  254. package/UI/Components/Forms/BasicModelForm.tsx +2 -1
  255. package/UI/Components/Forms/ModelForm.tsx +10 -1
  256. package/UI/Components/Forms/Utils/FormAnalyticsName.ts +39 -0
  257. package/UI/Components/List/List.tsx +37 -5
  258. package/UI/Components/List/ListSkeleton.tsx +54 -0
  259. package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
  260. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
  261. package/UI/Components/Modal/Modal.tsx +2 -2
  262. package/UI/Components/ModelFormModal/ModelFormModal.tsx +6 -1
  263. package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
  264. package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
  265. package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
  266. package/UI/Components/Navbar/NavBar.tsx +14 -1
  267. package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
  268. package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
  269. package/UI/Components/SideOver/SideOver.tsx +37 -2
  270. package/UI/Components/Skeleton/Skeleton.tsx +53 -0
  271. package/UI/Components/Table/Table.tsx +74 -44
  272. package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
  273. package/UI/Components/Tabs/Tab.tsx +1 -1
  274. package/UI/Components/Toast/Toast.tsx +118 -53
  275. package/UI/Components/Toast/ToastInit.tsx +82 -32
  276. package/UI/Styles/Theme.css +40 -0
  277. package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
  278. package/UI/Utils/ModelListCache.ts +188 -0
  279. package/UI/Utils/Project.ts +29 -0
  280. package/Utils/API.ts +6 -1
  281. package/Utils/Analytics.ts +55 -2
  282. package/Utils/Monitor/MonitorMetricType.ts +40 -0
  283. package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +587 -37
  284. package/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.ts +115 -0
  285. package/build/dist/Models/DatabaseModels/GlobalOidc.js +21 -0
  286. package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
  287. package/build/dist/Models/DatabaseModels/GlobalSso.js +21 -0
  288. package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
  289. package/build/dist/Models/DatabaseModels/MarketingConversion.js +20 -10
  290. package/build/dist/Models/DatabaseModels/MarketingConversion.js.map +1 -1
  291. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +47 -0
  292. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -1
  293. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
  294. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  295. package/build/dist/Models/DatabaseModels/StatusPage.js +4 -4
  296. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  297. package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
  298. package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
  299. package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
  300. package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
  301. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
  302. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
  303. package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
  304. package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
  305. package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
  306. package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
  307. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
  308. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
  309. package/build/dist/Server/API/BaseAPI.js +69 -13
  310. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  311. package/build/dist/Server/API/StatusPageAPI.js +25 -4
  312. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  313. package/build/dist/Server/API/UserCallAPI.js +42 -38
  314. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  315. package/build/dist/Server/API/UserEmailAPI.js +42 -38
  316. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  317. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
  318. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  319. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
  320. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
  321. package/build/dist/Server/API/UserPushAPI.js +95 -2
  322. package/build/dist/Server/API/UserPushAPI.js.map +1 -1
  323. package/build/dist/Server/API/UserSmsAPI.js +42 -38
  324. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  325. package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
  326. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  327. package/build/dist/Server/EnvironmentConfig.js +6 -0
  328. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  329. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
  330. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
  331. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
  332. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
  333. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
  334. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
  335. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js +12 -0
  336. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js.map +1 -0
  337. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js +29 -0
  338. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js.map +1 -0
  339. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  340. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  341. package/build/dist/Server/Middleware/SlackAuthorization.js +28 -4
  342. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  343. package/build/dist/Server/Middleware/UserAuthorization.js +197 -22
  344. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  345. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
  346. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
  347. package/build/dist/Server/Middleware/WhatsAppAuthorization.js +32 -2
  348. package/build/dist/Server/Middleware/WhatsAppAuthorization.js.map +1 -1
  349. package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
  350. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  351. package/build/dist/Server/Services/DatabaseService.js +74 -0
  352. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  353. package/build/dist/Server/Services/GlobalOidcProjectService.js +105 -0
  354. package/build/dist/Server/Services/GlobalOidcProjectService.js.map +1 -1
  355. package/build/dist/Server/Services/GlobalOidcService.js +127 -0
  356. package/build/dist/Server/Services/GlobalOidcService.js.map +1 -1
  357. package/build/dist/Server/Services/GlobalSsoProjectService.js +105 -0
  358. package/build/dist/Server/Services/GlobalSsoProjectService.js.map +1 -1
  359. package/build/dist/Server/Services/GlobalSsoService.js +127 -0
  360. package/build/dist/Server/Services/GlobalSsoService.js.map +1 -1
  361. package/build/dist/Server/Services/LogAggregationService.js +5 -0
  362. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  363. package/build/dist/Server/Services/PushNotificationService.js +69 -30
  364. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  365. package/build/dist/Server/Services/TeamMemberService.js +43 -7
  366. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  367. package/build/dist/Server/Services/UserCallService.js +54 -22
  368. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  369. package/build/dist/Server/Services/UserEmailService.js +78 -17
  370. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  371. package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
  372. package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
  373. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
  374. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
  375. package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
  376. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  377. package/build/dist/Server/Services/UserPushService.js +77 -0
  378. package/build/dist/Server/Services/UserPushService.js.map +1 -1
  379. package/build/dist/Server/Services/UserSmsService.js +50 -17
  380. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  381. package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
  382. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
  383. package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
  384. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  385. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
  386. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
  387. package/build/dist/Server/Utils/ChannelVerification.js +348 -0
  388. package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
  389. package/build/dist/Server/Utils/CronTab.js +66 -0
  390. package/build/dist/Server/Utils/CronTab.js.map +1 -1
  391. package/build/dist/Server/Utils/GlobalSsoAuthorization.js +112 -0
  392. package/build/dist/Server/Utils/GlobalSsoAuthorization.js.map +1 -0
  393. package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js +17 -1
  394. package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js.map +1 -1
  395. package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js +1 -1
  396. package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js.map +1 -1
  397. package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js +1 -1
  398. package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js.map +1 -1
  399. package/build/dist/Server/Utils/Marketing/Providers/Meta.js +1 -1
  400. package/build/dist/Server/Utils/Marketing/Providers/Meta.js.map +1 -1
  401. package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js +1 -1
  402. package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js.map +1 -1
  403. package/build/dist/Server/Utils/Marketing/Providers/Reddit.js +1 -1
  404. package/build/dist/Server/Utils/Marketing/Providers/Reddit.js.map +1 -1
  405. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +37 -35
  406. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
  407. package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js +21 -25
  408. package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js.map +1 -1
  409. package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +20 -22
  410. package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
  411. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +370 -42
  412. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  413. package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js +21 -25
  414. package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js.map +1 -1
  415. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +34 -37
  416. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
  417. package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +21 -25
  418. package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js.map +1 -1
  419. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +64 -52
  420. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
  421. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +25 -29
  422. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  423. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
  424. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  425. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +8 -0
  426. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  427. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
  428. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  429. package/build/dist/Server/Utils/Monitor/MonitorResource.js +123 -23
  430. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  431. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
  432. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
  433. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
  434. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
  435. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
  436. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
  437. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
  438. package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js +39 -0
  439. package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js.map +1 -0
  440. package/build/dist/Server/Utils/StatusPageCustomizationAccess.js +85 -0
  441. package/build/dist/Server/Utils/StatusPageCustomizationAccess.js.map +1 -0
  442. package/build/dist/Server/Utils/TotpAuth.js +127 -8
  443. package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
  444. package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
  445. package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
  446. package/build/dist/Server/Utils/VerificationCode.js +120 -0
  447. package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
  448. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  449. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  450. package/build/dist/Types/Marketing/MarketingConversion.js +10 -0
  451. package/build/dist/Types/Marketing/MarketingConversion.js.map +1 -1
  452. package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
  453. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  454. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
  455. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  456. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
  457. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  458. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
  459. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  460. package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
  461. package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
  462. package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js +46 -0
  463. package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js.map +1 -0
  464. package/build/dist/Types/Permission.js +33 -0
  465. package/build/dist/Types/Permission.js.map +1 -1
  466. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
  467. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
  468. package/build/dist/Types/Service/ServiceLanguage.js +96 -0
  469. package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
  470. package/build/dist/Types/Text.js +82 -17
  471. package/build/dist/Types/Text.js.map +1 -1
  472. package/build/dist/UI/Components/Button/Button.js +22 -14
  473. package/build/dist/UI/Components/Button/Button.js.map +1 -1
  474. package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
  475. package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
  476. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
  477. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
  478. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
  479. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
  480. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
  481. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
  482. package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
  483. package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
  484. package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
  485. package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
  486. package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
  487. package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
  488. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
  489. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
  490. package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
  491. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  492. package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
  493. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  494. package/build/dist/UI/Components/FormModal/BasicFormModal.js +2 -1
  495. package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
  496. package/build/dist/UI/Components/Forms/BasicForm.js +10 -1
  497. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  498. package/build/dist/UI/Components/Forms/BasicModelForm.js +2 -1
  499. package/build/dist/UI/Components/Forms/BasicModelForm.js.map +1 -1
  500. package/build/dist/UI/Components/Forms/ModelForm.js +4 -1
  501. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  502. package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js +33 -0
  503. package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js.map +1 -0
  504. package/build/dist/UI/Components/List/List.js +19 -5
  505. package/build/dist/UI/Components/List/List.js.map +1 -1
  506. package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
  507. package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
  508. package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
  509. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
  510. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  511. package/build/dist/UI/Components/Modal/Modal.js +2 -2
  512. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js +2 -1
  513. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
  514. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
  515. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  516. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
  517. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
  518. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
  519. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  520. package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
  521. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  522. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
  523. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
  524. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
  525. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
  526. package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
  527. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  528. package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
  529. package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
  530. package/build/dist/UI/Components/Table/Table.js +35 -24
  531. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  532. package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
  533. package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
  534. package/build/dist/UI/Components/Tabs/Tab.js +1 -1
  535. package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
  536. package/build/dist/UI/Components/Toast/Toast.js +77 -23
  537. package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
  538. package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
  539. package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
  540. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
  541. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  542. package/build/dist/UI/Utils/ModelListCache.js +126 -0
  543. package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
  544. package/build/dist/UI/Utils/Project.js +24 -1
  545. package/build/dist/UI/Utils/Project.js.map +1 -1
  546. package/build/dist/Utils/API.js +6 -1
  547. package/build/dist/Utils/API.js.map +1 -1
  548. package/build/dist/Utils/Analytics.js +50 -2
  549. package/build/dist/Utils/Analytics.js.map +1 -1
  550. package/build/dist/Utils/Monitor/MonitorMetricType.js +37 -0
  551. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  552. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +318 -37
  553. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -1
  554. package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js +87 -0
  555. package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js.map +1 -0
  556. package/jest.config.json +1 -1
  557. package/package.json +2 -3
  558. package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
  559. package/Tests/__mocks__/otpauth.js +0 -30
  560. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
  561. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
@@ -0,0 +1,1219 @@
1
+ import ServerMonitorCriteria from "../../../../../Server/Utils/Monitor/Criteria/ServerMonitorCriteria";
2
+ import EvaluateOverTime, {
3
+ OverTimeCriteriaValue,
4
+ } from "../../../../../Server/Utils/Monitor/Criteria/EvaluateOverTime";
5
+ import BasicInfrastructureMetrics, {
6
+ BasicDiskMetrics,
7
+ LoadMetrics,
8
+ } from "../../../../../Types/Infrastructure/BasicMetrics";
9
+ import {
10
+ CheckOn,
11
+ CriteriaFilter,
12
+ EvaluateOverTimeType,
13
+ FilterType,
14
+ } from "../../../../../Types/Monitor/CriteriaFilter";
15
+ import ServerMonitorResponse, {
16
+ ServerProcess,
17
+ } from "../../../../../Types/Monitor/ServerMonitor/ServerMonitorResponse";
18
+ import ObjectID from "../../../../../Types/ObjectID";
19
+ import { afterEach, describe, expect, jest, test } from "@jest/globals";
20
+
21
+ /*
22
+ * Fixed reference "now" so that the difference-in-minutes computation the
23
+ * evaluator performs (requestReceivedAt vs timeNow) is fully deterministic
24
+ * and never touches the wall clock.
25
+ */
26
+ const BASE_TIME: Date = new Date("2026-08-20T12:00:00.000Z");
27
+
28
+ /*
29
+ * Build a BasicInfrastructureMetrics payload. Every sub-metric has a benign
30
+ * default so an individual test only supplies the field it exercises.
31
+ */
32
+ function buildMetrics(input: {
33
+ cpuPercentUsed?: number | undefined;
34
+ cpuIoWaitPercent?: number | undefined;
35
+ memoryPercentUsed?: number | undefined;
36
+ swapPercentUsed?: number | undefined;
37
+ diskMetrics?: Array<BasicDiskMetrics> | undefined;
38
+ loadMetrics?: LoadMetrics | undefined;
39
+ }): BasicInfrastructureMetrics {
40
+ return {
41
+ cpuMetrics: {
42
+ percentUsed: input.cpuPercentUsed ?? 0,
43
+ cores: 4,
44
+ timeIoWaitPercent: input.cpuIoWaitPercent,
45
+ },
46
+ memoryMetrics: {
47
+ total: 100,
48
+ free: 50,
49
+ used: 50,
50
+ percentUsed: input.memoryPercentUsed ?? 0,
51
+ percentFree: 100 - (input.memoryPercentUsed ?? 0),
52
+ swapPercentUsed: input.swapPercentUsed,
53
+ },
54
+ diskMetrics: input.diskMetrics ?? [],
55
+ loadMetrics: input.loadMetrics,
56
+ };
57
+ }
58
+
59
+ /*
60
+ * Build a single disk metric entry. percentUsed / percentFree are optional so
61
+ * the evaluator's `percentUsed ?? percentFree ?? 0` fallback chain can be
62
+ * exercised; the cast tolerates the deliberately-absent required field.
63
+ */
64
+ function buildDiskMetric(input: {
65
+ diskPath: string;
66
+ percentUsed?: number | undefined;
67
+ percentFree?: number | undefined;
68
+ }): BasicDiskMetrics {
69
+ return {
70
+ total: 100,
71
+ free: 40,
72
+ used: 60,
73
+ diskPath: input.diskPath,
74
+ percentUsed: input.percentUsed as number,
75
+ percentFree: input.percentFree as number,
76
+ };
77
+ }
78
+
79
+ function buildProcess(input: {
80
+ pid?: number | undefined;
81
+ name?: string | undefined;
82
+ command?: string | undefined;
83
+ }): ServerProcess {
84
+ return {
85
+ pid: input.pid ?? 1,
86
+ name: input.name ?? "proc",
87
+ command: input.command ?? "/bin/proc",
88
+ };
89
+ }
90
+
91
+ /*
92
+ * Build a ServerMonitorResponse. `minutesSinceLastCheck` positions
93
+ * requestReceivedAt that many minutes before the fixed timeNow, which drives
94
+ * the online/offline decision for IsOnline checks.
95
+ */
96
+ function buildServerResponse(input: {
97
+ metrics?: BasicInfrastructureMetrics | undefined;
98
+ processes?: Array<ServerProcess> | undefined;
99
+ onlyCheckRequestReceivedAt?: boolean | undefined;
100
+ minutesSinceLastCheck?: number | undefined;
101
+ }): ServerMonitorResponse {
102
+ const minutesAgo: number = input.minutesSinceLastCheck ?? 0;
103
+
104
+ return {
105
+ projectId: ObjectID.generate(),
106
+ monitorId: ObjectID.generate(),
107
+ hostname: "test-host",
108
+ requestReceivedAt: new Date(BASE_TIME.getTime() - minutesAgo * 60000),
109
+ timeNow: BASE_TIME,
110
+ onlyCheckRequestReceivedAt: input.onlyCheckRequestReceivedAt ?? false,
111
+ basicInfrastructureMetrics: input.metrics,
112
+ processes: input.processes,
113
+ };
114
+ }
115
+
116
+ async function evaluate(
117
+ dataToProcess: ServerMonitorResponse,
118
+ criteriaFilter: CriteriaFilter,
119
+ ): Promise<string | null> {
120
+ return ServerMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
121
+ dataToProcess,
122
+ criteriaFilter,
123
+ });
124
+ }
125
+
126
+ describe("ServerMonitorCriteria.isMonitorInstanceCriteriaFilterMet", () => {
127
+ afterEach(() => {
128
+ jest.restoreAllMocks();
129
+ });
130
+
131
+ test("an unrelated CheckOn is not claimed by this evaluator", async () => {
132
+ const result: string | null = await evaluate(buildServerResponse({}), {
133
+ checkOn: CheckOn.ResponseTime,
134
+ filterType: FilterType.LessThan,
135
+ value: 1000,
136
+ });
137
+
138
+ expect(result).toBeNull();
139
+ });
140
+
141
+ describe("IsOnline", () => {
142
+ /*
143
+ * A recent check (difference < 3 minute default) is treated as online.
144
+ */
145
+ test("recent check + True → met", async () => {
146
+ const result: string | null = await evaluate(
147
+ buildServerResponse({ minutesSinceLastCheck: 1 }),
148
+ {
149
+ checkOn: CheckOn.IsOnline,
150
+ filterType: FilterType.True,
151
+ value: undefined,
152
+ },
153
+ );
154
+
155
+ expect(result).toContain(CheckOn.IsOnline);
156
+ expect(result).toContain("true");
157
+ });
158
+
159
+ test("recent check + False → not met", async () => {
160
+ const result: string | null = await evaluate(
161
+ buildServerResponse({ minutesSinceLastCheck: 1 }),
162
+ {
163
+ checkOn: CheckOn.IsOnline,
164
+ filterType: FilterType.False,
165
+ value: undefined,
166
+ },
167
+ );
168
+
169
+ expect(result).toBeNull();
170
+ });
171
+
172
+ /*
173
+ * A stale check (difference >= 3 minute default) is treated as offline.
174
+ */
175
+ test("stale check + False → met", async () => {
176
+ const result: string | null = await evaluate(
177
+ buildServerResponse({ minutesSinceLastCheck: 5 }),
178
+ {
179
+ checkOn: CheckOn.IsOnline,
180
+ filterType: FilterType.False,
181
+ value: undefined,
182
+ },
183
+ );
184
+
185
+ expect(result).toContain(CheckOn.IsOnline);
186
+ expect(result).toContain("false");
187
+ });
188
+
189
+ test("stale check + True → not met", async () => {
190
+ const result: string | null = await evaluate(
191
+ buildServerResponse({ minutesSinceLastCheck: 5 }),
192
+ {
193
+ checkOn: CheckOn.IsOnline,
194
+ filterType: FilterType.True,
195
+ value: undefined,
196
+ },
197
+ );
198
+
199
+ expect(result).toBeNull();
200
+ });
201
+
202
+ /*
203
+ * The offline boundary is inclusive: a difference of exactly the 3 minute
204
+ * threshold takes the offline branch.
205
+ */
206
+ test("difference exactly at the 3 minute threshold → offline branch", async () => {
207
+ const result: string | null = await evaluate(
208
+ buildServerResponse({ minutesSinceLastCheck: 3 }),
209
+ {
210
+ checkOn: CheckOn.IsOnline,
211
+ filterType: FilterType.False,
212
+ value: undefined,
213
+ },
214
+ );
215
+
216
+ expect(result).toContain("false");
217
+ });
218
+
219
+ test("difference just below the 3 minute threshold → online branch", async () => {
220
+ const result: string | null = await evaluate(
221
+ buildServerResponse({ minutesSinceLastCheck: 2 }),
222
+ {
223
+ checkOn: CheckOn.IsOnline,
224
+ filterType: FilterType.True,
225
+ value: undefined,
226
+ },
227
+ );
228
+
229
+ expect(result).toContain("true");
230
+ });
231
+
232
+ /*
233
+ * The IsOnline branches deliberately ignore onlyCheckRequestReceivedAt —
234
+ * liveness must still be evaluated on a heartbeat-only payload.
235
+ */
236
+ test("evaluates even when onlyCheckRequestReceivedAt is set", async () => {
237
+ const result: string | null = await evaluate(
238
+ buildServerResponse({
239
+ minutesSinceLastCheck: 1,
240
+ onlyCheckRequestReceivedAt: true,
241
+ }),
242
+ {
243
+ checkOn: CheckOn.IsOnline,
244
+ filterType: FilterType.True,
245
+ value: undefined,
246
+ },
247
+ );
248
+
249
+ expect(result).toContain(CheckOn.IsOnline);
250
+ });
251
+
252
+ /*
253
+ * A filter type the boolean comparator does not handle (a numeric
254
+ * operator) is undecidable for IsOnline.
255
+ */
256
+ test("unhandled filter type → undecidable", async () => {
257
+ const result: string | null = await evaluate(
258
+ buildServerResponse({ minutesSinceLastCheck: 1 }),
259
+ {
260
+ checkOn: CheckOn.IsOnline,
261
+ filterType: FilterType.GreaterThan,
262
+ value: 1,
263
+ },
264
+ );
265
+
266
+ expect(result).toBeNull();
267
+ });
268
+ });
269
+
270
+ describe("CPUUsagePercent", () => {
271
+ test("usage above threshold + GreaterThan → met", async () => {
272
+ const result: string | null = await evaluate(
273
+ buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 80 }) }),
274
+ {
275
+ checkOn: CheckOn.CPUUsagePercent,
276
+ filterType: FilterType.GreaterThan,
277
+ value: 50,
278
+ },
279
+ );
280
+
281
+ expect(result).toContain(CheckOn.CPUUsagePercent);
282
+ expect(result).toContain("greater than");
283
+ expect(result).toContain("80");
284
+ });
285
+
286
+ test("usage below threshold + GreaterThan → not met", async () => {
287
+ const result: string | null = await evaluate(
288
+ buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 30 }) }),
289
+ {
290
+ checkOn: CheckOn.CPUUsagePercent,
291
+ filterType: FilterType.GreaterThan,
292
+ value: 50,
293
+ },
294
+ );
295
+
296
+ expect(result).toBeNull();
297
+ });
298
+
299
+ test("numeric string threshold is accepted", async () => {
300
+ const result: string | null = await evaluate(
301
+ buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 80 }) }),
302
+ {
303
+ checkOn: CheckOn.CPUUsagePercent,
304
+ filterType: FilterType.GreaterThan,
305
+ value: "50",
306
+ },
307
+ );
308
+
309
+ expect(result).toContain(CheckOn.CPUUsagePercent);
310
+ });
311
+
312
+ test("non-numeric threshold → undecidable", async () => {
313
+ const result: string | null = await evaluate(
314
+ buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 80 }) }),
315
+ {
316
+ checkOn: CheckOn.CPUUsagePercent,
317
+ filterType: FilterType.GreaterThan,
318
+ value: "not-a-number",
319
+ },
320
+ );
321
+
322
+ expect(result).toBeNull();
323
+ });
324
+
325
+ /*
326
+ * With no infrastructure metrics present the CPU value falls back to 0,
327
+ * so a LessThan-1 check is met while a GreaterThan-1 check is not.
328
+ */
329
+ test("missing metrics fall back to zero usage", async () => {
330
+ const result: string | null = await evaluate(buildServerResponse({}), {
331
+ checkOn: CheckOn.CPUUsagePercent,
332
+ filterType: FilterType.LessThan,
333
+ value: 1,
334
+ });
335
+
336
+ expect(result).toContain(CheckOn.CPUUsagePercent);
337
+ });
338
+
339
+ /*
340
+ * onlyCheckRequestReceivedAt short-circuits every infrastructure metric
341
+ * branch — a heartbeat payload carries no fresh metric to evaluate.
342
+ */
343
+ test("onlyCheckRequestReceivedAt short-circuits the CPU branch", async () => {
344
+ const result: string | null = await evaluate(
345
+ buildServerResponse({
346
+ metrics: buildMetrics({ cpuPercentUsed: 90 }),
347
+ onlyCheckRequestReceivedAt: true,
348
+ }),
349
+ {
350
+ checkOn: CheckOn.CPUUsagePercent,
351
+ filterType: FilterType.GreaterThan,
352
+ value: 50,
353
+ },
354
+ );
355
+
356
+ expect(result).toBeNull();
357
+ });
358
+ });
359
+
360
+ describe("MemoryUsagePercent", () => {
361
+ test("usage below threshold + LessThan → met", async () => {
362
+ const result: string | null = await evaluate(
363
+ buildServerResponse({
364
+ metrics: buildMetrics({ memoryPercentUsed: 40 }),
365
+ }),
366
+ {
367
+ checkOn: CheckOn.MemoryUsagePercent,
368
+ filterType: FilterType.LessThan,
369
+ value: 95,
370
+ },
371
+ );
372
+
373
+ expect(result).toContain(CheckOn.MemoryUsagePercent);
374
+ });
375
+
376
+ test("usage above threshold + LessThan → not met", async () => {
377
+ const result: string | null = await evaluate(
378
+ buildServerResponse({
379
+ metrics: buildMetrics({ memoryPercentUsed: 96 }),
380
+ }),
381
+ {
382
+ checkOn: CheckOn.MemoryUsagePercent,
383
+ filterType: FilterType.LessThan,
384
+ value: 95,
385
+ },
386
+ );
387
+
388
+ expect(result).toBeNull();
389
+ });
390
+
391
+ test("usage equal to threshold + GreaterThanOrEqualTo → met (boundary)", async () => {
392
+ const result: string | null = await evaluate(
393
+ buildServerResponse({
394
+ metrics: buildMetrics({ memoryPercentUsed: 90 }),
395
+ }),
396
+ {
397
+ checkOn: CheckOn.MemoryUsagePercent,
398
+ filterType: FilterType.GreaterThanOrEqualTo,
399
+ value: 90,
400
+ },
401
+ );
402
+
403
+ expect(result).toContain(CheckOn.MemoryUsagePercent);
404
+ });
405
+ });
406
+
407
+ describe("SwapUsagePercent", () => {
408
+ test("swap usage above threshold + GreaterThan → met", async () => {
409
+ const result: string | null = await evaluate(
410
+ buildServerResponse({ metrics: buildMetrics({ swapPercentUsed: 30 }) }),
411
+ {
412
+ checkOn: CheckOn.SwapUsagePercent,
413
+ filterType: FilterType.GreaterThan,
414
+ value: 20,
415
+ },
416
+ );
417
+
418
+ expect(result).toContain(CheckOn.SwapUsagePercent);
419
+ });
420
+
421
+ test("absent swap metric falls back to zero", async () => {
422
+ const result: string | null = await evaluate(
423
+ buildServerResponse({ metrics: buildMetrics({}) }),
424
+ {
425
+ checkOn: CheckOn.SwapUsagePercent,
426
+ filterType: FilterType.GreaterThan,
427
+ value: 20,
428
+ },
429
+ );
430
+
431
+ expect(result).toBeNull();
432
+ });
433
+ });
434
+
435
+ describe("CPUIoWaitPercent", () => {
436
+ test("io wait above threshold + GreaterThan → met", async () => {
437
+ const result: string | null = await evaluate(
438
+ buildServerResponse({
439
+ metrics: buildMetrics({ cpuIoWaitPercent: 15 }),
440
+ }),
441
+ {
442
+ checkOn: CheckOn.CPUIoWaitPercent,
443
+ filterType: FilterType.GreaterThan,
444
+ value: 10,
445
+ },
446
+ );
447
+
448
+ expect(result).toContain(CheckOn.CPUIoWaitPercent);
449
+ });
450
+
451
+ test("absent io wait metric falls back to zero", async () => {
452
+ const result: string | null = await evaluate(
453
+ buildServerResponse({ metrics: buildMetrics({}) }),
454
+ {
455
+ checkOn: CheckOn.CPUIoWaitPercent,
456
+ filterType: FilterType.GreaterThan,
457
+ value: 10,
458
+ },
459
+ );
460
+
461
+ expect(result).toBeNull();
462
+ });
463
+ });
464
+
465
+ describe("LoadAverage", () => {
466
+ const load: LoadMetrics = { load1: 2, load5: 1.5, load15: 0.5 };
467
+
468
+ test("LoadAverage1Min reads the 1 minute figure", async () => {
469
+ const result: string | null = await evaluate(
470
+ buildServerResponse({ metrics: buildMetrics({ loadMetrics: load }) }),
471
+ {
472
+ checkOn: CheckOn.LoadAverage1Min,
473
+ filterType: FilterType.GreaterThan,
474
+ value: 1,
475
+ },
476
+ );
477
+
478
+ expect(result).toContain(CheckOn.LoadAverage1Min);
479
+ });
480
+
481
+ test("LoadAverage5Min reads the 5 minute figure", async () => {
482
+ const result: string | null = await evaluate(
483
+ buildServerResponse({ metrics: buildMetrics({ loadMetrics: load }) }),
484
+ {
485
+ checkOn: CheckOn.LoadAverage5Min,
486
+ filterType: FilterType.GreaterThan,
487
+ value: 1,
488
+ },
489
+ );
490
+
491
+ expect(result).toContain(CheckOn.LoadAverage5Min);
492
+ });
493
+
494
+ /*
495
+ * The 15 minute figure (0.5) is below the threshold, so the same filter
496
+ * that matched the 1 and 5 minute figures does not fire here — proving
497
+ * the correct load slot is selected per CheckOn.
498
+ */
499
+ test("LoadAverage15Min reads the 15 minute figure → not met", async () => {
500
+ const result: string | null = await evaluate(
501
+ buildServerResponse({ metrics: buildMetrics({ loadMetrics: load }) }),
502
+ {
503
+ checkOn: CheckOn.LoadAverage15Min,
504
+ filterType: FilterType.GreaterThan,
505
+ value: 1,
506
+ },
507
+ );
508
+
509
+ expect(result).toBeNull();
510
+ });
511
+
512
+ test("absent load metrics fall back to zero", async () => {
513
+ const result: string | null = await evaluate(
514
+ buildServerResponse({ metrics: buildMetrics({}) }),
515
+ {
516
+ checkOn: CheckOn.LoadAverage1Min,
517
+ filterType: FilterType.LessThan,
518
+ value: 1,
519
+ },
520
+ );
521
+
522
+ expect(result).toContain(CheckOn.LoadAverage1Min);
523
+ });
524
+ });
525
+
526
+ describe("DiskUsagePercent", () => {
527
+ /*
528
+ * A trailing slash on the requested path and none on the reported path
529
+ * still resolve to the same disk after normalization.
530
+ */
531
+ test("matches disk after path normalization and uses percentUsed", async () => {
532
+ const result: string | null = await evaluate(
533
+ buildServerResponse({
534
+ metrics: buildMetrics({
535
+ diskMetrics: [
536
+ buildDiskMetric({ diskPath: "/var/log", percentUsed: 75 }),
537
+ ],
538
+ }),
539
+ }),
540
+ {
541
+ checkOn: CheckOn.DiskUsagePercent,
542
+ filterType: FilterType.GreaterThan,
543
+ value: 50,
544
+ serverMonitorOptions: { diskPath: "/var/log/" },
545
+ },
546
+ );
547
+
548
+ expect(result).toContain(CheckOn.DiskUsagePercent);
549
+ expect(result).toContain("/var/log/");
550
+ });
551
+
552
+ /*
553
+ * Backslash separators and mixed case both normalize away before the
554
+ * lookup, so a Windows-style reported path matches a forward-slash
555
+ * lower-case request.
556
+ */
557
+ test("normalizes backslashes and case when matching the disk", async () => {
558
+ const result: string | null = await evaluate(
559
+ buildServerResponse({
560
+ metrics: buildMetrics({
561
+ diskMetrics: [
562
+ buildDiskMetric({ diskPath: "C:\\Data", percentUsed: 88 }),
563
+ ],
564
+ }),
565
+ }),
566
+ {
567
+ checkOn: CheckOn.DiskUsagePercent,
568
+ filterType: FilterType.GreaterThan,
569
+ value: 50,
570
+ serverMonitorOptions: { diskPath: "c:/data" },
571
+ },
572
+ );
573
+
574
+ expect(result).toContain(CheckOn.DiskUsagePercent);
575
+ });
576
+
577
+ /*
578
+ * With no serverMonitorOptions the requested path defaults to "/".
579
+ */
580
+ test("defaults to the root disk when no path option is given", async () => {
581
+ const result: string | null = await evaluate(
582
+ buildServerResponse({
583
+ metrics: buildMetrics({
584
+ diskMetrics: [buildDiskMetric({ diskPath: "/", percentUsed: 40 })],
585
+ }),
586
+ }),
587
+ {
588
+ checkOn: CheckOn.DiskUsagePercent,
589
+ filterType: FilterType.GreaterThanOrEqualTo,
590
+ value: 40,
591
+ },
592
+ );
593
+
594
+ expect(result).toContain(CheckOn.DiskUsagePercent);
595
+ });
596
+
597
+ /*
598
+ * When percentUsed is absent the evaluator falls back to percentFree.
599
+ */
600
+ test("falls back to percentFree when percentUsed is absent", async () => {
601
+ const result: string | null = await evaluate(
602
+ buildServerResponse({
603
+ metrics: buildMetrics({
604
+ diskMetrics: [
605
+ buildDiskMetric({
606
+ diskPath: "/data",
607
+ percentUsed: undefined,
608
+ percentFree: 65,
609
+ }),
610
+ ],
611
+ }),
612
+ }),
613
+ {
614
+ checkOn: CheckOn.DiskUsagePercent,
615
+ filterType: FilterType.GreaterThan,
616
+ value: 50,
617
+ serverMonitorOptions: { diskPath: "/data" },
618
+ },
619
+ );
620
+
621
+ expect(result).toContain(CheckOn.DiskUsagePercent);
622
+ });
623
+
624
+ /*
625
+ * A requested path that matches no reported disk yields a usage of 0.
626
+ */
627
+ test("unmatched disk path yields zero usage", async () => {
628
+ const result: string | null = await evaluate(
629
+ buildServerResponse({
630
+ metrics: buildMetrics({
631
+ diskMetrics: [
632
+ buildDiskMetric({ diskPath: "/other", percentUsed: 99 }),
633
+ ],
634
+ }),
635
+ }),
636
+ {
637
+ checkOn: CheckOn.DiskUsagePercent,
638
+ filterType: FilterType.LessThan,
639
+ value: 10,
640
+ serverMonitorOptions: { diskPath: "/data" },
641
+ },
642
+ );
643
+
644
+ expect(result).toContain(CheckOn.DiskUsagePercent);
645
+ });
646
+ });
647
+
648
+ describe("ServerProcessName", () => {
649
+ test("IsExecuting + process present → met", async () => {
650
+ const result: string | null = await evaluate(
651
+ buildServerResponse({
652
+ processes: [buildProcess({ name: "nginx" })],
653
+ }),
654
+ {
655
+ checkOn: CheckOn.ServerProcessName,
656
+ filterType: FilterType.IsExecuting,
657
+ value: "nginx",
658
+ },
659
+ );
660
+
661
+ expect(result).toBe("Process nginx is executing.");
662
+ });
663
+
664
+ /*
665
+ * Matching is case-insensitive and trimmed, but the original threshold
666
+ * text is echoed back in the message.
667
+ */
668
+ test("IsExecuting matches case-insensitively", async () => {
669
+ const result: string | null = await evaluate(
670
+ buildServerResponse({
671
+ processes: [buildProcess({ name: "nginx" })],
672
+ }),
673
+ {
674
+ checkOn: CheckOn.ServerProcessName,
675
+ filterType: FilterType.IsExecuting,
676
+ value: "NGINX",
677
+ },
678
+ );
679
+
680
+ expect(result).toBe("Process NGINX is executing.");
681
+ });
682
+
683
+ test("IsExecuting + process absent → not met", async () => {
684
+ const result: string | null = await evaluate(
685
+ buildServerResponse({
686
+ processes: [buildProcess({ name: "nginx" })],
687
+ }),
688
+ {
689
+ checkOn: CheckOn.ServerProcessName,
690
+ filterType: FilterType.IsExecuting,
691
+ value: "redis",
692
+ },
693
+ );
694
+
695
+ expect(result).toBeNull();
696
+ });
697
+
698
+ test("IsNotExecuting + process absent → met", async () => {
699
+ const result: string | null = await evaluate(
700
+ buildServerResponse({
701
+ processes: [buildProcess({ name: "nginx" })],
702
+ }),
703
+ {
704
+ checkOn: CheckOn.ServerProcessName,
705
+ filterType: FilterType.IsNotExecuting,
706
+ value: "redis",
707
+ },
708
+ );
709
+
710
+ expect(result).toBe("Process redis is not executing.");
711
+ });
712
+
713
+ test("IsNotExecuting + process present → not met", async () => {
714
+ const result: string | null = await evaluate(
715
+ buildServerResponse({
716
+ processes: [buildProcess({ name: "nginx" })],
717
+ }),
718
+ {
719
+ checkOn: CheckOn.ServerProcessName,
720
+ filterType: FilterType.IsNotExecuting,
721
+ value: "nginx",
722
+ },
723
+ );
724
+
725
+ expect(result).toBeNull();
726
+ });
727
+
728
+ /*
729
+ * An absent processes array is treated as an empty list, so nothing is
730
+ * executing and IsNotExecuting is satisfied.
731
+ */
732
+ test("absent processes list satisfies IsNotExecuting", async () => {
733
+ const result: string | null = await evaluate(buildServerResponse({}), {
734
+ checkOn: CheckOn.ServerProcessName,
735
+ filterType: FilterType.IsNotExecuting,
736
+ value: "nginx",
737
+ });
738
+
739
+ expect(result).toBe("Process nginx is not executing.");
740
+ });
741
+
742
+ /*
743
+ * A falsy threshold (undefined value) skips the whole process block via
744
+ * the `threshold &&` guard, leaving the check undecidable.
745
+ */
746
+ test("undefined threshold skips the process block", async () => {
747
+ const result: string | null = await evaluate(
748
+ buildServerResponse({
749
+ processes: [buildProcess({ name: "nginx" })],
750
+ }),
751
+ {
752
+ checkOn: CheckOn.ServerProcessName,
753
+ filterType: FilterType.IsExecuting,
754
+ value: undefined,
755
+ },
756
+ );
757
+
758
+ expect(result).toBeNull();
759
+ });
760
+
761
+ /*
762
+ * A filter type that is neither executing nor not-executing falls through
763
+ * the process block without a decision.
764
+ */
765
+ test("unhandled filter type → undecidable", async () => {
766
+ const result: string | null = await evaluate(
767
+ buildServerResponse({
768
+ processes: [buildProcess({ name: "nginx" })],
769
+ }),
770
+ {
771
+ checkOn: CheckOn.ServerProcessName,
772
+ filterType: FilterType.EqualTo,
773
+ value: "nginx",
774
+ },
775
+ );
776
+
777
+ expect(result).toBeNull();
778
+ });
779
+
780
+ test("onlyCheckRequestReceivedAt short-circuits the process block", async () => {
781
+ const result: string | null = await evaluate(
782
+ buildServerResponse({
783
+ processes: [buildProcess({ name: "nginx" })],
784
+ onlyCheckRequestReceivedAt: true,
785
+ }),
786
+ {
787
+ checkOn: CheckOn.ServerProcessName,
788
+ filterType: FilterType.IsExecuting,
789
+ value: "nginx",
790
+ },
791
+ );
792
+
793
+ expect(result).toBeNull();
794
+ });
795
+ });
796
+
797
+ describe("ServerProcessPID", () => {
798
+ test("IsExecuting matches a numeric PID threshold", async () => {
799
+ const result: string | null = await evaluate(
800
+ buildServerResponse({
801
+ processes: [buildProcess({ pid: 4321 })],
802
+ }),
803
+ {
804
+ checkOn: CheckOn.ServerProcessPID,
805
+ filterType: FilterType.IsExecuting,
806
+ value: 4321,
807
+ },
808
+ );
809
+
810
+ expect(result).toBe("Process with PID 4321 is executing.");
811
+ });
812
+
813
+ test("IsNotExecuting + PID absent → met", async () => {
814
+ const result: string | null = await evaluate(
815
+ buildServerResponse({
816
+ processes: [buildProcess({ pid: 4321 })],
817
+ }),
818
+ {
819
+ checkOn: CheckOn.ServerProcessPID,
820
+ filterType: FilterType.IsNotExecuting,
821
+ value: "9999",
822
+ },
823
+ );
824
+
825
+ expect(result).toBe("Process with PID 9999 is not executing.");
826
+ });
827
+
828
+ /*
829
+ * The PID block has an explicit trailing null return, so an unhandled
830
+ * filter type resolves to null without falling through to later blocks.
831
+ */
832
+ test("unhandled filter type → undecidable", async () => {
833
+ const result: string | null = await evaluate(
834
+ buildServerResponse({
835
+ processes: [buildProcess({ pid: 4321 })],
836
+ }),
837
+ {
838
+ checkOn: CheckOn.ServerProcessPID,
839
+ filterType: FilterType.EqualTo,
840
+ value: 4321,
841
+ },
842
+ );
843
+
844
+ expect(result).toBeNull();
845
+ });
846
+ });
847
+
848
+ describe("ServerProcessCommand", () => {
849
+ test("IsExecuting matches an exact command", async () => {
850
+ const result: string | null = await evaluate(
851
+ buildServerResponse({
852
+ processes: [buildProcess({ command: "/usr/bin/node server.js" })],
853
+ }),
854
+ {
855
+ checkOn: CheckOn.ServerProcessCommand,
856
+ filterType: FilterType.IsExecuting,
857
+ value: "/usr/bin/node server.js",
858
+ },
859
+ );
860
+
861
+ expect(result).toBe(
862
+ "Process with command /usr/bin/node server.js is executing.",
863
+ );
864
+ });
865
+
866
+ test("IsExecuting matches after trimming and lower-casing", async () => {
867
+ const result: string | null = await evaluate(
868
+ buildServerResponse({
869
+ processes: [buildProcess({ command: "/usr/bin/node server.js" })],
870
+ }),
871
+ {
872
+ checkOn: CheckOn.ServerProcessCommand,
873
+ filterType: FilterType.IsExecuting,
874
+ value: " /USR/bin/Node server.js ",
875
+ },
876
+ );
877
+
878
+ expect(result).toContain("is executing.");
879
+ });
880
+
881
+ test("IsNotExecuting + command absent → met", async () => {
882
+ const result: string | null = await evaluate(
883
+ buildServerResponse({
884
+ processes: [buildProcess({ command: "/usr/bin/node server.js" })],
885
+ }),
886
+ {
887
+ checkOn: CheckOn.ServerProcessCommand,
888
+ filterType: FilterType.IsNotExecuting,
889
+ value: "/bin/bash",
890
+ },
891
+ );
892
+
893
+ expect(result).toBe("Process with command /bin/bash is not executing.");
894
+ });
895
+ });
896
+
897
+ /*
898
+ * The evaluate-over-time path replaces the current metric value with the
899
+ * window recorded for the monitor. The DB-backed lookup is spied so these
900
+ * tests stay deterministic.
901
+ */
902
+ describe("evaluate over time", () => {
903
+ /** The window produced a usable value. */
904
+ function usable(
905
+ value: Array<number | boolean> | number | boolean,
906
+ ): OverTimeCriteriaValue {
907
+ return { earlyReturn: null, value: value };
908
+ }
909
+
910
+ /** The window could not back the filter, so nothing is compared. */
911
+ function noUsableWindow(): OverTimeCriteriaValue {
912
+ return { earlyReturn: { result: null }, value: undefined };
913
+ }
914
+
915
+ function mockOverTime(
916
+ result: OverTimeCriteriaValue,
917
+ ): ReturnType<typeof jest.spyOn> {
918
+ return jest
919
+ .spyOn(EvaluateOverTime, "getOverTimeValueForCriteriaFilter")
920
+ .mockResolvedValue(result) as ReturnType<typeof jest.spyOn>;
921
+ }
922
+
923
+ test("uses the over-time boolean series for IsOnline while online", async () => {
924
+ const spy: ReturnType<typeof jest.spyOn> = mockOverTime(
925
+ usable([true, false]),
926
+ );
927
+
928
+ const response: ServerMonitorResponse = buildServerResponse({
929
+ minutesSinceLastCheck: 5,
930
+ });
931
+
932
+ const result: string | null = await evaluate(response, {
933
+ checkOn: CheckOn.IsOnline,
934
+ filterType: FilterType.True,
935
+ value: undefined,
936
+ evaluateOverTime: true,
937
+ evaluateOverTimeOptions: {
938
+ timeValueInMinutes: 10,
939
+ evaluateOverTimeType: EvaluateOverTimeType.AnyValue,
940
+ },
941
+ });
942
+
943
+ expect(result).toContain(CheckOn.IsOnline);
944
+ expect(spy).toHaveBeenCalledWith(
945
+ expect.objectContaining({
946
+ projectId: response.projectId,
947
+ monitorId: response.monitorId,
948
+ criteriaFilter: expect.objectContaining({
949
+ checkOn: CheckOn.IsOnline,
950
+ }),
951
+ }),
952
+ );
953
+ });
954
+
955
+ /*
956
+ * timeValueInMinutes overrides the default offline threshold: a 5 minute
957
+ * gap is still "online" when the window is 10 minutes, which would have
958
+ * been offline under the default of 3.
959
+ */
960
+ test("timeValueInMinutes overrides the offline threshold", async () => {
961
+ mockOverTime(usable([false, false]));
962
+
963
+ const result: string | null = await evaluate(
964
+ buildServerResponse({ minutesSinceLastCheck: 5 }),
965
+ {
966
+ checkOn: CheckOn.IsOnline,
967
+ filterType: FilterType.False,
968
+ value: undefined,
969
+ evaluateOverTime: true,
970
+ evaluateOverTimeOptions: {
971
+ timeValueInMinutes: 3,
972
+ evaluateOverTimeType: EvaluateOverTimeType.AllValues,
973
+ },
974
+ },
975
+ );
976
+
977
+ expect(result).toContain("false");
978
+ });
979
+
980
+ /*
981
+ * "Is Online" is the one filter that keeps its fallback: for a server
982
+ * monitor the absence of data IS the signal, and the last-check-in
983
+ * arithmetic above already implements the "wait this long" behaviour. So
984
+ * an unusable window still falls back to the "recent check -> online"
985
+ * default rather than declining to evaluate.
986
+ */
987
+ test("empty over-time series falls back to the liveness default", async () => {
988
+ mockOverTime(noUsableWindow());
989
+
990
+ const result: string | null = await evaluate(
991
+ buildServerResponse({ minutesSinceLastCheck: 1 }),
992
+ {
993
+ checkOn: CheckOn.IsOnline,
994
+ filterType: FilterType.True,
995
+ value: undefined,
996
+ evaluateOverTime: true,
997
+ evaluateOverTimeOptions: {
998
+ timeValueInMinutes: 3,
999
+ evaluateOverTimeType: EvaluateOverTimeType.AllValues,
1000
+ },
1001
+ },
1002
+ );
1003
+
1004
+ expect(result).toContain("true");
1005
+ });
1006
+
1007
+ /*
1008
+ * A numeric over-time series takes precedence over the point-in-time CPU
1009
+ * metric. The array (70, 80) breaches while the live value (10) would not.
1010
+ */
1011
+ test("over-time numeric series takes precedence over the live CPU metric", async () => {
1012
+ mockOverTime(usable([70, 80]));
1013
+
1014
+ const result: string | null = await evaluate(
1015
+ buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 10 }) }),
1016
+ {
1017
+ checkOn: CheckOn.CPUUsagePercent,
1018
+ filterType: FilterType.GreaterThan,
1019
+ value: 50,
1020
+ evaluateOverTime: true,
1021
+ evaluateOverTimeOptions: {
1022
+ timeValueInMinutes: 5,
1023
+ evaluateOverTimeType: EvaluateOverTimeType.AllValues,
1024
+ },
1025
+ },
1026
+ );
1027
+
1028
+ expect(result).toContain(CheckOn.CPUUsagePercent);
1029
+ expect(result).toContain("70");
1030
+ });
1031
+
1032
+ /*
1033
+ * Only the disk-usage series carries a diskPath attribute. Scoping any
1034
+ * other series by it would filter against an attribute no row has, and
1035
+ * an unusable window now means the filter waits rather than comparing
1036
+ * the live value - so the stray option would silence it outright.
1037
+ */
1038
+ test("scopes the window by disk path only for disk usage", async () => {
1039
+ const spy: ReturnType<typeof jest.spyOn> = mockOverTime(usable([95]));
1040
+
1041
+ await evaluate(
1042
+ buildServerResponse({
1043
+ metrics: buildMetrics({
1044
+ diskMetrics: [
1045
+ buildDiskMetric({ diskPath: "/data", percentUsed: 95 }),
1046
+ ],
1047
+ }),
1048
+ }),
1049
+ {
1050
+ checkOn: CheckOn.DiskUsagePercent,
1051
+ filterType: FilterType.GreaterThan,
1052
+ value: 90,
1053
+ evaluateOverTime: true,
1054
+ evaluateOverTimeOptions: {
1055
+ timeValueInMinutes: 5,
1056
+ evaluateOverTimeType: EvaluateOverTimeType.AllValues,
1057
+ },
1058
+ serverMonitorOptions: { diskPath: "/data" },
1059
+ },
1060
+ );
1061
+
1062
+ expect(spy).toHaveBeenCalledWith(
1063
+ expect.objectContaining({ miscData: { diskPath: "/data" } }),
1064
+ );
1065
+ });
1066
+
1067
+ test("does not scope a CPU window by a stray disk path", async () => {
1068
+ const spy: ReturnType<typeof jest.spyOn> = mockOverTime(usable([70, 80]));
1069
+
1070
+ await evaluate(
1071
+ buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 75 }) }),
1072
+ {
1073
+ checkOn: CheckOn.CPUUsagePercent,
1074
+ filterType: FilterType.GreaterThan,
1075
+ value: 50,
1076
+ evaluateOverTime: true,
1077
+ evaluateOverTimeOptions: {
1078
+ timeValueInMinutes: 5,
1079
+ evaluateOverTimeType: EvaluateOverTimeType.AllValues,
1080
+ },
1081
+ serverMonitorOptions: { diskPath: "/" },
1082
+ },
1083
+ );
1084
+
1085
+ expect(spy).toHaveBeenCalledWith(
1086
+ expect.objectContaining({ miscData: undefined }),
1087
+ );
1088
+ });
1089
+
1090
+ /*
1091
+ * Disk usage read its over-time window and then threw the result away,
1092
+ * comparing the reading from this check instead - so "evaluate over
1093
+ * time" on a disk filter did nothing at all.
1094
+ */
1095
+ test("disk usage compares the over-time window, not just this check", async () => {
1096
+ mockOverTime(usable([95, 96, 97]));
1097
+
1098
+ const result: string | null = await evaluate(
1099
+ buildServerResponse({
1100
+ metrics: buildMetrics({
1101
+ diskMetrics: [buildDiskMetric({ diskPath: "/", percentUsed: 10 })],
1102
+ }),
1103
+ }),
1104
+ {
1105
+ checkOn: CheckOn.DiskUsagePercent,
1106
+ filterType: FilterType.GreaterThan,
1107
+ value: 90,
1108
+ evaluateOverTime: true,
1109
+ evaluateOverTimeOptions: {
1110
+ timeValueInMinutes: 5,
1111
+ evaluateOverTimeType: EvaluateOverTimeType.AllValues,
1112
+ },
1113
+ serverMonitorOptions: { diskPath: "/" },
1114
+ },
1115
+ );
1116
+
1117
+ expect(result).toContain("All values of");
1118
+ expect(result).toContain("95");
1119
+ });
1120
+
1121
+ test("disk usage does not fire while its window is unusable", async () => {
1122
+ mockOverTime(noUsableWindow());
1123
+
1124
+ const result: string | null = await evaluate(
1125
+ buildServerResponse({
1126
+ metrics: buildMetrics({
1127
+ diskMetrics: [buildDiskMetric({ diskPath: "/", percentUsed: 99 })],
1128
+ }),
1129
+ }),
1130
+ {
1131
+ checkOn: CheckOn.DiskUsagePercent,
1132
+ filterType: FilterType.GreaterThan,
1133
+ value: 90,
1134
+ evaluateOverTime: true,
1135
+ evaluateOverTimeOptions: {
1136
+ timeValueInMinutes: 5,
1137
+ evaluateOverTimeType: EvaluateOverTimeType.AllValues,
1138
+ },
1139
+ serverMonitorOptions: { diskPath: "/" },
1140
+ },
1141
+ );
1142
+
1143
+ expect(result).toBeNull();
1144
+ });
1145
+
1146
+ /*
1147
+ * A disk filter that does NOT evaluate over time keeps comparing the
1148
+ * reading from this check.
1149
+ */
1150
+ test("disk usage without over-time still compares this check", async () => {
1151
+ const result: string | null = await evaluate(
1152
+ buildServerResponse({
1153
+ metrics: buildMetrics({
1154
+ diskMetrics: [buildDiskMetric({ diskPath: "/", percentUsed: 99 })],
1155
+ }),
1156
+ }),
1157
+ {
1158
+ checkOn: CheckOn.DiskUsagePercent,
1159
+ filterType: FilterType.GreaterThan,
1160
+ value: 90,
1161
+ serverMonitorOptions: { diskPath: "/" },
1162
+ },
1163
+ );
1164
+
1165
+ expect(result).toContain("99");
1166
+ });
1167
+
1168
+ /*
1169
+ * An average of exactly zero is a real measurement, not a missing one.
1170
+ * It used to be swallowed by a truthiness check and replaced with the
1171
+ * live CPU reading, so "average CPU over 5 minutes above 50%" could fire
1172
+ * on a single busy sample while the average itself was 0.
1173
+ */
1174
+ test("a zero aggregate is compared as zero, not replaced by the live metric", async () => {
1175
+ mockOverTime(usable(0));
1176
+
1177
+ const result: string | null = await evaluate(
1178
+ buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 90 }) }),
1179
+ {
1180
+ checkOn: CheckOn.CPUUsagePercent,
1181
+ filterType: FilterType.GreaterThan,
1182
+ value: 50,
1183
+ evaluateOverTime: true,
1184
+ evaluateOverTimeOptions: {
1185
+ timeValueInMinutes: 5,
1186
+ evaluateOverTimeType: EvaluateOverTimeType.Average,
1187
+ },
1188
+ },
1189
+ );
1190
+
1191
+ expect(result).toBeNull();
1192
+ });
1193
+
1194
+ /*
1195
+ * A window that could not be read says nothing about the last five
1196
+ * minutes, so the filter waits rather than firing off the single live
1197
+ * reading that happens to have arrived with this check.
1198
+ */
1199
+ test("an unreadable window does not fire off the live CPU metric", async () => {
1200
+ mockOverTime(noUsableWindow());
1201
+
1202
+ const result: string | null = await evaluate(
1203
+ buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 90 }) }),
1204
+ {
1205
+ checkOn: CheckOn.CPUUsagePercent,
1206
+ filterType: FilterType.GreaterThan,
1207
+ value: 50,
1208
+ evaluateOverTime: true,
1209
+ evaluateOverTimeOptions: {
1210
+ timeValueInMinutes: 5,
1211
+ evaluateOverTimeType: EvaluateOverTimeType.Average,
1212
+ },
1213
+ },
1214
+ );
1215
+
1216
+ expect(result).toBeNull();
1217
+ });
1218
+ });
1219
+ });