@oneuptime/common 12.0.13 → 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 (376) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
  2. package/Models/DatabaseModels/UserCall.ts +94 -3
  3. package/Models/DatabaseModels/UserEmail.ts +94 -3
  4. package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
  5. package/Models/DatabaseModels/UserPush.ts +37 -0
  6. package/Models/DatabaseModels/UserSMS.ts +94 -3
  7. package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
  8. package/Server/API/BaseAPI.ts +79 -14
  9. package/Server/API/UserCallAPI.ts +53 -45
  10. package/Server/API/UserEmailAPI.ts +53 -44
  11. package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
  12. package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
  13. package/Server/API/UserPushAPI.ts +126 -2
  14. package/Server/API/UserSmsAPI.ts +53 -44
  15. package/Server/API/UserWhatsAppAPI.ts +53 -50
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  20. package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
  21. package/Server/Services/AnalyticsDatabaseService.ts +169 -0
  22. package/Server/Services/DatabaseService.ts +101 -0
  23. package/Server/Services/LogAggregationService.ts +5 -0
  24. package/Server/Services/PushNotificationService.ts +127 -12
  25. package/Server/Services/TeamMemberService.ts +53 -13
  26. package/Server/Services/UserCallService.ts +55 -24
  27. package/Server/Services/UserEmailService.ts +83 -17
  28. package/Server/Services/UserIncomingCallNumberService.ts +49 -85
  29. package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
  30. package/Server/Services/UserNotificationRuleService.ts +26 -0
  31. package/Server/Services/UserPushService.ts +89 -0
  32. package/Server/Services/UserSmsService.ts +50 -17
  33. package/Server/Services/UserWhatsAppService.ts +48 -15
  34. package/Server/Types/Database/QueryHelper.ts +30 -0
  35. package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
  36. package/Server/Utils/ChannelVerification.ts +510 -0
  37. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
  38. package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
  39. package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
  40. package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
  41. package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
  42. package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
  43. package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
  44. package/Server/Utils/TotpAuth.ts +137 -9
  45. package/Server/Utils/UserRegistrationToken.ts +182 -0
  46. package/Server/Utils/VerificationCode.ts +134 -0
  47. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
  48. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
  49. package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
  50. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
  51. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
  52. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
  53. package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
  54. package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
  55. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
  56. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
  57. package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
  58. package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
  59. package/Tests/Server/API/UserSmsApi.test.ts +107 -14
  60. package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
  61. package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +315 -0
  62. package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
  63. package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
  64. package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
  65. package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
  66. package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
  67. package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
  68. package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
  69. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
  70. package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
  71. package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
  72. package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
  73. package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
  74. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
  75. package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
  76. package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
  77. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
  78. package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
  79. package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
  80. package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
  81. package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
  82. package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
  83. package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
  84. package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
  85. package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
  86. package/Tests/Server/Utils/Browser.test.ts +162 -0
  87. package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
  88. package/Tests/Server/Utils/Express.test.ts +371 -0
  89. package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
  90. package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
  91. package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
  92. package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
  93. package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
  94. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
  95. package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
  96. package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
  97. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
  98. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
  99. package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
  100. package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
  101. package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
  102. package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
  103. package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
  104. package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
  105. package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
  106. package/Tests/Types/Call/CallRequest.test.ts +189 -0
  107. package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
  108. package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
  109. package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
  110. package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
  111. package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
  112. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
  113. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
  114. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
  115. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
  116. package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
  117. package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
  118. package/Tests/Types/TextRandomGeneration.test.ts +211 -0
  119. package/Tests/UI/Components/Button.test.tsx +175 -1
  120. package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
  121. package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
  122. package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
  123. package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
  124. package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
  125. package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
  126. package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
  127. package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
  128. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
  129. package/Tests/UI/Components/List.test.tsx +9 -2
  130. package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
  131. package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
  132. package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
  133. package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
  134. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
  135. package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
  136. package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
  137. package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
  138. package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
  139. package/Tests/UI/Components/Skeleton.test.tsx +71 -0
  140. package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
  141. package/Tests/UI/Components/Tabs.test.tsx +24 -0
  142. package/Tests/UI/Components/Toast.test.tsx +130 -7
  143. package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
  144. package/Tests/UI/Utils/Dropdown.test.ts +423 -0
  145. package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
  146. package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
  147. package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
  148. package/Tests/Utils/API.test.ts +16 -2
  149. package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
  150. package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
  151. package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
  152. package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
  153. package/Types/Email/EmailTemplateType.ts +1 -0
  154. package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
  155. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
  156. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
  157. package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
  158. package/Types/Permission.ts +35 -0
  159. package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
  160. package/Types/PushNotification/PushNotificationMessage.ts +15 -0
  161. package/Types/PushNotification/PushNotificationRequest.ts +8 -16
  162. package/Types/Service/ServiceLanguage.ts +144 -0
  163. package/Types/Text.ts +111 -19
  164. package/UI/Components/Button/Button.tsx +27 -14
  165. package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
  166. package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
  167. package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
  168. package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
  169. package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
  170. package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
  171. package/UI/Components/CommandPalette/Types.ts +49 -0
  172. package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
  173. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  174. package/UI/Components/Feed/FeedItem.tsx +1 -1
  175. package/UI/Components/List/List.tsx +37 -5
  176. package/UI/Components/List/ListSkeleton.tsx +54 -0
  177. package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
  178. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
  179. package/UI/Components/Modal/Modal.tsx +2 -2
  180. package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
  181. package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
  182. package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
  183. package/UI/Components/Navbar/NavBar.tsx +14 -1
  184. package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
  185. package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
  186. package/UI/Components/SideOver/SideOver.tsx +37 -2
  187. package/UI/Components/Skeleton/Skeleton.tsx +53 -0
  188. package/UI/Components/Table/Table.tsx +74 -44
  189. package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
  190. package/UI/Components/Tabs/Tab.tsx +1 -1
  191. package/UI/Components/Toast/Toast.tsx +118 -53
  192. package/UI/Components/Toast/ToastInit.tsx +82 -32
  193. package/UI/Styles/Theme.css +40 -0
  194. package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
  195. package/UI/Utils/ModelListCache.ts +188 -0
  196. package/UI/Utils/Project.ts +29 -0
  197. package/Utils/API.ts +6 -1
  198. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
  199. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  200. package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
  201. package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
  202. package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
  203. package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
  205. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
  206. package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
  207. package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
  208. package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
  209. package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
  211. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
  212. package/build/dist/Server/API/BaseAPI.js +69 -13
  213. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  214. package/build/dist/Server/API/UserCallAPI.js +42 -38
  215. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  216. package/build/dist/Server/API/UserEmailAPI.js +42 -38
  217. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  218. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
  219. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  220. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
  221. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
  222. package/build/dist/Server/API/UserPushAPI.js +95 -2
  223. package/build/dist/Server/API/UserPushAPI.js.map +1 -1
  224. package/build/dist/Server/API/UserSmsAPI.js +42 -38
  225. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  226. package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
  227. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  228. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
  229. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
  230. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
  231. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
  232. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
  233. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
  234. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  235. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  236. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
  237. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
  238. package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
  239. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  240. package/build/dist/Server/Services/DatabaseService.js +74 -0
  241. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  242. package/build/dist/Server/Services/LogAggregationService.js +5 -0
  243. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  244. package/build/dist/Server/Services/PushNotificationService.js +69 -30
  245. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  246. package/build/dist/Server/Services/TeamMemberService.js +43 -7
  247. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  248. package/build/dist/Server/Services/UserCallService.js +54 -22
  249. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  250. package/build/dist/Server/Services/UserEmailService.js +78 -17
  251. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  252. package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
  253. package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
  254. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
  255. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
  256. package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
  257. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  258. package/build/dist/Server/Services/UserPushService.js +77 -0
  259. package/build/dist/Server/Services/UserPushService.js.map +1 -1
  260. package/build/dist/Server/Services/UserSmsService.js +50 -17
  261. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  262. package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
  263. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
  264. package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
  265. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  266. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
  267. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
  268. package/build/dist/Server/Utils/ChannelVerification.js +348 -0
  269. package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
  270. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
  271. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
  272. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
  273. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  274. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
  275. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  276. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
  277. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
  278. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
  279. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
  280. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
  281. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
  282. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
  283. package/build/dist/Server/Utils/TotpAuth.js +127 -8
  284. package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
  285. package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
  286. package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
  287. package/build/dist/Server/Utils/VerificationCode.js +120 -0
  288. package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
  289. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  290. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  291. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
  292. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  293. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
  294. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  295. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
  296. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  297. package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
  298. package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
  299. package/build/dist/Types/Permission.js +33 -0
  300. package/build/dist/Types/Permission.js.map +1 -1
  301. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
  302. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
  303. package/build/dist/Types/Service/ServiceLanguage.js +96 -0
  304. package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
  305. package/build/dist/Types/Text.js +82 -17
  306. package/build/dist/Types/Text.js.map +1 -1
  307. package/build/dist/UI/Components/Button/Button.js +22 -14
  308. package/build/dist/UI/Components/Button/Button.js.map +1 -1
  309. package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
  310. package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
  311. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
  312. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
  313. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
  314. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
  315. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
  316. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
  317. package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
  318. package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
  319. package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
  320. package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
  321. package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
  322. package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
  323. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
  324. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
  325. package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
  326. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  327. package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
  328. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  329. package/build/dist/UI/Components/List/List.js +19 -5
  330. package/build/dist/UI/Components/List/List.js.map +1 -1
  331. package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
  332. package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
  333. package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
  334. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
  335. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  336. package/build/dist/UI/Components/Modal/Modal.js +2 -2
  337. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
  338. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  339. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
  340. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
  341. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
  342. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  343. package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
  344. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  345. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
  346. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
  347. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
  348. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
  349. package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
  350. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  351. package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
  352. package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
  353. package/build/dist/UI/Components/Table/Table.js +35 -24
  354. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  355. package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
  356. package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
  357. package/build/dist/UI/Components/Tabs/Tab.js +1 -1
  358. package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
  359. package/build/dist/UI/Components/Toast/Toast.js +77 -23
  360. package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
  361. package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
  362. package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
  363. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
  364. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  365. package/build/dist/UI/Utils/ModelListCache.js +126 -0
  366. package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
  367. package/build/dist/UI/Utils/Project.js +24 -1
  368. package/build/dist/UI/Utils/Project.js.map +1 -1
  369. package/build/dist/Utils/API.js +6 -1
  370. package/build/dist/Utils/API.js.map +1 -1
  371. package/jest.config.json +1 -1
  372. package/package.json +2 -3
  373. package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
  374. package/Tests/__mocks__/otpauth.js +0 -30
  375. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
  376. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
@@ -37,10 +37,10 @@ import MonitorSummarySnapshot from "../../../Types/Monitor/MonitorSummarySnapsho
37
37
  import MonitorSummarySnapshotUtil from "../../../Utils/Monitor/MonitorSummarySnapshotUtil";
38
38
  import { IncidentMemberRoleAssignment } from "../../../Types/Monitor/CriteriaIncident";
39
39
  import { PerSeriesCriteriaMatch } from "../../../Types/Probe/ProbeApiIngestResponse";
40
- import MonitorClusterContextUtil, {
41
- MonitorClusterContext,
42
- } from "./MonitorClusterContext";
43
- import SeriesResourceLinker from "./SeriesResourceLinker";
40
+ import MonitorResourceContextUtil from "./MonitorResourceContext";
41
+ import SeriesResourceLinker, {
42
+ SeriesResolvedResourceIds,
43
+ } from "./SeriesResourceLinker";
44
44
 
45
45
  export default class MonitorIncident {
46
46
  @CaptureSpan()
@@ -364,15 +364,17 @@ export default class MonitorIncident {
364
364
  }
365
365
 
366
366
  /*
367
- * Proxmox/Ceph monitors: resolve the monitored cluster once per
368
- * evaluation (lookup-only, from the step config's clusterIdentifier)
369
- * so every incident created below is attached to it. Series labels
370
- * cannot supply this they carry datapoint labels (`id`,
371
- * `ceph_daemon`, `pool_id`), not cluster identity, and ungrouped
372
- * templates have no series at all. No-op for other monitor types.
367
+ * Resolve the resources this monitor's own config names — its host,
368
+ * cluster, fleet, telemetry services, or the resource its metric
369
+ * filters scope it to once per evaluation, so every incident
370
+ * created below is attached to them. Series labels cannot supply
371
+ * this: they only exist for grouped criteria, and most monitors
372
+ * (every shipped Host/Docker/Podman template, all Logs/Traces/
373
+ * Exceptions monitors) are ungrouped. No-op, and no round-trip, for
374
+ * monitor types whose config names no resource.
373
375
  */
374
- const clusterContext: MonitorClusterContext =
375
- await MonitorClusterContextUtil.resolveClusterContextForMonitor({
376
+ const resourceContext: SeriesResolvedResourceIds =
377
+ await MonitorResourceContextUtil.resolveResourceContextForMonitor({
376
378
  monitor: input.monitor,
377
379
  });
378
380
 
@@ -656,19 +658,20 @@ export default class MonitorIncident {
656
658
  model: incident,
657
659
  seriesLabels,
658
660
  projectId: input.monitor.projectId!,
661
+ monitorType: input.monitor.monitorType,
659
662
  });
660
663
  }
661
664
 
662
665
  /*
663
- * Deterministic Proxmox/Ceph cluster link from the monitor's
664
- * step config (resolved once above). Runs for both grouped and
665
- * ungrouped incidents and merges with anything the series-label
666
- * path resolved, so the per-cluster Activity tabs always see
666
+ * Deterministic resource link from the monitor's step config
667
+ * (resolved once above). Runs for both grouped and ungrouped
668
+ * incidents and merges with anything the series-label path
669
+ * resolved, so the per-resource Activity tabs always see
667
670
  * monitor-created incidents.
668
671
  */
669
- SeriesResourceLinker.attachClusterContext({
672
+ SeriesResourceLinker.attachResolvedResources({
670
673
  model: incident,
671
- clusterContext,
674
+ resolved: resourceContext,
672
675
  });
673
676
 
674
677
  incident.onCallDutyPolicies =
@@ -0,0 +1,107 @@
1
+ import Monitor from "../../../Models/DatabaseModels/Monitor";
2
+ import logger from "../Logger";
3
+ import MonitorStepResourceIdentity from "./MonitorStepResourceIdentity";
4
+ import { SeriesResourceRefs } from "./SeriesResourceLabels";
5
+ import SeriesResourceLinker, {
6
+ SeriesResolvedResourceIds,
7
+ } from "./SeriesResourceLinker";
8
+
9
+ /*
10
+ * Incidents and alerts created by a monitor must be attached to the
11
+ * resources that monitor watches — the per-resource Activity pages, the
12
+ * SideMenu badge counts, the "Affected Resources" card, the affected-
13
+ * resources filter, and resource owner/label inheritance all query those
14
+ * relations on Incident/Alert.
15
+ *
16
+ * Series labels cannot supply that identity on their own. They exist
17
+ * only when the criteria is GROUPED, and most monitors are not: every
18
+ * shipped Host / Docker / Podman / RUM template is ungrouped, the
19
+ * Kubernetes templates group by node/pod (never by cluster), and
20
+ * Logs / Traces / Exceptions monitors have no series concept at all. An
21
+ * ungrouped monitor therefore linked nothing, which is why a metric
22
+ * monitor scoped to one service with
23
+ * `oneuptime.service.name = checkout-api` opened alerts that showed "No
24
+ * resources affected".
25
+ *
26
+ * The deterministic source is the monitor's own step config, which
27
+ * always carries whatever the user picked when they built the monitor:
28
+ * a hostIdentifier, a clusterIdentifier, a fleetIdentifier, a set of
29
+ * telemetryServiceIds, or a metric attribute filter. This module reads
30
+ * it once per evaluation and resolves it to real rows.
31
+ *
32
+ * This supersedes the old MonitorClusterContext, which did the same
33
+ * thing for exactly four cluster types (Proxmox / Ceph / Docker Swarm /
34
+ * IoT) with a hand-rolled findOneBy per identifier.
35
+ */
36
+ export default class MonitorResourceContextUtil {
37
+ /*
38
+ * Resolve the resource rows the monitor's configuration names.
39
+ *
40
+ * Lookup-only — row creation belongs to ingest discovery
41
+ * (findOrCreateByName); a monitor pointing at a host that never sent
42
+ * data simply links nothing. Lookups are ALWAYS project-scoped:
43
+ * `isRoot` bypasses row-level access control, so a stale or hostile
44
+ * identifier must never be able to pull a row in from another tenant.
45
+ *
46
+ * Returns empty for every monitor type whose config names no resource
47
+ * (Website, API, Ping, Synthetic, ...) without touching the database.
48
+ */
49
+ public static async resolveResourceContextForMonitor(input: {
50
+ monitor: Monitor;
51
+ }): Promise<SeriesResolvedResourceIds> {
52
+ const empty: SeriesResolvedResourceIds = this.emptyContext();
53
+
54
+ if (!input.monitor.projectId) {
55
+ return empty;
56
+ }
57
+
58
+ /*
59
+ * Resource linking is best-effort context — a failure must never
60
+ * block incident/alert creation, which runs inside the probe and
61
+ * telemetry queue workers where a throw retries the whole job
62
+ * forever. The EXTRACTION is inside the try as well as the lookup:
63
+ * it reads free-form, unvalidated step JSON, so a monitor saved
64
+ * through the API or an import can hand it a shape it cannot parse.
65
+ */
66
+ try {
67
+ const refs: SeriesResourceRefs =
68
+ MonitorStepResourceIdentity.extractResourceRefsFromMonitor({
69
+ monitor: input.monitor,
70
+ });
71
+
72
+ if (MonitorStepResourceIdentity.isEmpty(refs)) {
73
+ return empty;
74
+ }
75
+
76
+ return await SeriesResourceLinker.resolveResourceRefs({
77
+ refs: refs,
78
+ projectId: input.monitor.projectId,
79
+ /*
80
+ * The identifiers here were typed by a user into the monitor
81
+ * form, while the rows' names were stamped by an agent at
82
+ * ingest; the two legitimately differ by case.
83
+ */
84
+ nameMatch: "caseInsensitive",
85
+ });
86
+ } catch (err) {
87
+ logger.error(
88
+ `Failed to resolve affected resources for monitor ${input.monitor.id?.toString()}: ${err}`,
89
+ );
90
+ return empty;
91
+ }
92
+ }
93
+
94
+ public static emptyContext(): SeriesResolvedResourceIds {
95
+ return {
96
+ hostIds: [],
97
+ dockerHostIds: [],
98
+ podmanHostIds: [],
99
+ kubernetesClusterIds: [],
100
+ serviceIds: [],
101
+ proxmoxClusterIds: [],
102
+ cephClusterIds: [],
103
+ dockerSwarmClusterIds: [],
104
+ iotFleetIds: [],
105
+ };
106
+ }
107
+ }
@@ -0,0 +1,442 @@
1
+ import Monitor from "../../../Models/DatabaseModels/Monitor";
2
+ import { JSONObject } from "../../../Types/JSON";
3
+ import MetricQueryConfigData from "../../../Types/Metrics/MetricQueryConfigData";
4
+ import MetricsViewConfig from "../../../Types/Metrics/MetricsViewConfig";
5
+ import MonitorStep from "../../../Types/Monitor/MonitorStep";
6
+ import MonitorType from "../../../Types/Monitor/MonitorType";
7
+ import ObjectID from "../../../Types/ObjectID";
8
+ import SeriesResourceLabels, {
9
+ SeriesResourceRefs,
10
+ } from "./SeriesResourceLabels";
11
+
12
+ /*
13
+ * The step-config twin of SeriesResourceLabels.
14
+ *
15
+ * SeriesResourceLabels answers "which resources does this BREACHING
16
+ * SERIES point at" by reading the labels of one grouped series. That
17
+ * only works when the criteria is grouped — an ungrouped monitor emits
18
+ * no series labels at all, so it linked nothing, and the vast majority
19
+ * of monitors (every shipped Host / Docker / Podman / RUM template, and
20
+ * every Logs / Traces / Exceptions monitor, which cannot be grouped in
21
+ * the first place) are ungrouped.
22
+ *
23
+ * This module answers the same question from the other, always-present
24
+ * side: "which resources does this MONITOR'S OWN CONFIGURATION point
25
+ * at". A host monitor names its host, a Kubernetes monitor names its
26
+ * cluster, a log monitor names its telemetry services, and any monitor
27
+ * with a metric query can carry resource identity in its attribute
28
+ * filters (e.g. `oneuptime.service.name = checkout-api`). None of that
29
+ * depends on the criteria being grouped.
30
+ *
31
+ * Both modules emit the SAME `SeriesResourceRefs` shape, so the single
32
+ * nine-way resolver in SeriesResourceLinker serves both, and the two can
33
+ * never drift into disagreeing about what identifies a resource.
34
+ *
35
+ * Pure: no database access, no I/O.
36
+ */
37
+
38
+ /*
39
+ * Which relation a monitor type's own step config speaks for. Held as an
40
+ * exhaustive-by-construction map so a new infra monitor type is a
41
+ * one-line addition next to its siblings rather than a new `if` branch
42
+ * buried in the extractor.
43
+ */
44
+ type NameRefKey = keyof Pick<
45
+ SeriesResourceRefs,
46
+ | "hostNames"
47
+ | "dockerHostNames"
48
+ | "podmanHostNames"
49
+ | "kubernetesClusterNames"
50
+ | "proxmoxClusterNames"
51
+ | "cephClusterNames"
52
+ | "dockerSwarmClusterNames"
53
+ | "iotFleetNames"
54
+ >;
55
+
56
+ export default class MonitorStepResourceIdentity {
57
+ /*
58
+ * Every resource the monitor's configuration names, unioned across its
59
+ * steps and deduped. A monitor with three host steps names three
60
+ * hosts: the creation path does not know which step fired, and the
61
+ * alternative — attributing nothing — is what this module exists to
62
+ * fix.
63
+ */
64
+ public static extractResourceRefsFromMonitor(input: {
65
+ monitor: Monitor;
66
+ }): SeriesResourceRefs {
67
+ const refs: SeriesResourceRefs = this.emptyRefs();
68
+
69
+ const monitorType: MonitorType | undefined = input.monitor.monitorType;
70
+
71
+ if (!monitorType) {
72
+ return refs;
73
+ }
74
+
75
+ const monitorSteps: Array<MonitorStep> =
76
+ input.monitor.monitorSteps?.data?.monitorStepsInstanceArray || [];
77
+
78
+ for (const monitorStep of monitorSteps) {
79
+ this.collectFromStep({
80
+ monitorStep: monitorStep,
81
+ monitorType: monitorType,
82
+ refs: refs,
83
+ });
84
+ }
85
+
86
+ return this.dedupeRefs(refs);
87
+ }
88
+
89
+ private static collectFromStep(input: {
90
+ monitorStep: MonitorStep;
91
+ monitorType: MonitorType;
92
+ refs: SeriesResourceRefs;
93
+ }): void {
94
+ const stepData: MonitorStep["data"] = input.monitorStep.data;
95
+
96
+ if (!stepData) {
97
+ return;
98
+ }
99
+
100
+ /*
101
+ * 1. The declared resource identifier — the field the user picked in
102
+ * the monitor form. Validation makes it required for each of
103
+ * these types (see MonitorStep's validation), so this is the
104
+ * strongest signal available.
105
+ */
106
+ const declared: { key: NameRefKey; value: string | undefined } | null =
107
+ this.getDeclaredIdentifier({
108
+ stepData: stepData,
109
+ monitorType: input.monitorType,
110
+ });
111
+
112
+ /*
113
+ * `typeof` rather than a truthiness check: step JSON is not
114
+ * schema-checked, so an identifier written by the API, a seed or an
115
+ * import can be a number or an object, and `.trim()` on those throws
116
+ * out of the incident/alert creation path.
117
+ */
118
+ if (declared && typeof declared.value === "string") {
119
+ const identifier: string = declared.value.trim();
120
+
121
+ if (identifier.length > 0) {
122
+ input.refs[declared.key].push(identifier);
123
+ }
124
+ }
125
+
126
+ /*
127
+ * 2. Telemetry services. Real `Service._id` values written by the
128
+ * monitor form's service picker — a primary key, not a name, so
129
+ * this is the most precise identity in the whole module. Metric
130
+ * monitors carry the field too (RUM recommendation monitors set
131
+ * it), where it is optional.
132
+ */
133
+ for (const serviceId of this.getTelemetryServiceIds({
134
+ stepData: stepData,
135
+ })) {
136
+ input.refs.serviceIds.push(serviceId);
137
+ }
138
+
139
+ /*
140
+ * 3. Metric attribute filters. A generic metric monitor names its
141
+ * resource nowhere else: it scopes itself with filters like
142
+ * `oneuptime.service.name = checkout-api`, which is exactly the
143
+ * key map SeriesResourceLabels already owns. Reusing that map
144
+ * means a filter and a group-by on the same attribute resolve to
145
+ * the same row.
146
+ */
147
+ this.collectFromMetricFilters({
148
+ stepData: stepData,
149
+ monitorType: input.monitorType,
150
+ refs: input.refs,
151
+ });
152
+ }
153
+
154
+ private static getDeclaredIdentifier(input: {
155
+ stepData: NonNullable<MonitorStep["data"]>;
156
+ monitorType: MonitorType;
157
+ }): { key: NameRefKey; value: string | undefined } | null {
158
+ const stepData: NonNullable<MonitorStep["data"]> = input.stepData;
159
+
160
+ switch (input.monitorType) {
161
+ case MonitorType.Host:
162
+ return {
163
+ key: "hostNames",
164
+ value: stepData.hostMonitor?.hostIdentifier,
165
+ };
166
+ case MonitorType.Docker:
167
+ return {
168
+ key: "dockerHostNames",
169
+ value: stepData.dockerMonitor?.hostIdentifier,
170
+ };
171
+ case MonitorType.Podman:
172
+ return {
173
+ key: "podmanHostNames",
174
+ value: stepData.podmanMonitor?.hostIdentifier,
175
+ };
176
+ case MonitorType.Kubernetes:
177
+ return {
178
+ key: "kubernetesClusterNames",
179
+ value: stepData.kubernetesMonitor?.clusterIdentifier,
180
+ };
181
+ case MonitorType.Proxmox:
182
+ return {
183
+ key: "proxmoxClusterNames",
184
+ value: stepData.proxmoxMonitor?.clusterIdentifier,
185
+ };
186
+ case MonitorType.Ceph:
187
+ return {
188
+ key: "cephClusterNames",
189
+ value: stepData.cephMonitor?.clusterIdentifier,
190
+ };
191
+ case MonitorType.DockerSwarm:
192
+ return {
193
+ key: "dockerSwarmClusterNames",
194
+ value: stepData.dockerSwarmMonitor?.clusterIdentifier,
195
+ };
196
+ case MonitorType.IoTDevice:
197
+ return {
198
+ key: "iotFleetNames",
199
+ value: stepData.iotMonitor?.fleetIdentifier,
200
+ };
201
+ default:
202
+ return null;
203
+ }
204
+ }
205
+
206
+ private static getTelemetryServiceIds(input: {
207
+ stepData: NonNullable<MonitorStep["data"]>;
208
+ }): Array<string> {
209
+ const stepData: NonNullable<MonitorStep["data"]> = input.stepData;
210
+
211
+ /*
212
+ * Read from every telemetry sub-config present rather than switching
213
+ * on monitorType: only one of them is ever populated for a given
214
+ * monitor, and this way a step written by an older build (or by the
215
+ * API, a seed, or an import) with a mismatched type still resolves.
216
+ */
217
+ const idLists: Array<Array<ObjectID> | undefined> = [
218
+ stepData.logMonitor?.telemetryServiceIds,
219
+ stepData.traceMonitor?.telemetryServiceIds,
220
+ stepData.exceptionMonitor?.telemetryServiceIds,
221
+ stepData.profileMonitor?.telemetryServiceIds,
222
+ stepData.metricMonitor?.telemetryServiceIds,
223
+ ];
224
+
225
+ const serviceIds: Array<string> = [];
226
+
227
+ for (const idList of idLists) {
228
+ /*
229
+ * `Array.isArray` rather than a truthiness check: an unchecked
230
+ * step written by the API or an import can hold an object or a
231
+ * number here, and `for...of` on those throws out of the
232
+ * incident/alert creation path.
233
+ */
234
+ if (!Array.isArray(idList) || idList.length === 0) {
235
+ continue;
236
+ }
237
+
238
+ for (const id of idList) {
239
+ /*
240
+ * An entry can be a bare string rather than a rehydrated
241
+ * ObjectID, for the same reason. `String()` covers both; empty
242
+ * values are dropped so they can't widen the lookup, and a
243
+ * non-scalar is dropped rather than stringified into a garbage
244
+ * "[object Object]" lookup key.
245
+ */
246
+ if (
247
+ id !== null &&
248
+ typeof id === "object" &&
249
+ !(id instanceof ObjectID)
250
+ ) {
251
+ continue;
252
+ }
253
+
254
+ const idString: string = String(id ?? "").trim();
255
+
256
+ if (idString.length > 0) {
257
+ serviceIds.push(idString);
258
+ }
259
+ }
260
+ }
261
+
262
+ return serviceIds;
263
+ }
264
+
265
+ private static collectFromMetricFilters(input: {
266
+ stepData: NonNullable<MonitorStep["data"]>;
267
+ monitorType: MonitorType;
268
+ refs: SeriesResourceRefs;
269
+ }): void {
270
+ const filterAttributes: JSONObject = this.collectMetricFilterAttributes({
271
+ stepData: input.stepData,
272
+ });
273
+
274
+ if (Object.keys(filterAttributes).length === 0) {
275
+ return;
276
+ }
277
+
278
+ const filterRefs: SeriesResourceRefs =
279
+ SeriesResourceLabels.extractResourceRefs(filterAttributes);
280
+
281
+ /*
282
+ * `resource.host.name` belongs to Host in the label key map, but on
283
+ * a Docker or Podman monitor the worker writes that same attribute
284
+ * from the step's `hostIdentifier` — which names a DockerHost /
285
+ * PodmanHost row, not a Host row. Honouring the map here would
286
+ * attach the wrong model and surface the event on an unrelated
287
+ * Host's Activity tab, so the declared identifier (collected above,
288
+ * into the right bucket) is the only host identity these two types
289
+ * get.
290
+ */
291
+ const suppressHostRefs: boolean =
292
+ input.monitorType === MonitorType.Docker ||
293
+ input.monitorType === MonitorType.Podman;
294
+
295
+ if (suppressHostRefs) {
296
+ filterRefs.hostIds = [];
297
+ filterRefs.hostNames = [];
298
+ }
299
+
300
+ this.mergeRefs({ target: input.refs, source: filterRefs });
301
+ }
302
+
303
+ /*
304
+ * The attribute filters of every metric query on the step, merged.
305
+ * Each infra monitor type keeps its metric view config under its own
306
+ * key, so read them all — exactly the set MonitorStep's own
307
+ * metric-view-config resolver knows about.
308
+ *
309
+ * Values accumulate into an ARRAY per key rather than overwriting: a
310
+ * step can hold several queries, and two of them filtering
311
+ * `oneuptime.service.name` on different services both name a real
312
+ * resource. Last-write-wins would silently drop one of them.
313
+ * SeriesResourceLabels.collectLabelValues already flattens
314
+ * array-valued labels, so the multi-value shape needs nothing extra
315
+ * downstream.
316
+ */
317
+ private static collectMetricFilterAttributes(input: {
318
+ stepData: NonNullable<MonitorStep["data"]>;
319
+ }): JSONObject {
320
+ const stepData: NonNullable<MonitorStep["data"]> = input.stepData;
321
+
322
+ const viewConfigs: Array<MetricsViewConfig | undefined> = [
323
+ stepData.metricMonitor?.metricViewConfig,
324
+ stepData.hostMonitor?.metricViewConfig,
325
+ stepData.kubernetesMonitor?.metricViewConfig,
326
+ stepData.dockerMonitor?.metricViewConfig,
327
+ stepData.podmanMonitor?.metricViewConfig,
328
+ stepData.proxmoxMonitor?.metricViewConfig,
329
+ stepData.cephMonitor?.metricViewConfig,
330
+ stepData.dockerSwarmMonitor?.metricViewConfig,
331
+ stepData.iotMonitor?.metricViewConfig,
332
+ ];
333
+
334
+ const valuesByKey: Map<string, Array<string>> = new Map<
335
+ string,
336
+ Array<string>
337
+ >();
338
+
339
+ for (const viewConfig of viewConfigs) {
340
+ const queryConfigs: Array<MetricQueryConfigData> = Array.isArray(
341
+ viewConfig?.queryConfigs,
342
+ )
343
+ ? viewConfig.queryConfigs
344
+ : [];
345
+
346
+ for (const queryConfig of queryConfigs) {
347
+ const queryAttributes: unknown =
348
+ queryConfig?.metricQueryData?.filterData?.attributes;
349
+
350
+ if (!queryAttributes || typeof queryAttributes !== "object") {
351
+ continue;
352
+ }
353
+
354
+ for (const [key, value] of Object.entries(
355
+ queryAttributes as Record<string, unknown>,
356
+ )) {
357
+ /*
358
+ * Only plain string filters identify a resource. A filter can
359
+ * also hold a Search or Includes instance (substring / set
360
+ * matching), and neither is an identity we can resolve to one
361
+ * row — a `Search("prod")` filter names no specific service.
362
+ */
363
+ if (typeof value !== "string" || value.length === 0) {
364
+ continue;
365
+ }
366
+
367
+ const existing: Array<string> = valuesByKey.get(key) || [];
368
+
369
+ if (!existing.includes(value)) {
370
+ existing.push(value);
371
+ }
372
+
373
+ valuesByKey.set(key, existing);
374
+ }
375
+ }
376
+ }
377
+
378
+ const attributes: JSONObject = {};
379
+
380
+ for (const [key, values] of valuesByKey) {
381
+ /*
382
+ * A single value stays a bare string so the common case reads
383
+ * exactly like a series label; only a genuinely multi-valued
384
+ * filter becomes an array.
385
+ */
386
+ attributes[key] = values.length === 1 ? values[0]! : values;
387
+ }
388
+
389
+ return attributes;
390
+ }
391
+
392
+ private static mergeRefs(input: {
393
+ target: SeriesResourceRefs;
394
+ source: SeriesResourceRefs;
395
+ }): void {
396
+ for (const key of Object.keys(input.target) as Array<
397
+ keyof SeriesResourceRefs
398
+ >) {
399
+ input.target[key].push(...input.source[key]);
400
+ }
401
+ }
402
+
403
+ private static dedupeRefs(refs: SeriesResourceRefs): SeriesResourceRefs {
404
+ for (const key of Object.keys(refs) as Array<keyof SeriesResourceRefs>) {
405
+ refs[key] = Array.from(new Set<string>(refs[key]));
406
+ }
407
+
408
+ return refs;
409
+ }
410
+
411
+ public static emptyRefs(): SeriesResourceRefs {
412
+ return {
413
+ hostIds: [],
414
+ hostNames: [],
415
+ dockerHostIds: [],
416
+ dockerHostNames: [],
417
+ podmanHostIds: [],
418
+ podmanHostNames: [],
419
+ kubernetesClusterIds: [],
420
+ kubernetesClusterNames: [],
421
+ dockerSwarmClusterNames: [],
422
+ proxmoxClusterNames: [],
423
+ cephClusterNames: [],
424
+ iotFleetNames: [],
425
+ serviceIds: [],
426
+ serviceNames: [],
427
+ };
428
+ }
429
+
430
+ /*
431
+ * True when the monitor's configuration names nothing at all — the
432
+ * common case for the ~17 monitor types that have no resource
433
+ * identity (Website, API, Ping, Synthetic, ...). Callers use it to
434
+ * skip the lookup entirely so those monitors keep costing zero
435
+ * database round-trips per evaluation.
436
+ */
437
+ public static isEmpty(refs: SeriesResourceRefs): boolean {
438
+ return Object.values(refs).every((values: Array<string>): boolean => {
439
+ return values.length === 0;
440
+ });
441
+ }
442
+ }
@@ -74,7 +74,7 @@ export const PodmanHostNameLabelKeys: ReadonlyArray<string> = [
74
74
  * Like Proxmox/Ceph, the shipped Swarm alert templates group by
75
75
  * datapoint labels (`container.name`), so their series labels do NOT
76
76
  * carry this key; the deterministic cluster link for those monitors
77
- * comes from the monitor step config instead (see MonitorClusterContext).
77
+ * comes from the monitor step config instead (see MonitorResourceContext).
78
78
  * These keys cover user-built monitors that group by the cluster
79
79
  * attribute.
80
80
  */
@@ -105,7 +105,7 @@ export const KubernetesClusterNameLabelKeys: ReadonlyArray<string> = [
105
105
  * datapoint labels (`id`, `ceph_daemon`, `pool_id`), so their series
106
106
  * labels do NOT carry these keys; the deterministic cluster link for
107
107
  * those monitors comes from the monitor step config instead (see
108
- * MonitorClusterContext). These keys cover user-built monitors that
108
+ * MonitorResourceContext). These keys cover user-built monitors that
109
109
  * group by the cluster attribute, exactly like the K8s keys above.
110
110
  */
111
111
  export const ProxmoxClusterNameLabelKeys: ReadonlyArray<string> = [
@@ -127,7 +127,7 @@ export const CephClusterNameLabelKeys: ReadonlyArray<string> = [
127
127
  * alert templates group by the datapoint label `device.id`, so their
128
128
  * series labels do NOT carry these keys; the deterministic fleet link
129
129
  * for those monitors comes from the monitor step config instead (see
130
- * MonitorClusterContext). These keys cover user-built monitors that
130
+ * MonitorResourceContext). These keys cover user-built monitors that
131
131
  * group by the fleet attribute.
132
132
  */
133
133
  export const IoTFleetNameLabelKeys: ReadonlyArray<string> = [