@oneuptime/common 12.0.7 → 12.0.9

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 (873) hide show
  1. package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +1 -1
  2. package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +1 -1
  3. package/Models/DatabaseModels/AIConversation.ts +32 -0
  4. package/Models/DatabaseModels/AIConversationMessage.ts +41 -0
  5. package/Models/DatabaseModels/AlertEpisodeMember.ts +27 -0
  6. package/Models/DatabaseModels/IncidentEpisodeMember.ts +28 -0
  7. package/Models/DatabaseModels/Index.ts +12 -4
  8. package/Models/DatabaseModels/{TelemetryEntity.ts → InventoryItem.ts} +184 -9
  9. package/Models/DatabaseModels/InventoryItemCustomField.ts +434 -0
  10. package/Models/DatabaseModels/{TelemetryEntityRelationship.ts → InventoryItemRelationship.ts} +33 -7
  11. package/Models/DatabaseModels/NetworkDevice.ts +141 -0
  12. package/Models/DatabaseModels/NetworkDeviceLink.ts +699 -0
  13. package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +467 -0
  14. package/Models/DatabaseModels/NetworkTopologySuppression.ts +429 -0
  15. package/Models/DatabaseModels/OnCallDutyPolicyFeed.ts +9 -0
  16. package/Models/DatabaseModels/Project.ts +78 -0
  17. package/Models/DatabaseModels/UserCall.ts +42 -0
  18. package/Models/DatabaseModels/UserEmail.ts +44 -0
  19. package/Models/DatabaseModels/UserNotificationRule.ts +425 -55
  20. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +24 -2
  21. package/Models/DatabaseModels/UserPush.ts +49 -0
  22. package/Models/DatabaseModels/UserSMS.ts +43 -0
  23. package/Models/DatabaseModels/UserTelegram.ts +59 -0
  24. package/Models/DatabaseModels/UserWebhook.ts +52 -0
  25. package/Models/DatabaseModels/UserWhatsApp.ts +41 -0
  26. package/Models/DatabaseModels/WorkflowLog.ts +38 -0
  27. package/Models/DatabaseModels/WorkflowVariable.ts +12 -0
  28. package/Server/API/AIChatAPI.ts +315 -1
  29. package/Server/API/DashboardAPI.ts +217 -1
  30. package/Server/API/OnCallReadinessAPI.ts +841 -0
  31. package/Server/API/TeamComplianceAPI.ts +69 -17
  32. package/Server/API/TelemetryAPI.ts +220 -12
  33. package/Server/API/UserAPI.ts +16 -1
  34. package/Server/EnvironmentConfig.ts +52 -0
  35. package/Server/Infrastructure/Postgres/DataSourceOptions.ts +22 -0
  36. package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +4 -4
  37. package/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.ts +5 -5
  38. package/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.ts +41 -0
  39. package/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.ts +17 -0
  40. package/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.ts +35 -0
  41. package/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.ts +82 -0
  42. package/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.ts +91 -0
  43. package/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.ts +47 -0
  44. package/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.ts +255 -0
  45. package/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.ts +107 -0
  46. package/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.ts +90 -0
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.ts +39 -0
  48. package/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.ts +33 -0
  49. package/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.ts +59 -0
  50. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +24 -0
  51. package/Server/Infrastructure/Queue.ts +78 -13
  52. package/Server/Middleware/MasterAdminAuthorization.ts +11 -6
  53. package/Server/Middleware/PublicDashboardRateLimit.ts +593 -0
  54. package/Server/Services/AIService.ts +7 -0
  55. package/Server/Services/AlertEpisodeStateTimelineService.ts +29 -0
  56. package/Server/Services/AlertSeverityService.ts +63 -0
  57. package/Server/Services/DashboardService.ts +9 -10
  58. package/Server/Services/DatabaseService.ts +32 -2
  59. package/Server/Services/IncidentEpisodeStateTimelineService.ts +29 -0
  60. package/Server/Services/IncidentSeverityService.ts +76 -0
  61. package/Server/Services/Index.ts +12 -4
  62. package/Server/Services/InventoryItemCustomFieldService.ts +9 -0
  63. package/Server/Services/{TelemetryEntityRelationshipService.ts → InventoryItemRelationshipService.ts} +7 -4
  64. package/Server/Services/{TelemetryEntityService.ts → InventoryItemService.ts} +203 -21
  65. package/Server/Services/LogAggregationService.ts +45 -8
  66. package/Server/Services/MetricAggregationService.ts +121 -0
  67. package/Server/Services/MetricService.ts +7 -7
  68. package/Server/Services/NetworkDeviceLinkRuleService.ts +10 -0
  69. package/Server/Services/NetworkDeviceLinkService.ts +84 -0
  70. package/Server/Services/NetworkDeviceService.ts +140 -0
  71. package/Server/Services/NetworkSiteService.ts +77 -25
  72. package/Server/Services/NetworkTopologySuppressionService.ts +84 -0
  73. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +41 -29
  74. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +8 -0
  75. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +62 -13
  76. package/Server/Services/OnCallDutyPolicyScheduleService.ts +61 -1
  77. package/Server/Services/OnCallNotificationAlertingService.ts +742 -0
  78. package/Server/Services/OnCallReadinessService.ts +2803 -0
  79. package/Server/Services/OnCallSetupReminderService.ts +955 -0
  80. package/Server/Services/ProfileAggregationService.ts +123 -0
  81. package/Server/Services/StatusPageService.ts +9 -10
  82. package/Server/Services/TeamComplianceService.ts +429 -252
  83. package/Server/Services/UserCallService.ts +26 -1
  84. package/Server/Services/UserEmailService.ts +26 -1
  85. package/Server/Services/UserNotificationRuleAdminService.ts +1183 -0
  86. package/Server/Services/UserNotificationRuleService.ts +3812 -333
  87. package/Server/Services/UserOnCallLogService.ts +561 -48
  88. package/Server/Services/UserPushService.ts +29 -0
  89. package/Server/Services/UserService.ts +11 -0
  90. package/Server/Services/UserSmsService.ts +26 -1
  91. package/Server/Services/UserTelegramService.ts +24 -1
  92. package/Server/Services/UserWebhookService.ts +28 -1
  93. package/Server/Services/UserWhatsAppService.ts +24 -1
  94. package/Server/Types/Database/Permissions/BasePermission.ts +19 -0
  95. package/Server/Types/Database/Permissions/CreatePermission.ts +164 -0
  96. package/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.ts +340 -0
  97. package/Server/Types/Database/Permissions/QueryPermission.ts +48 -0
  98. package/Server/Types/Database/Permissions/TenantPermission.ts +8 -1
  99. package/Server/Types/Workflow/Components/API/Delete.ts +1 -1
  100. package/Server/Types/Workflow/Components/API/Get.ts +1 -1
  101. package/Server/Types/Workflow/Components/API/Patch.ts +1 -1
  102. package/Server/Types/Workflow/Components/API/Post.ts +1 -1
  103. package/Server/Types/Workflow/Components/API/Put.ts +1 -1
  104. package/Server/Types/Workflow/Components/API/Utils.ts +44 -1
  105. package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +29 -5
  106. package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +18 -10
  107. package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +55 -0
  108. package/Server/Types/Workflow/Components/Conditions/IfElse.ts +3 -17
  109. package/Server/Types/Workflow/Components/Email.ts +25 -7
  110. package/Server/Types/Workflow/Components/JavaScript.ts +10 -3
  111. package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +1 -1
  112. package/Server/Types/Workflow/TriggerCode.ts +12 -0
  113. package/Server/Types/Workflow/Workflow.ts +5 -0
  114. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +643 -48
  115. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +32 -3
  116. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +20 -6
  117. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +7 -0
  118. package/Server/Utils/AI/Toolbox/AIActionTools.ts +2 -2
  119. package/Server/Utils/AI/Toolbox/AIMetaTools.ts +863 -0
  120. package/Server/Utils/AI/Toolbox/AlertTools.ts +177 -15
  121. package/Server/Utils/AI/Toolbox/IncidentTools.ts +191 -10
  122. package/Server/Utils/AI/Toolbox/Index.ts +48 -0
  123. package/Server/Utils/AI/Toolbox/MonitorTools.ts +298 -11
  124. package/Server/Utils/AI/Toolbox/NoteWriteTools.ts +295 -0
  125. package/Server/Utils/AI/Toolbox/OnCallTools.ts +1246 -0
  126. package/Server/Utils/AI/Toolbox/RunbookTools.ts +424 -0
  127. package/Server/Utils/AI/Toolbox/SloTools.ts +456 -0
  128. package/Server/Utils/AI/Toolbox/StatusPageTools.ts +559 -0
  129. package/Server/Utils/AI/Toolbox/TeamTools.ts +327 -0
  130. package/Server/Utils/AI/Toolbox/TimelineTools.ts +615 -0
  131. package/Server/Utils/AI/Toolbox/WorkflowProbeTools.ts +664 -0
  132. package/Server/Utils/ClientIp.ts +221 -0
  133. package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +47 -0
  134. package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +163 -0
  135. package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +147 -0
  136. package/Server/Utils/Express.ts +12 -17
  137. package/Server/Utils/LLM/LLMService.ts +85 -8
  138. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +204 -10
  139. package/Server/Utils/SSRFProtection.ts +98 -23
  140. package/Server/Utils/StartServer.ts +12 -3
  141. package/Server/Utils/Telemetry/EntityRegistry.ts +205 -18
  142. package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +689 -0
  143. package/Server/Utils/Telemetry/TelemetryEntity.ts +160 -52
  144. package/Server/Utils/VM/VMAPI.ts +56 -8
  145. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +7 -3
  146. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +2146 -0
  147. package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +561 -0
  148. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +2470 -0
  149. package/Tests/App/Dashboard/MonitorCriteriaAttributeFilter.test.tsx +574 -0
  150. package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +1897 -0
  151. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3606 -0
  152. package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +784 -0
  153. package/Tests/App/Dashboard/OnCallRulesTable.test.tsx +1119 -0
  154. package/Tests/App/Dashboard/SloWidgetFetching.test.tsx +531 -0
  155. package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +1312 -0
  156. package/Tests/App/Dashboard/UserSettingsSetupChecklistPage.test.tsx +1390 -0
  157. package/Tests/Models/InventoryItemModel.test.ts +174 -0
  158. package/Tests/Models/InventoryItemNaming.test.ts +302 -0
  159. package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +437 -0
  160. package/Tests/Server/API/DashboardPublicRateLimit.test.ts +659 -0
  161. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +18 -0
  162. package/Tests/Server/API/DashboardPublicSloAPI.test.ts +880 -0
  163. package/Tests/Server/API/Helpers.ts +24 -15
  164. package/Tests/Server/API/OnCallReadinessAPI.test.ts +2680 -0
  165. package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +915 -0
  166. package/Tests/Server/API/UserProjectsAPI.test.ts +478 -4
  167. package/Tests/Server/Infrastructure/Postgres/EpisodeMemberNotifyIndexesMigration.test.ts +533 -0
  168. package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +213 -0
  169. package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +432 -0
  170. package/Tests/Server/Infrastructure/Queue.test.ts +293 -0
  171. package/Tests/Server/Middleware/PublicDashboardRateLimit.test.ts +1645 -0
  172. package/Tests/Server/Services/AdminRuleEditGuards.test.ts +2848 -0
  173. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1393 -0
  174. package/Tests/Server/Services/EpisodeRuleSeverityRepair.test.ts +1802 -0
  175. package/Tests/Server/Services/EpisodeStateTimelineNote.test.ts +304 -0
  176. package/Tests/Server/Services/InventoryItemDisplayName.test.ts +339 -0
  177. package/Tests/Server/Services/InventoryItemManualCreate.test.ts +248 -0
  178. package/Tests/Server/Services/IpAllowlistSpoofing.test.ts +450 -0
  179. package/Tests/Server/Services/LogAggregationService.test.ts +235 -1
  180. package/Tests/Server/Services/MetricAggregationService.test.ts +231 -0
  181. package/Tests/Server/Services/MetricEntityMVKeyParity.test.ts +80 -29
  182. package/Tests/Server/Services/MetricServiceAggregate.test.ts +30 -30
  183. package/Tests/Server/Services/NetworkSiteService.test.ts +18 -3
  184. package/Tests/Server/Services/NotificationChannelEventCoverage.test.ts +1728 -0
  185. package/Tests/Server/Services/NotificationDeletionImpact.test.ts +2402 -0
  186. package/Tests/Server/Services/OnCallDutyPolicyExecutionLogTimelineGapFeed.test.ts +394 -0
  187. package/Tests/Server/Services/OnCallNotificationFallback.test.ts +1744 -0
  188. package/Tests/Server/Services/OnCallReadinessService.test.ts +4295 -0
  189. package/Tests/Server/Services/OnCallSetupReminder.test.ts +1272 -0
  190. package/Tests/Server/Services/OnCallWeeklyReadinessDigest.test.ts +1021 -0
  191. package/Tests/Server/Services/ProfileAggregationService.test.ts +296 -0
  192. package/Tests/Server/Services/SeverityCreationRuleBackfill.test.ts +1536 -0
  193. package/Tests/Server/Services/SeverityRuleBackfill.test.ts +1818 -0
  194. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +1845 -0
  195. package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +1394 -0
  196. package/Tests/Server/Services/UserNotificationRuleDefaultCreation.test.ts +1166 -0
  197. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1468 -0
  198. package/Tests/Server/Services/UserOnCallLogNoNotificationRules.test.ts +1457 -0
  199. package/Tests/Server/Types/Database/Permissions/AdminNotificationRuleAccess.test.ts +1546 -0
  200. package/Tests/Server/Types/Database/Permissions/CreateOwnershipScoping.test.ts +529 -0
  201. package/Tests/Server/Types/Database/Permissions/OwnerOnlyColumns.test.ts +1219 -0
  202. package/Tests/Server/Types/Database/Permissions/UserNotificationRuleScoping.test.ts +1089 -0
  203. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +2 -1
  204. package/Tests/Server/Types/Workflow/Components/ApiComponentHeaders.test.ts +192 -0
  205. package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +190 -0
  206. package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +44 -14
  207. package/Tests/Server/Types/Workflow/Components/Email.test.ts +151 -0
  208. package/Tests/Server/Types/Workflow/Components/IfElse.test.ts +98 -0
  209. package/Tests/Server/Types/Workflow/Components/JavaScript.test.ts +51 -0
  210. package/Tests/Server/Utils/AI/AIMetaTools.test.ts +586 -0
  211. package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +582 -0
  212. package/Tests/Server/Utils/AI/ChatAgentRunner.test.ts +726 -0
  213. package/Tests/Server/Utils/AI/IncidentToolsFilters.test.ts +315 -0
  214. package/Tests/Server/Utils/AI/LLMServiceStopReason.test.ts +314 -0
  215. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +26 -3
  216. package/Tests/Server/Utils/AI/NoteWriteTools.test.ts +268 -0
  217. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +169 -0
  218. package/Tests/Server/Utils/AI/OnCallTools.test.ts +664 -0
  219. package/Tests/Server/Utils/AI/RunbookTools.test.ts +325 -0
  220. package/Tests/Server/Utils/AI/SloTools.test.ts +306 -0
  221. package/Tests/Server/Utils/AI/StatusPageTools.test.ts +391 -0
  222. package/Tests/Server/Utils/AI/TeamTools.test.ts +257 -0
  223. package/Tests/Server/Utils/AI/TimelineTools.test.ts +472 -0
  224. package/Tests/Server/Utils/AI/WorkflowProbeTools.test.ts +428 -0
  225. package/Tests/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.test.ts +152 -0
  226. package/Tests/Server/Utils/ClientIp.test.ts +438 -0
  227. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +171 -0
  228. package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +383 -0
  229. package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +23 -25
  230. package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +6 -0
  231. package/Tests/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.test.ts +307 -0
  232. package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +468 -0
  233. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorTelemetryDeepLinks.test.ts +460 -0
  234. package/Tests/Server/Utils/ResponseRateLimitStatusCodes.test.ts +137 -0
  235. package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +40 -8
  236. package/Tests/Server/Utils/SSRFProtectionUserInfo.test.ts +351 -0
  237. package/Tests/Server/Utils/Telemetry/EntityRegistryRetirement.test.ts +531 -0
  238. package/Tests/Server/Utils/Telemetry/InventoryEntityRegistry.test.ts +322 -0
  239. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +356 -39
  240. package/Tests/Server/Utils/VM/VMAPISubstitution.test.ts +243 -0
  241. package/Tests/Types/IP/IP.test.ts +263 -0
  242. package/Tests/Types/IP/IPWhitelist.test.ts +197 -0
  243. package/Tests/Types/IP/IPv6.test.ts +12 -1
  244. package/Tests/Types/Monitor/SnmpOid.test.ts +64 -0
  245. package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +110 -0
  246. package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeAudit.test.ts +106 -0
  247. package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeDifferential.test.ts +511 -0
  248. package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageEndToEnd.test.ts +489 -0
  249. package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageGapTolerance.test.ts +479 -0
  250. package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageState.test.ts +822 -0
  251. package/Tests/Types/SerializableObjectDictionaryImportCycle.test.ts +197 -0
  252. package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +140 -0
  253. package/Tests/Types/Workflow/BaseModelComponents.test.ts +429 -0
  254. package/Tests/Types/Workflow/Components/BaseModel.test.ts +225 -0
  255. package/Tests/Types/Workflow/IntegrationCredentialMetadata.test.ts +100 -0
  256. package/Tests/Types/Workflow/StepTrace.test.ts +235 -0
  257. package/Tests/Types/Workflow/TemplateSyntax.test.ts +491 -0
  258. package/Tests/Types/Workflow/Templates.test.ts +1218 -0
  259. package/Tests/UI/Components/ActiveFilterChipsOpenRoute.test.tsx +82 -0
  260. package/Tests/UI/Components/ComponentsModal.test.tsx +564 -7
  261. package/Tests/UI/Components/CustomTimeRangeModal.test.tsx +459 -0
  262. package/Tests/UI/Components/DictionaryAttributeFilterRow.test.tsx +477 -0
  263. package/Tests/UI/Components/Forms/AnchoredFieldPopupKeyboard.test.tsx +382 -0
  264. package/Tests/UI/Components/Forms/ColorPickerPicking.test.tsx +569 -0
  265. package/Tests/UI/Components/Forms/ValidationJSON.test.ts +241 -0
  266. package/Tests/UI/Components/KeyboardShortcut.test.tsx +95 -0
  267. package/Tests/UI/Components/LogDetailsPanelCrossSignal.test.tsx +448 -0
  268. package/Tests/UI/Components/LogTimeRangePicker.test.tsx +42 -0
  269. package/Tests/UI/Components/LogsTableCrossLinks.test.tsx +263 -0
  270. package/Tests/UI/Components/ModalPortalDismissal.test.tsx +90 -0
  271. package/Tests/UI/Components/PendingProjectInvitations.test.tsx +913 -0
  272. package/Tests/UI/Components/SimpleLogViewer.test.tsx +228 -0
  273. package/Tests/UI/Components/TableRowSelectability.test.tsx +312 -0
  274. package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +49 -7
  275. package/Tests/UI/Components/TimeRangePickerDropdown.test.tsx +325 -0
  276. package/Tests/UI/Components/Workflow/GraphLint.test.ts +893 -0
  277. package/Tests/UI/Components/Workflow/GraphLintSummary.test.ts +755 -0
  278. package/Tests/UI/Components/Workflow/ModelColumnEditor.test.ts +522 -0
  279. package/Tests/UI/Components/Workflow/ModelColumnEditorServerContract.test.ts +193 -0
  280. package/Tests/UI/Components/Workflow/ModelSchema.test.ts +388 -0
  281. package/Tests/UI/Components/Workflow/RunStatusWatcher.test.ts +210 -0
  282. package/Tests/UI/Components/Workflow/StepTraceViewer.test.tsx +256 -0
  283. package/Tests/UI/Components/Workflow/UseRunWatch.test.tsx +665 -0
  284. package/Tests/UI/Components/Workflow/Utils.test.ts +192 -0
  285. package/Tests/UI/Components/Workflow/WorkflowIssuesModal.test.tsx +485 -0
  286. package/Tests/UI/Components/Workflow/WorkflowLogModal.test.tsx +478 -0
  287. package/Tests/UI/Components/Workflow/WorkflowStatusBar.test.tsx +379 -0
  288. package/Tests/UI/EsbuildConfig.test.ts +607 -0
  289. package/Tests/UI/Monitor/MonitorStepCriteriaView.test.tsx +432 -0
  290. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +5 -0
  291. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +11 -4
  292. package/Tests/UI/Utils/ModelAPICreateMiscData.test.ts +94 -0
  293. package/Tests/UI/Utils/Platform.test.ts +147 -0
  294. package/Tests/UI/Utils/ProjectInvitationDisplay.test.ts +357 -0
  295. package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +198 -0
  296. package/Tests/Utils/Monitor/NetworkDeviceRoleUtil.test.ts +514 -0
  297. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +727 -0
  298. package/Tests/Utils/Schema/AnalyticsModelSchema.test.ts +469 -0
  299. package/Tests/Utils/Schema/ModelSchema.test.ts +268 -0
  300. package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +698 -0
  301. package/Tests/Utils/Telemetry/EntityKeyNonTelemetry.test.ts +193 -0
  302. package/Tests/__mocks__/bullmq.js +55 -0
  303. package/Types/AI/AIChatMessageStatus.ts +8 -1
  304. package/Types/AI/AIChatTypes.ts +12 -0
  305. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +88 -0
  306. package/Types/Exception/ExceptionCode.ts +2 -0
  307. package/Types/Exception/ServiceUnavailableException.ts +8 -0
  308. package/Types/Exception/TooManyRequestsException.ts +8 -0
  309. package/Types/IP/IP.ts +93 -47
  310. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +80 -3
  311. package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +55 -0
  312. package/Types/OnCallDutyPolicy/Layer.ts +203 -149
  313. package/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.ts +13 -0
  314. package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +155 -10
  315. package/Types/Permission.ts +193 -0
  316. package/Types/SerializableObjectDictionary.ts +133 -39
  317. package/Types/Telemetry/EntityRelationshipType.ts +1 -1
  318. package/Types/Telemetry/EntitySource.ts +40 -0
  319. package/Types/Telemetry/EntityType.ts +28 -1
  320. package/Types/Telemetry/EntityTypeGroups.ts +65 -0
  321. package/Types/Workflow/Component.ts +29 -0
  322. package/Types/Workflow/Components/API.ts +35 -0
  323. package/Types/Workflow/Components/BaseModel.ts +77 -27
  324. package/Types/Workflow/Components/Discord.ts +1 -0
  325. package/Types/Workflow/Components/Email.ts +12 -3
  326. package/Types/Workflow/Components/JavaScript.ts +7 -0
  327. package/Types/Workflow/Components/MicrosoftTeams.ts +3 -2
  328. package/Types/Workflow/Components/Slack.ts +1 -0
  329. package/Types/Workflow/Components/Telegram.ts +1 -0
  330. package/Types/Workflow/StepTrace.ts +181 -0
  331. package/Types/Workflow/TemplateSyntax.ts +543 -0
  332. package/Types/Workflow/Templates.ts +2368 -0
  333. package/UI/Components/Calendar/Calendar.css +43 -0
  334. package/UI/Components/Calendar/Calendar.tsx +8 -0
  335. package/UI/Components/Card/Card.tsx +2 -2
  336. package/UI/Components/Checkbox/Checkbox.tsx +16 -0
  337. package/UI/Components/Date/CustomTimeRangeModal.tsx +278 -0
  338. package/UI/Components/Date/TimeRangePickerDropdown.tsx +250 -0
  339. package/UI/Components/Dictionary/Dictionary.tsx +71 -15
  340. package/UI/Components/FormModal/BasicFormModal.tsx +2 -1
  341. package/UI/Components/Forms/Fields/ColorPicker.tsx +66 -10
  342. package/UI/Components/Forms/Fields/IconPicker.tsx +48 -10
  343. package/UI/Components/Forms/Types/Field.ts +7 -0
  344. package/UI/Components/Forms/Validation.ts +63 -1
  345. package/UI/Components/Header/HeaderIconDropdownButton.tsx +53 -3
  346. package/UI/Components/Input/Input.tsx +32 -3
  347. package/UI/Components/KeyboardShortcut/KeyboardKey.ts +185 -0
  348. package/UI/Components/KeyboardShortcut/KeyboardShortcut.tsx +87 -0
  349. package/UI/Components/LogsViewer/LogsViewer.tsx +28 -0
  350. package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +31 -0
  351. package/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.tsx +18 -18
  352. package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +363 -14
  353. package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +11 -216
  354. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +11 -0
  355. package/UI/Components/LogsViewer/components/LogsTable.tsx +155 -12
  356. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +29 -0
  357. package/UI/Components/LogsViewer/types.ts +23 -0
  358. package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +9 -2
  359. package/UI/Components/Modal/Modal.tsx +37 -4
  360. package/UI/Components/Navbar/NavBarMenuModal.tsx +15 -30
  361. package/UI/Components/ProjectInvitations/PendingProjectInvitations.tsx +442 -0
  362. package/UI/Components/SimpleLogViewer/SimpleLogViewer.tsx +23 -1
  363. package/UI/Components/Table/Table.tsx +49 -16
  364. package/UI/Components/Table/TableBody.tsx +53 -28
  365. package/UI/Components/Table/TableHeader.tsx +13 -0
  366. package/UI/Components/Table/TableRow.tsx +58 -26
  367. package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +11 -210
  368. package/UI/Components/Workflow/ArgumentsForm.tsx +341 -8
  369. package/UI/Components/Workflow/Component.tsx +28 -26
  370. package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +26 -0
  371. package/UI/Components/Workflow/ComponentSettingsModal.tsx +79 -9
  372. package/UI/Components/Workflow/ComponentValuePickerModal.tsx +135 -7
  373. package/UI/Components/Workflow/ComponentsModal.tsx +116 -22
  374. package/UI/Components/Workflow/DocumentationViewer.tsx +59 -9
  375. package/UI/Components/Workflow/GraphLint.ts +628 -0
  376. package/UI/Components/Workflow/GraphLintSummary.ts +390 -0
  377. package/UI/Components/Workflow/ModelColumnEditor.tsx +528 -0
  378. package/UI/Components/Workflow/ModelSchema.ts +278 -0
  379. package/UI/Components/Workflow/RunForm.tsx +41 -7
  380. package/UI/Components/Workflow/RunStatusWatcher.ts +122 -0
  381. package/UI/Components/Workflow/StepTraceViewer.tsx +186 -0
  382. package/UI/Components/Workflow/UseRunWatch.ts +212 -0
  383. package/UI/Components/Workflow/Utils.ts +93 -1
  384. package/UI/Components/Workflow/VariableModal.tsx +6 -2
  385. package/UI/Components/Workflow/Workflow.tsx +126 -7
  386. package/UI/Components/Workflow/WorkflowIssuesModal.tsx +255 -0
  387. package/UI/Components/Workflow/WorkflowLogModal.tsx +128 -0
  388. package/UI/Components/Workflow/WorkflowStatusBar.tsx +224 -0
  389. package/UI/Types/LayeredDismissal.ts +31 -0
  390. package/UI/Types/UseAnchoredFieldPopup.ts +99 -0
  391. package/UI/Utils/AIChatExport/ConversationMarkdown.ts +10 -0
  392. package/UI/Utils/ModelAPI/ModelAPI.ts +7 -1
  393. package/UI/Utils/Platform.ts +149 -0
  394. package/UI/Utils/ProjectInvitationDisplay.ts +118 -0
  395. package/UI/esbuild-config.js +22 -1
  396. package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +187 -0
  397. package/Utils/Monitor/NetworkDeviceRoleUtil.ts +533 -0
  398. package/Utils/Monitor/NetworkTopologyUtil.ts +917 -155
  399. package/Utils/Telemetry/CrossSignalScope.ts +502 -0
  400. package/Utils/Telemetry/EntityKey.ts +71 -5
  401. package/Utils/Telemetry/EntityRelationship.ts +1 -1
  402. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +1 -1
  403. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +1 -1
  404. package/build/dist/Models/DatabaseModels/AIConversation.js +32 -0
  405. package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
  406. package/build/dist/Models/DatabaseModels/AIConversationMessage.js +42 -0
  407. package/build/dist/Models/DatabaseModels/AIConversationMessage.js.map +1 -1
  408. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +28 -0
  409. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
  410. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +29 -0
  411. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
  412. package/build/dist/Models/DatabaseModels/Index.js +12 -4
  413. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  414. package/build/dist/Models/DatabaseModels/{TelemetryEntity.js → InventoryItem.js} +212 -29
  415. package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -0
  416. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +454 -0
  417. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js.map +1 -0
  418. package/build/dist/Models/DatabaseModels/{TelemetryEntityRelationship.js → InventoryItemRelationship.js} +52 -25
  419. package/build/dist/Models/DatabaseModels/InventoryItemRelationship.js.map +1 -0
  420. package/build/dist/Models/DatabaseModels/NetworkDevice.js +141 -0
  421. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  422. package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js +719 -0
  423. package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js.map +1 -0
  424. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +475 -0
  425. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -0
  426. package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js +446 -0
  427. package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js.map +1 -0
  428. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js +9 -0
  429. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js.map +1 -1
  430. package/build/dist/Models/DatabaseModels/Project.js +80 -0
  431. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  432. package/build/dist/Models/DatabaseModels/UserCall.js +46 -2
  433. package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
  434. package/build/dist/Models/DatabaseModels/UserEmail.js +48 -2
  435. package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
  436. package/build/dist/Models/DatabaseModels/UserNotificationRule.js +424 -55
  437. package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
  438. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +24 -2
  439. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  440. package/build/dist/Models/DatabaseModels/UserPush.js +51 -1
  441. package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
  442. package/build/dist/Models/DatabaseModels/UserSMS.js +47 -2
  443. package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
  444. package/build/dist/Models/DatabaseModels/UserTelegram.js +65 -3
  445. package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
  446. package/build/dist/Models/DatabaseModels/UserWebhook.js +56 -2
  447. package/build/dist/Models/DatabaseModels/UserWebhook.js.map +1 -1
  448. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +45 -2
  449. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
  450. package/build/dist/Models/DatabaseModels/WorkflowLog.js +39 -0
  451. package/build/dist/Models/DatabaseModels/WorkflowLog.js.map +1 -1
  452. package/build/dist/Models/DatabaseModels/WorkflowVariable.js +12 -0
  453. package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
  454. package/build/dist/Server/API/AIChatAPI.js +237 -1
  455. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  456. package/build/dist/Server/API/DashboardAPI.js +165 -13
  457. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  458. package/build/dist/Server/API/OnCallReadinessAPI.js +599 -0
  459. package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -0
  460. package/build/dist/Server/API/TeamComplianceAPI.js +68 -9
  461. package/build/dist/Server/API/TeamComplianceAPI.js.map +1 -1
  462. package/build/dist/Server/API/TelemetryAPI.js +129 -18
  463. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  464. package/build/dist/Server/API/UserAPI.js +16 -1
  465. package/build/dist/Server/API/UserAPI.js.map +1 -1
  466. package/build/dist/Server/EnvironmentConfig.js +45 -0
  467. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  468. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +22 -0
  469. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
  470. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js +4 -4
  471. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.js +20 -0
  472. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.js.map +1 -0
  473. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.js +12 -0
  474. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.js.map +1 -0
  475. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js +18 -0
  476. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js.map +1 -0
  477. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js +39 -0
  478. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js.map +1 -0
  479. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js +38 -0
  480. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js.map +1 -0
  481. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js +22 -0
  482. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js.map +1 -0
  483. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js +150 -0
  484. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js.map +1 -0
  485. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js +57 -0
  486. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js.map +1 -0
  487. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js +69 -0
  488. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js.map +1 -0
  489. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js +32 -0
  490. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js.map +1 -0
  491. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js +26 -0
  492. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js.map +1 -0
  493. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js +48 -0
  494. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js.map +1 -0
  495. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +24 -0
  496. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  497. package/build/dist/Server/Infrastructure/Queue.js +72 -13
  498. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  499. package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -6
  500. package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
  501. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js +399 -0
  502. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js.map +1 -0
  503. package/build/dist/Server/Services/AIService.js +1 -0
  504. package/build/dist/Server/Services/AIService.js.map +1 -1
  505. package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js +24 -3
  506. package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js.map +1 -1
  507. package/build/dist/Server/Services/AlertSeverityService.js +54 -0
  508. package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
  509. package/build/dist/Server/Services/DashboardService.js +10 -9
  510. package/build/dist/Server/Services/DashboardService.js.map +1 -1
  511. package/build/dist/Server/Services/DatabaseService.js +24 -2
  512. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  513. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +24 -3
  514. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
  515. package/build/dist/Server/Services/IncidentSeverityService.js +67 -0
  516. package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
  517. package/build/dist/Server/Services/Index.js +12 -4
  518. package/build/dist/Server/Services/Index.js.map +1 -1
  519. package/build/dist/Server/Services/InventoryItemCustomFieldService.js +9 -0
  520. package/build/dist/Server/Services/InventoryItemCustomFieldService.js.map +1 -0
  521. package/build/dist/Server/Services/{TelemetryEntityRelationshipService.js → InventoryItemRelationshipService.js} +9 -6
  522. package/build/dist/Server/Services/InventoryItemRelationshipService.js.map +1 -0
  523. package/build/dist/Server/Services/{TelemetryEntityService.js → InventoryItemService.js} +158 -23
  524. package/build/dist/Server/Services/InventoryItemService.js.map +1 -0
  525. package/build/dist/Server/Services/LogAggregationService.js +27 -8
  526. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  527. package/build/dist/Server/Services/MetricAggregationService.js +80 -0
  528. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  529. package/build/dist/Server/Services/MetricService.js +6 -6
  530. package/build/dist/Server/Services/MetricService.js.map +1 -1
  531. package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js +9 -0
  532. package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js.map +1 -0
  533. package/build/dist/Server/Services/NetworkDeviceLinkService.js +71 -0
  534. package/build/dist/Server/Services/NetworkDeviceLinkService.js.map +1 -0
  535. package/build/dist/Server/Services/NetworkDeviceService.js +113 -0
  536. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  537. package/build/dist/Server/Services/NetworkSiteService.js +53 -13
  538. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  539. package/build/dist/Server/Services/NetworkTopologySuppressionService.js +85 -0
  540. package/build/dist/Server/Services/NetworkTopologySuppressionService.js.map +1 -0
  541. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +48 -32
  542. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  543. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +8 -0
  544. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  545. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +51 -12
  546. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  547. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +57 -13
  548. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  549. package/build/dist/Server/Services/OnCallNotificationAlertingService.js +548 -0
  550. package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -0
  551. package/build/dist/Server/Services/OnCallReadinessService.js +1961 -0
  552. package/build/dist/Server/Services/OnCallReadinessService.js.map +1 -0
  553. package/build/dist/Server/Services/OnCallSetupReminderService.js +738 -0
  554. package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -0
  555. package/build/dist/Server/Services/ProfileAggregationService.js +68 -4
  556. package/build/dist/Server/Services/ProfileAggregationService.js.map +1 -1
  557. package/build/dist/Server/Services/StatusPageService.js +11 -10
  558. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  559. package/build/dist/Server/Services/TeamComplianceService.js +312 -160
  560. package/build/dist/Server/Services/TeamComplianceService.js.map +1 -1
  561. package/build/dist/Server/Services/UserCallService.js +24 -1
  562. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  563. package/build/dist/Server/Services/UserEmailService.js +24 -1
  564. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  565. package/build/dist/Server/Services/UserNotificationRuleAdminService.js +858 -0
  566. package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -0
  567. package/build/dist/Server/Services/UserNotificationRuleService.js +2830 -175
  568. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  569. package/build/dist/Server/Services/UserOnCallLogService.js +488 -43
  570. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  571. package/build/dist/Server/Services/UserPushService.js +26 -0
  572. package/build/dist/Server/Services/UserPushService.js.map +1 -1
  573. package/build/dist/Server/Services/UserService.js +10 -0
  574. package/build/dist/Server/Services/UserService.js.map +1 -1
  575. package/build/dist/Server/Services/UserSmsService.js +24 -1
  576. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  577. package/build/dist/Server/Services/UserTelegramService.js +22 -1
  578. package/build/dist/Server/Services/UserTelegramService.js.map +1 -1
  579. package/build/dist/Server/Services/UserWebhookService.js +25 -1
  580. package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
  581. package/build/dist/Server/Services/UserWhatsAppService.js +22 -1
  582. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
  583. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +12 -1
  584. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  585. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +126 -0
  586. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  587. package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js +254 -0
  588. package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js.map +1 -0
  589. package/build/dist/Server/Types/Database/Permissions/QueryPermission.js +47 -2
  590. package/build/dist/Server/Types/Database/Permissions/QueryPermission.js.map +1 -1
  591. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +7 -0
  592. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
  593. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +1 -1
  594. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  595. package/build/dist/Server/Types/Workflow/Components/API/Get.js +1 -1
  596. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  597. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +1 -1
  598. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  599. package/build/dist/Server/Types/Workflow/Components/API/Post.js +1 -1
  600. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  601. package/build/dist/Server/Types/Workflow/Components/API/Put.js +1 -1
  602. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  603. package/build/dist/Server/Types/Workflow/Components/API/Utils.js +28 -0
  604. package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
  605. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +21 -5
  606. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
  607. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +14 -10
  608. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
  609. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +31 -0
  610. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -1
  611. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +3 -9
  612. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
  613. package/build/dist/Server/Types/Workflow/Components/Email.js +15 -4
  614. package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
  615. package/build/dist/Server/Types/Workflow/Components/JavaScript.js +7 -2
  616. package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
  617. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +1 -1
  618. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
  619. package/build/dist/Server/Types/Workflow/TriggerCode.js.map +1 -1
  620. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +514 -56
  621. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  622. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +20 -3
  623. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  624. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +19 -6
  625. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  626. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +7 -0
  627. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  628. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js +2 -2
  629. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -1
  630. package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js +692 -0
  631. package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js.map +1 -0
  632. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +148 -12
  633. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
  634. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +157 -10
  635. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
  636. package/build/dist/Server/Utils/AI/Toolbox/Index.js +37 -0
  637. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  638. package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js +259 -14
  639. package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js.map +1 -1
  640. package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js +235 -0
  641. package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js.map +1 -0
  642. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +1000 -0
  643. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -0
  644. package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js +356 -0
  645. package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js.map +1 -0
  646. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +394 -0
  647. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -0
  648. package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js +465 -0
  649. package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js.map +1 -0
  650. package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js +280 -0
  651. package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js.map +1 -0
  652. package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +527 -0
  653. package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -0
  654. package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js +548 -0
  655. package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js.map +1 -0
  656. package/build/dist/Server/Utils/ClientIp.js +137 -0
  657. package/build/dist/Server/Utils/ClientIp.js.map +1 -0
  658. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +38 -0
  659. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
  660. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +89 -0
  661. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -0
  662. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +77 -0
  663. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -0
  664. package/build/dist/Server/Utils/Express.js +12 -12
  665. package/build/dist/Server/Utils/Express.js.map +1 -1
  666. package/build/dist/Server/Utils/LLM/LLMService.js +70 -7
  667. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  668. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +121 -11
  669. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  670. package/build/dist/Server/Utils/SSRFProtection.js +82 -21
  671. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  672. package/build/dist/Server/Utils/StartServer.js +12 -4
  673. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  674. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +165 -18
  675. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  676. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +507 -0
  677. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -0
  678. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +122 -47
  679. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  680. package/build/dist/Server/Utils/VM/VMAPI.js +51 -4
  681. package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
  682. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +7 -3
  683. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  684. package/build/dist/Types/AI/AIChatMessageStatus.js +8 -1
  685. package/build/dist/Types/AI/AIChatMessageStatus.js.map +1 -1
  686. package/build/dist/Types/AI/AIChatTypes.js +12 -0
  687. package/build/dist/Types/AI/AIChatTypes.js.map +1 -1
  688. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +60 -0
  689. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -0
  690. package/build/dist/Types/Exception/ExceptionCode.js +2 -0
  691. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  692. package/build/dist/Types/Exception/ServiceUnavailableException.js +8 -0
  693. package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -0
  694. package/build/dist/Types/Exception/TooManyRequestsException.js +8 -0
  695. package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -0
  696. package/build/dist/Types/IP/IP.js +87 -43
  697. package/build/dist/Types/IP/IP.js.map +1 -1
  698. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +50 -0
  699. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -0
  700. package/build/dist/Types/OnCallDutyPolicy/Layer.js +186 -123
  701. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  702. package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js +13 -0
  703. package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js.map +1 -1
  704. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +105 -11
  705. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
  706. package/build/dist/Types/Permission.js +174 -0
  707. package/build/dist/Types/Permission.js.map +1 -1
  708. package/build/dist/Types/SerializableObjectDictionary.js +133 -39
  709. package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
  710. package/build/dist/Types/Telemetry/EntityRelationshipType.js +1 -1
  711. package/build/dist/Types/Telemetry/EntitySource.js +39 -0
  712. package/build/dist/Types/Telemetry/EntitySource.js.map +1 -0
  713. package/build/dist/Types/Telemetry/EntityType.js +28 -1
  714. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  715. package/build/dist/Types/Telemetry/EntityTypeGroups.js +57 -0
  716. package/build/dist/Types/Telemetry/EntityTypeGroups.js.map +1 -0
  717. package/build/dist/Types/Workflow/Component.js +21 -0
  718. package/build/dist/Types/Workflow/Component.js.map +1 -1
  719. package/build/dist/Types/Workflow/Components/API.js +35 -0
  720. package/build/dist/Types/Workflow/Components/API.js.map +1 -1
  721. package/build/dist/Types/Workflow/Components/BaseModel.js +68 -26
  722. package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
  723. package/build/dist/Types/Workflow/Components/Discord.js +1 -0
  724. package/build/dist/Types/Workflow/Components/Discord.js.map +1 -1
  725. package/build/dist/Types/Workflow/Components/Email.js +12 -3
  726. package/build/dist/Types/Workflow/Components/Email.js.map +1 -1
  727. package/build/dist/Types/Workflow/Components/JavaScript.js +7 -0
  728. package/build/dist/Types/Workflow/Components/JavaScript.js.map +1 -1
  729. package/build/dist/Types/Workflow/Components/MicrosoftTeams.js +3 -2
  730. package/build/dist/Types/Workflow/Components/MicrosoftTeams.js.map +1 -1
  731. package/build/dist/Types/Workflow/Components/Slack.js +1 -0
  732. package/build/dist/Types/Workflow/Components/Slack.js.map +1 -1
  733. package/build/dist/Types/Workflow/Components/Telegram.js +1 -0
  734. package/build/dist/Types/Workflow/Components/Telegram.js.map +1 -1
  735. package/build/dist/Types/Workflow/StepTrace.js +104 -0
  736. package/build/dist/Types/Workflow/StepTrace.js.map +1 -0
  737. package/build/dist/Types/Workflow/TemplateSyntax.js +338 -0
  738. package/build/dist/Types/Workflow/TemplateSyntax.js.map +1 -0
  739. package/build/dist/Types/Workflow/Templates.js +2111 -0
  740. package/build/dist/Types/Workflow/Templates.js.map +1 -0
  741. package/build/dist/UI/Components/Calendar/Calendar.js +1 -1
  742. package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
  743. package/build/dist/UI/Components/Checkbox/Checkbox.js +1 -1
  744. package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
  745. package/build/dist/UI/Components/Date/CustomTimeRangeModal.js +126 -0
  746. package/build/dist/UI/Components/Date/CustomTimeRangeModal.js.map +1 -0
  747. package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js +123 -0
  748. package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js.map +1 -0
  749. package/build/dist/UI/Components/Dictionary/Dictionary.js +47 -17
  750. package/build/dist/UI/Components/Dictionary/Dictionary.js.map +1 -1
  751. package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
  752. package/build/dist/UI/Components/Forms/Fields/ColorPicker.js +52 -13
  753. package/build/dist/UI/Components/Forms/Fields/ColorPicker.js.map +1 -1
  754. package/build/dist/UI/Components/Forms/Fields/IconPicker.js +28 -12
  755. package/build/dist/UI/Components/Forms/Fields/IconPicker.js.map +1 -1
  756. package/build/dist/UI/Components/Forms/Validation.js +44 -0
  757. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  758. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +27 -4
  759. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  760. package/build/dist/UI/Components/Input/Input.js +13 -4
  761. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  762. package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js +163 -0
  763. package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js.map +1 -0
  764. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js +47 -0
  765. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js.map +1 -0
  766. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +4 -4
  767. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  768. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +11 -1
  769. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
  770. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js +10 -8
  771. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js.map +1 -1
  772. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +227 -14
  773. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
  774. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +5 -108
  775. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
  776. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +5 -0
  777. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  778. package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +69 -5
  779. package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
  780. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +8 -0
  781. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  782. package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
  783. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +9 -2
  784. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
  785. package/build/dist/UI/Components/Modal/Modal.js +31 -5
  786. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  787. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +8 -21
  788. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  789. package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js +251 -0
  790. package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js.map +1 -0
  791. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js +9 -2
  792. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js.map +1 -1
  793. package/build/dist/UI/Components/Table/Table.js +27 -15
  794. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  795. package/build/dist/UI/Components/Table/TableBody.js +24 -18
  796. package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
  797. package/build/dist/UI/Components/Table/TableHeader.js +9 -1
  798. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  799. package/build/dist/UI/Components/Table/TableRow.js +29 -21
  800. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  801. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +5 -105
  802. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
  803. package/build/dist/UI/Components/Workflow/ArgumentsForm.js +261 -14
  804. package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
  805. package/build/dist/UI/Components/Workflow/Component.js +20 -19
  806. package/build/dist/UI/Components/Workflow/Component.js.map +1 -1
  807. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +10 -1
  808. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
  809. package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +35 -7
  810. package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
  811. package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js +57 -7
  812. package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js.map +1 -1
  813. package/build/dist/UI/Components/Workflow/ComponentsModal.js +53 -18
  814. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  815. package/build/dist/UI/Components/Workflow/DocumentationViewer.js +19 -6
  816. package/build/dist/UI/Components/Workflow/DocumentationViewer.js.map +1 -1
  817. package/build/dist/UI/Components/Workflow/GraphLint.js +425 -0
  818. package/build/dist/UI/Components/Workflow/GraphLint.js.map +1 -0
  819. package/build/dist/UI/Components/Workflow/GraphLintSummary.js +231 -0
  820. package/build/dist/UI/Components/Workflow/GraphLintSummary.js.map +1 -0
  821. package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +320 -0
  822. package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -0
  823. package/build/dist/UI/Components/Workflow/ModelSchema.js +156 -0
  824. package/build/dist/UI/Components/Workflow/ModelSchema.js.map +1 -0
  825. package/build/dist/UI/Components/Workflow/RunForm.js +22 -6
  826. package/build/dist/UI/Components/Workflow/RunForm.js.map +1 -1
  827. package/build/dist/UI/Components/Workflow/RunStatusWatcher.js +76 -0
  828. package/build/dist/UI/Components/Workflow/RunStatusWatcher.js.map +1 -0
  829. package/build/dist/UI/Components/Workflow/StepTraceViewer.js +76 -0
  830. package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -0
  831. package/build/dist/UI/Components/Workflow/UseRunWatch.js +123 -0
  832. package/build/dist/UI/Components/Workflow/UseRunWatch.js.map +1 -0
  833. package/build/dist/UI/Components/Workflow/Utils.js +73 -1
  834. package/build/dist/UI/Components/Workflow/Utils.js.map +1 -1
  835. package/build/dist/UI/Components/Workflow/VariableModal.js +3 -2
  836. package/build/dist/UI/Components/Workflow/VariableModal.js.map +1 -1
  837. package/build/dist/UI/Components/Workflow/Workflow.js +92 -7
  838. package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
  839. package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js +99 -0
  840. package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js.map +1 -0
  841. package/build/dist/UI/Components/Workflow/WorkflowLogModal.js +56 -0
  842. package/build/dist/UI/Components/Workflow/WorkflowLogModal.js.map +1 -0
  843. package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js +92 -0
  844. package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js.map +1 -0
  845. package/build/dist/UI/Types/LayeredDismissal.js +21 -0
  846. package/build/dist/UI/Types/LayeredDismissal.js.map +1 -0
  847. package/build/dist/UI/Types/UseAnchoredFieldPopup.js +74 -1
  848. package/build/dist/UI/Types/UseAnchoredFieldPopup.js.map +1 -1
  849. package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js +9 -0
  850. package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js.map +1 -1
  851. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +1 -1
  852. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  853. package/build/dist/UI/Utils/Platform.js +118 -0
  854. package/build/dist/UI/Utils/Platform.js.map +1 -0
  855. package/build/dist/UI/Utils/ProjectInvitationDisplay.js +106 -0
  856. package/build/dist/UI/Utils/ProjectInvitationDisplay.js.map +1 -0
  857. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +108 -0
  858. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -0
  859. package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +386 -0
  860. package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -0
  861. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +661 -126
  862. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  863. package/build/dist/Utils/Telemetry/CrossSignalScope.js +328 -0
  864. package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -0
  865. package/build/dist/Utils/Telemetry/EntityKey.js +57 -5
  866. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  867. package/build/dist/Utils/Telemetry/EntityRelationship.js +1 -1
  868. package/jest.config.json +1 -0
  869. package/package.json +1 -1
  870. package/build/dist/Models/DatabaseModels/TelemetryEntity.js.map +0 -1
  871. package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js.map +0 -1
  872. package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +0 -1
  873. package/build/dist/Server/Services/TelemetryEntityService.js.map +0 -1
@@ -0,0 +1,1468 @@
1
+ import UserNotificationRuleService from "../../../Server/Services/UserNotificationRuleService";
2
+ import UserOnCallLogService from "../../../Server/Services/UserOnCallLogService";
3
+ import UserOnCallLogTimelineService from "../../../Server/Services/UserOnCallLogTimelineService";
4
+ import ProjectCallSMSConfigService from "../../../Server/Services/ProjectCallSMSConfigService";
5
+ import IncidentService from "../../../Server/Services/IncidentService";
6
+ import AlertService from "../../../Server/Services/AlertService";
7
+ import AlertEpisodeService from "../../../Server/Services/AlertEpisodeService";
8
+ import IncidentEpisodeService from "../../../Server/Services/IncidentEpisodeService";
9
+ import MailService from "../../../Server/Services/MailService";
10
+ import SmsService from "../../../Server/Services/SmsService";
11
+ import CallService from "../../../Server/Services/CallService";
12
+ import WhatsAppService from "../../../Server/Services/WhatsAppService";
13
+ import TelegramService from "../../../Server/Services/TelegramService";
14
+ import WebhookService from "../../../Server/Services/WebhookService";
15
+ import PushNotificationService from "../../../Server/Services/PushNotificationService";
16
+ import WorkspaceNotificationRuleService from "../../../Server/Services/WorkspaceNotificationRuleService";
17
+ import logger from "../../../Server/Utils/Logger";
18
+ import Incident from "../../../Models/DatabaseModels/Incident";
19
+ import Alert from "../../../Models/DatabaseModels/Alert";
20
+ import UserOnCallLog from "../../../Models/DatabaseModels/UserOnCallLog";
21
+ import UserOnCallLogTimeline from "../../../Models/DatabaseModels/UserOnCallLogTimeline";
22
+ import UserNotificationRule from "../../../Models/DatabaseModels/UserNotificationRule";
23
+ import BadDataException from "../../../Types/Exception/BadDataException";
24
+ import Email from "../../../Types/Email";
25
+ import Phone from "../../../Types/Phone";
26
+ import ObjectID from "../../../Types/ObjectID";
27
+ import { JSONObject } from "../../../Types/JSON";
28
+ import EmailMessage from "../../../Types/Email/EmailMessage";
29
+ import UserNotificationEventType from "../../../Types/UserNotification/UserNotificationEventType";
30
+ import UserNotificationExecutionStatus from "../../../Types/UserNotification/UserNotificationExecutionStatus";
31
+ import UserNotificationStatus from "../../../Types/UserNotification/UserNotificationStatus";
32
+ import NotificationRuleEventType from "../../../Types/Workspace/NotificationRules/EventType";
33
+ import { describe, expect, test, beforeEach, afterEach } from "@jest/globals";
34
+
35
+ /*
36
+ * `executeNotificationRuleItem` is the last mile of the on-call system: by the
37
+ * time control reaches it, an incident has fired, a policy has escalated, a
38
+ * responder has been chosen, and a delay has elapsed. Everything that happens
39
+ * inside decides whether a human's phone actually rings. Three things in it are
40
+ * load-bearing and easy to break by accident, so they are pinned here:
41
+ *
42
+ * 1. THE CLAIM GATE. The very first statement is an atomic claim
43
+ * (`UserOnCallLogService.claimNotificationRuleExecution`, audit F7). When
44
+ * the claim is lost, the function must return *before* it reads anything
45
+ * and before any send happens — that is what stops two overlapping cron
46
+ * ticks from double-paging one responder for one escalation. A refactor
47
+ * that moved the rule lookup above the gate, or that treated `false` as
48
+ * "keep going", would silently reintroduce duplicate pages, so we assert
49
+ * not just "nothing was sent" but "findOneById was never even called" and
50
+ * that the claim strictly precedes the read.
51
+ *
52
+ * 2. THE SELECT CONTRACT. Every channel is verification-gated at send time
53
+ * (`userEmail?.email && userEmail?.isVerified`). Those gates are only as
54
+ * good as the `select` that hydrates them: an unselected `isVerified`
55
+ * arrives as `undefined`, which is falsy, so dropping it would not page
56
+ * unverified methods — it would *silence every verified one* and write a
57
+ * "not verified" error row for a phone that is perfectly verified. The
58
+ * exact select shape is therefore asserted field by field, together with
59
+ * the verified/unverified behaviour it drives.
60
+ *
61
+ * 3. THE SCHEDULING ENTRYPOINT. `startUserNotificationRulesExecution` writes
62
+ * the `UserOnCallLog` row that the ExecutePendingExecutions worker later
63
+ * picks up. Every option it is handed has to land on that row (a dropped
64
+ * `onCallDutyPolicyExecutionLogTimelineId` means the timeline never
65
+ * reconciles), the row must be `Scheduled`/"Scheduled" so the worker picks
66
+ * it up at all, and its fire-and-forget workspace-invite call must never
67
+ * be able to take the scheduling down with it.
68
+ *
69
+ * Nothing here touches a database and no template rendering is exercised — the
70
+ * senders and generators are stubbed. This file pins CONTROL FLOW and CONTRACTS,
71
+ * which is precisely what a later refactor of this 1700-line method will break.
72
+ */
73
+
74
+ const PROJECT_ID: ObjectID = new ObjectID(
75
+ "11111111-1111-4111-8111-111111111111",
76
+ );
77
+ const RULE_ID: ObjectID = new ObjectID("22222222-2222-4222-8222-222222222222");
78
+ const LOG_ID: ObjectID = new ObjectID("33333333-3333-4333-8333-333333333333");
79
+ const USER_ID: ObjectID = new ObjectID("44444444-4444-4444-8444-444444444444");
80
+ const INCIDENT_ID: ObjectID = new ObjectID(
81
+ "55555555-5555-4555-8555-555555555555",
82
+ );
83
+ const ALERT_ID: ObjectID = new ObjectID("66666666-6666-4666-8666-666666666666");
84
+ const TEAM_ID: ObjectID = new ObjectID("77777777-7777-4777-8777-777777777777");
85
+ const POLICY_ID: ObjectID = new ObjectID(
86
+ "88888888-8888-4888-8888-888888888888",
87
+ );
88
+ const ESCALATION_RULE_ID: ObjectID = new ObjectID(
89
+ "99999999-9999-4999-8999-999999999999",
90
+ );
91
+ const EXECUTION_LOG_ID: ObjectID = new ObjectID(
92
+ "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
93
+ );
94
+ const EXECUTION_LOG_TIMELINE_ID: ObjectID = new ObjectID(
95
+ "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
96
+ );
97
+ const SCHEDULE_ID: ObjectID = new ObjectID(
98
+ "cccccccc-cccc-4ccc-8ccc-cccccccccccc",
99
+ );
100
+ const TIMELINE_ID: ObjectID = new ObjectID(
101
+ "dddddddd-dddd-4ddd-8ddd-dddddddddddd",
102
+ );
103
+ const ALERT_EPISODE_ID: ObjectID = new ObjectID(
104
+ "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee",
105
+ );
106
+ const INCIDENT_EPISODE_ID: ObjectID = new ObjectID(
107
+ "ffffffff-ffff-4fff-8fff-ffffffffffff",
108
+ );
109
+ const OVERRIDE_USER_ID: ObjectID = new ObjectID(
110
+ "12121212-1212-4212-8212-121212121212",
111
+ );
112
+ const METHOD_ID: ObjectID = new ObjectID(
113
+ "13131313-1313-4313-8313-131313131313",
114
+ );
115
+
116
+ type ExecuteOptions = Parameters<
117
+ typeof UserNotificationRuleService.executeNotificationRuleItem
118
+ >[1];
119
+
120
+ type StartOptions = Parameters<
121
+ typeof UserNotificationRuleService.startUserNotificationRulesExecution
122
+ >[1];
123
+
124
+ /* The `select` / `props` bundle handed to findOneById. */
125
+ interface FindOneByIdArg {
126
+ id: ObjectID;
127
+ select: JSONObject;
128
+ props: { isRoot: boolean };
129
+ }
130
+
131
+ /*
132
+ * The service mutates ONE UserOnCallLogTimeline instance and passes that same
133
+ * instance to create() over and over, so mock.calls all alias the final state.
134
+ * We snapshot the fields we care about at call time instead.
135
+ */
136
+ interface TimelineRow {
137
+ status: UserNotificationStatus | undefined;
138
+ statusMessage: string | undefined;
139
+ userId: ObjectID | undefined;
140
+ userNotificationRuleId: ObjectID | undefined;
141
+ userNotificationLogId: ObjectID | undefined;
142
+ projectId: ObjectID | undefined;
143
+ }
144
+
145
+ function flushMicrotasks(): Promise<void> {
146
+ return Promise.resolve()
147
+ .then((): Promise<void> => {
148
+ return Promise.resolve();
149
+ })
150
+ .then((): Promise<void> => {
151
+ return Promise.resolve();
152
+ });
153
+ }
154
+
155
+ function executeOptions(
156
+ overrides: Partial<ExecuteOptions> = {},
157
+ ): ExecuteOptions {
158
+ return {
159
+ projectId: PROJECT_ID,
160
+ userNotificationEventType: UserNotificationEventType.IncidentCreated,
161
+ triggeredByIncidentId: INCIDENT_ID,
162
+ onCallPolicyId: POLICY_ID,
163
+ userNotificationLogId: LOG_ID,
164
+ ...overrides,
165
+ };
166
+ }
167
+
168
+ function ruleItem(channels: JSONObject = {}): UserNotificationRule {
169
+ return {
170
+ id: RULE_ID,
171
+ _id: RULE_ID.toString(),
172
+ userId: USER_ID,
173
+ ...channels,
174
+ } as unknown as UserNotificationRule;
175
+ }
176
+
177
+ function fakeIncident(): Incident {
178
+ return {
179
+ id: INCIDENT_ID,
180
+ projectId: PROJECT_ID,
181
+ title: "Checkout is down",
182
+ description: "Checkout returns 500 for every request.",
183
+ incidentNumber: 42,
184
+ incidentNumberWithPrefix: "INC-42",
185
+ } as unknown as Incident;
186
+ }
187
+
188
+ function fakeAlert(): Alert {
189
+ return {
190
+ id: ALERT_ID,
191
+ projectId: PROJECT_ID,
192
+ title: "Disk almost full",
193
+ description: "94% used on node-3.",
194
+ alertNumber: 7,
195
+ alertNumberWithPrefix: "ALR-7",
196
+ } as unknown as Alert;
197
+ }
198
+
199
+ /* Every stub the delivery path touches, so no test can reach a real service. */
200
+ interface DeliverySpies {
201
+ claim: jest.SpyInstance;
202
+ findRule: jest.SpyInstance;
203
+ twilio: jest.SpyInstance;
204
+ timelineCreate: jest.SpyInstance;
205
+ timelineUpdate: jest.SpyInstance;
206
+ incidentFind: jest.SpyInstance;
207
+ alertFind: jest.SpyInstance;
208
+ alertEpisodeFind: jest.SpyInstance;
209
+ incidentEpisodeFind: jest.SpyInstance;
210
+ mail: jest.SpyInstance;
211
+ sms: jest.SpyInstance;
212
+ call: jest.SpyInstance;
213
+ whatsApp: jest.SpyInstance;
214
+ telegram: jest.SpyInstance;
215
+ webhook: jest.SpyInstance;
216
+ push: jest.SpyInstance;
217
+ emailTemplateForIncident: jest.SpyInstance;
218
+ }
219
+
220
+ describe("UserNotificationRuleService.executeNotificationRuleItem", () => {
221
+ let spies: DeliverySpies;
222
+ let timelineRows: Array<TimelineRow>;
223
+
224
+ beforeEach(() => {
225
+ timelineRows = [];
226
+
227
+ jest.spyOn(logger, "error").mockImplementation((): void => {
228
+ return undefined;
229
+ });
230
+
231
+ const timelineCreate: jest.SpyInstance = jest.spyOn(
232
+ UserOnCallLogTimelineService,
233
+ "create",
234
+ );
235
+ timelineCreate.mockImplementation(
236
+ (createBy: unknown): Promise<UserOnCallLogTimeline> => {
237
+ const data: UserOnCallLogTimeline = (
238
+ createBy as { data: UserOnCallLogTimeline }
239
+ ).data;
240
+
241
+ timelineRows.push({
242
+ status: data.status,
243
+ statusMessage: data.statusMessage,
244
+ userId: data.userId,
245
+ userNotificationRuleId: data.userNotificationRuleId,
246
+ userNotificationLogId: data.userNotificationLogId,
247
+ projectId: data.projectId,
248
+ });
249
+
250
+ return Promise.resolve({
251
+ id: TIMELINE_ID,
252
+ } as unknown as UserOnCallLogTimeline);
253
+ },
254
+ );
255
+
256
+ spies = {
257
+ claim: jest
258
+ .spyOn(UserOnCallLogService, "claimNotificationRuleExecution")
259
+ .mockResolvedValue(true as never),
260
+ findRule: jest
261
+ .spyOn(UserNotificationRuleService, "findOneById")
262
+ .mockResolvedValue(ruleItem() as never),
263
+ twilio: jest
264
+ .spyOn(ProjectCallSMSConfigService, "getProjectDefaultTwilioConfig")
265
+ .mockResolvedValue(undefined as never),
266
+ timelineCreate: timelineCreate,
267
+ timelineUpdate: jest
268
+ .spyOn(UserOnCallLogTimelineService, "updateOneById")
269
+ .mockResolvedValue(undefined as never),
270
+ incidentFind: jest
271
+ .spyOn(IncidentService, "findOneById")
272
+ .mockResolvedValue(fakeIncident() as never),
273
+ alertFind: jest
274
+ .spyOn(AlertService, "findOneById")
275
+ .mockResolvedValue(fakeAlert() as never),
276
+ alertEpisodeFind: jest
277
+ .spyOn(AlertEpisodeService, "findOneById")
278
+ .mockResolvedValue(null as never),
279
+ incidentEpisodeFind: jest
280
+ .spyOn(IncidentEpisodeService, "findOneById")
281
+ .mockResolvedValue(null as never),
282
+ mail: jest
283
+ .spyOn(MailService, "sendMail")
284
+ .mockResolvedValue(undefined as never),
285
+ sms: jest
286
+ .spyOn(SmsService, "sendSms")
287
+ .mockResolvedValue(undefined as never),
288
+ call: jest
289
+ .spyOn(CallService, "makeCall")
290
+ .mockResolvedValue(undefined as never),
291
+ whatsApp: jest
292
+ .spyOn(WhatsAppService, "sendWhatsAppMessage")
293
+ .mockResolvedValue(undefined as never),
294
+ telegram: jest
295
+ .spyOn(TelegramService, "sendTelegramMessage")
296
+ .mockResolvedValue(undefined as never),
297
+ webhook: jest
298
+ .spyOn(WebhookService, "sendWebhook")
299
+ .mockResolvedValue(undefined as never),
300
+ push: jest
301
+ .spyOn(PushNotificationService, "sendPushNotification")
302
+ .mockResolvedValue(undefined as never),
303
+ emailTemplateForIncident: jest
304
+ .spyOn(
305
+ UserNotificationRuleService,
306
+ "generateEmailTemplateForIncidentCreated",
307
+ )
308
+ .mockResolvedValue({} as EmailMessage as never),
309
+ };
310
+ });
311
+
312
+ afterEach(() => {
313
+ jest.restoreAllMocks();
314
+ });
315
+
316
+ function everySender(): Array<jest.SpyInstance> {
317
+ return [
318
+ spies.mail,
319
+ spies.sms,
320
+ spies.call,
321
+ spies.whatsApp,
322
+ spies.telegram,
323
+ spies.webhook,
324
+ spies.push,
325
+ ];
326
+ }
327
+
328
+ /*
329
+ * ----------------------------------------------------------------------- *
330
+ * (A) The atomic claim gate.
331
+ * -----------------------------------------------------------------------
332
+ */
333
+
334
+ describe("the atomic claim gate runs first and is decisive", () => {
335
+ test("claim resolving FALSE returns immediately - findOneById is never called", async () => {
336
+ spies.claim.mockResolvedValue(false as never);
337
+
338
+ await UserNotificationRuleService.executeNotificationRuleItem(
339
+ RULE_ID,
340
+ executeOptions(),
341
+ );
342
+
343
+ expect(spies.claim).toHaveBeenCalledTimes(1);
344
+ /*
345
+ * The whole point of F7: a lost claim must short-circuit BEFORE the read,
346
+ * not merely before the send.
347
+ */
348
+ expect(spies.findRule).not.toHaveBeenCalled();
349
+ });
350
+
351
+ test("claim resolving FALSE sends nothing on any channel and writes no timeline row", async () => {
352
+ spies.claim.mockResolvedValue(false as never);
353
+
354
+ await UserNotificationRuleService.executeNotificationRuleItem(
355
+ RULE_ID,
356
+ executeOptions(),
357
+ );
358
+
359
+ for (const sender of everySender()) {
360
+ expect(sender).not.toHaveBeenCalled();
361
+ }
362
+ expect(spies.timelineCreate).not.toHaveBeenCalled();
363
+ expect(spies.timelineUpdate).not.toHaveBeenCalled();
364
+ });
365
+
366
+ test("claim resolving FALSE also skips the incident/alert lookups and the Twilio config read", async () => {
367
+ spies.claim.mockResolvedValue(false as never);
368
+
369
+ await UserNotificationRuleService.executeNotificationRuleItem(
370
+ RULE_ID,
371
+ executeOptions(),
372
+ );
373
+
374
+ expect(spies.twilio).not.toHaveBeenCalled();
375
+ expect(spies.incidentFind).not.toHaveBeenCalled();
376
+ expect(spies.alertFind).not.toHaveBeenCalled();
377
+ });
378
+
379
+ test("a lost claim resolves (does NOT throw) so the worker does not mark the log Error", async () => {
380
+ spies.claim.mockResolvedValue(false as never);
381
+
382
+ /*
383
+ * ExecutePendingExecutions marks a log `Error` on BadDataException. A
384
+ * duplicate-suppressed rule is a normal outcome, not bad data, so this
385
+ * path must resolve quietly.
386
+ */
387
+ await expect(
388
+ UserNotificationRuleService.executeNotificationRuleItem(
389
+ RULE_ID,
390
+ executeOptions(),
391
+ ),
392
+ ).resolves.toBeUndefined();
393
+ });
394
+
395
+ test("the claim is made for exactly this on-call log and this rule", async () => {
396
+ spies.claim.mockResolvedValue(false as never);
397
+
398
+ await UserNotificationRuleService.executeNotificationRuleItem(
399
+ RULE_ID,
400
+ executeOptions({ userNotificationLogId: LOG_ID }),
401
+ );
402
+
403
+ const claimArg: {
404
+ userOnCallLogId: ObjectID;
405
+ userNotificationRuleId: ObjectID;
406
+ } = spies.claim.mock.calls[0][0] as {
407
+ userOnCallLogId: ObjectID;
408
+ userNotificationRuleId: ObjectID;
409
+ };
410
+ expect(claimArg.userOnCallLogId.toString()).toBe(LOG_ID.toString());
411
+ expect(claimArg.userNotificationRuleId.toString()).toBe(
412
+ RULE_ID.toString(),
413
+ );
414
+ });
415
+
416
+ test("claim resolving TRUE lets execution proceed to the rule lookup", async () => {
417
+ spies.claim.mockResolvedValue(true as never);
418
+
419
+ await UserNotificationRuleService.executeNotificationRuleItem(
420
+ RULE_ID,
421
+ executeOptions(),
422
+ );
423
+
424
+ expect(spies.findRule).toHaveBeenCalledTimes(1);
425
+ });
426
+
427
+ test("the claim strictly PRECEDES the rule lookup (ordering, not just presence)", async () => {
428
+ await UserNotificationRuleService.executeNotificationRuleItem(
429
+ RULE_ID,
430
+ executeOptions(),
431
+ );
432
+
433
+ expect(spies.claim.mock.invocationCallOrder[0]).toBeLessThan(
434
+ spies.findRule.mock.invocationCallOrder[0] as number,
435
+ );
436
+ });
437
+
438
+ test("a claim that rejects propagates - the page is NOT attempted on an unknown claim state", async () => {
439
+ spies.claim.mockRejectedValue(new Error("db connection reset") as never);
440
+
441
+ await expect(
442
+ UserNotificationRuleService.executeNotificationRuleItem(
443
+ RULE_ID,
444
+ executeOptions(),
445
+ ),
446
+ ).rejects.toThrow("db connection reset");
447
+
448
+ expect(spies.findRule).not.toHaveBeenCalled();
449
+ for (const sender of everySender()) {
450
+ expect(sender).not.toHaveBeenCalled();
451
+ }
452
+ });
453
+ });
454
+
455
+ /*
456
+ * ----------------------------------------------------------------------- *
457
+ * (B) A rule id that resolves to nothing.
458
+ * -----------------------------------------------------------------------
459
+ */
460
+
461
+ describe("a rule id that resolves to nothing", () => {
462
+ test('throws BadDataException("Notification rule item not found.")', async () => {
463
+ spies.findRule.mockResolvedValue(null as never);
464
+
465
+ await expect(
466
+ UserNotificationRuleService.executeNotificationRuleItem(
467
+ RULE_ID,
468
+ executeOptions(),
469
+ ),
470
+ ).rejects.toThrow(BadDataException);
471
+
472
+ await expect(
473
+ UserNotificationRuleService.executeNotificationRuleItem(
474
+ RULE_ID,
475
+ executeOptions(),
476
+ ),
477
+ ).rejects.toThrow("Notification rule item not found.");
478
+ });
479
+
480
+ test("the throw happens before the Twilio config and incident lookups", async () => {
481
+ spies.findRule.mockResolvedValue(null as never);
482
+
483
+ await expect(
484
+ UserNotificationRuleService.executeNotificationRuleItem(
485
+ RULE_ID,
486
+ executeOptions(),
487
+ ),
488
+ ).rejects.toThrow(BadDataException);
489
+
490
+ expect(spies.twilio).not.toHaveBeenCalled();
491
+ expect(spies.incidentFind).not.toHaveBeenCalled();
492
+ expect(spies.timelineCreate).not.toHaveBeenCalled();
493
+ });
494
+
495
+ test("nothing is sent when the rule is missing", async () => {
496
+ spies.findRule.mockResolvedValue(null as never);
497
+
498
+ await expect(
499
+ UserNotificationRuleService.executeNotificationRuleItem(
500
+ RULE_ID,
501
+ executeOptions(),
502
+ ),
503
+ ).rejects.toThrow(BadDataException);
504
+
505
+ for (const sender of everySender()) {
506
+ expect(sender).not.toHaveBeenCalled();
507
+ }
508
+ });
509
+
510
+ test("the claim has ALREADY been consumed when the rule turns out to be missing", async () => {
511
+ spies.findRule.mockResolvedValue(null as never);
512
+
513
+ await expect(
514
+ UserNotificationRuleService.executeNotificationRuleItem(
515
+ RULE_ID,
516
+ executeOptions(),
517
+ ),
518
+ ).rejects.toThrow(BadDataException);
519
+
520
+ /*
521
+ * Current behaviour, worth knowing: the claim is written before the rule
522
+ * is read, so a rule deleted between scheduling and execution burns its
523
+ * claim and is never retried by a later tick. That is deliberate (a
524
+ * missing rule is permanent), but it means the claim is not released on
525
+ * failure.
526
+ */
527
+ expect(spies.claim).toHaveBeenCalledTimes(1);
528
+ });
529
+ });
530
+
531
+ /*
532
+ * ----------------------------------------------------------------------- *
533
+ * (C) The select contract that the verification gates depend on.
534
+ * -----------------------------------------------------------------------
535
+ */
536
+
537
+ describe("the select handed to findOneById", () => {
538
+ async function captureFindArg(): Promise<FindOneByIdArg> {
539
+ await UserNotificationRuleService.executeNotificationRuleItem(
540
+ RULE_ID,
541
+ executeOptions(),
542
+ );
543
+
544
+ return spies.findRule.mock.calls[0][0] as FindOneByIdArg;
545
+ }
546
+
547
+ test("targets the requested rule id, as root", async () => {
548
+ const arg: FindOneByIdArg = await captureFindArg();
549
+
550
+ expect(arg.id.toString()).toBe(RULE_ID.toString());
551
+ expect(arg.props.isRoot).toBe(true);
552
+ });
553
+
554
+ test("is EXACTLY this shape (a dropped field silently changes who gets paged)", async () => {
555
+ const arg: FindOneByIdArg = await captureFindArg();
556
+
557
+ /*
558
+ * WHY EACH RELATION ALSO ASKS FOR ITS OWN userId, WHICH NO SENDER READS.
559
+ *
560
+ * A rule is a pair of columns that nothing in the ORM ever compares: its
561
+ * `userId` decides WHOSE page this is, and the method relation decides
562
+ * WHERE that page is delivered. A row where those two name different
563
+ * people routes one person's pages to another person's address, and it is
564
+ * invisible from both ends - the rules page still lists a rule and the
565
+ * on-call log still records a delivered notification.
566
+ *
567
+ * The write-side guards refuse to SAVE such a row. This select is what
568
+ * lets executeNotificationRuleItem refuse to ACT ON one that exists
569
+ * anyway: written before those guards landed, written by internal code
570
+ * running as root, or written down a path a future change forgets to
571
+ * route through them. getNotificationMethodsNotOwnedByRuleOwner compares
572
+ * the loaded relation's userId against the rule's, and it can only report
573
+ * a mismatch it can SEE - an unselected column arrives as `undefined` and
574
+ * is deliberately read as "no evidence", so dropping any one of these
575
+ * seven silently disables the backstop for that channel.
576
+ *
577
+ * Kept as an exact-shape assertion on purpose. This test caught the
578
+ * column being added, which is the whole argument for not relaxing it
579
+ * into a partial match: the select is a contract about who gets paged,
580
+ * and every future edit to it should have to come through here.
581
+ */
582
+ expect(arg.select).toEqual({
583
+ _id: true,
584
+ userId: true,
585
+ userCall: {
586
+ phone: true,
587
+ isVerified: true,
588
+ userId: true,
589
+ },
590
+ userSms: {
591
+ phone: true,
592
+ isVerified: true,
593
+ userId: true,
594
+ },
595
+ userWhatsApp: {
596
+ phone: true,
597
+ isVerified: true,
598
+ userId: true,
599
+ },
600
+ userTelegram: {
601
+ telegramChatId: true,
602
+ telegramUserHandle: true,
603
+ isVerified: true,
604
+ userId: true,
605
+ },
606
+ userWebhook: {
607
+ webhookUrl: true,
608
+ name: true,
609
+ secret: true,
610
+ userId: true,
611
+ },
612
+ userEmail: {
613
+ email: true,
614
+ isVerified: true,
615
+ userId: true,
616
+ },
617
+ userPush: {
618
+ deviceToken: true,
619
+ deviceType: true,
620
+ isVerified: true,
621
+ userId: true,
622
+ },
623
+ });
624
+ });
625
+
626
+ test.each<[string]>([
627
+ ["userCall"],
628
+ ["userSms"],
629
+ ["userWhatsApp"],
630
+ ["userTelegram"],
631
+ ["userEmail"],
632
+ ["userPush"],
633
+ ])(
634
+ "%s requests isVerified - without it every verified method reads as unverified",
635
+ async (channel: string) => {
636
+ const arg: FindOneByIdArg = await captureFindArg();
637
+ const selected: JSONObject = arg.select[channel] as JSONObject;
638
+
639
+ expect(selected).toBeDefined();
640
+ expect(selected["isVerified"]).toBe(true);
641
+ },
642
+ );
643
+
644
+ test.each<[string, string]>([
645
+ ["userCall", "phone"],
646
+ ["userSms", "phone"],
647
+ ["userWhatsApp", "phone"],
648
+ ["userTelegram", "telegramChatId"],
649
+ ["userEmail", "email"],
650
+ ["userPush", "deviceToken"],
651
+ ])(
652
+ "%s also requests its address column (%s), which the send gate reads",
653
+ async (channel: string, addressColumn: string) => {
654
+ const arg: FindOneByIdArg = await captureFindArg();
655
+ const selected: JSONObject = arg.select[channel] as JSONObject;
656
+
657
+ expect(selected[addressColumn]).toBe(true);
658
+ },
659
+ );
660
+
661
+ test("userWebhook requests webhookUrl, name, secret - and its owner", async () => {
662
+ const arg: FindOneByIdArg = await captureFindArg();
663
+ const webhookSelect: JSONObject = arg.select["userWebhook"] as JSONObject;
664
+
665
+ /*
666
+ * `userId` is read by no part of the webhook send. It is the
667
+ * defence-in-depth column described on the exact-shape assertion above -
668
+ * the one the pre-delivery ownership check compares against the rule's
669
+ * own userId - and webhooks are the channel where a hijacked method
670
+ * matters most, because the attacker chooses the endpoint outright.
671
+ */
672
+ expect(webhookSelect).toEqual({
673
+ webhookUrl: true,
674
+ name: true,
675
+ secret: true,
676
+ userId: true,
677
+ });
678
+ });
679
+
680
+ test("userWebhook requests NO isVerified - the UserWebhook model has no such column", async () => {
681
+ const arg: FindOneByIdArg = await captureFindArg();
682
+ const webhookSelect: JSONObject = arg.select["userWebhook"] as JSONObject;
683
+
684
+ /*
685
+ * Pinned as-is: webhooks are the one user-contactable channel with no
686
+ * verification concept at all (UserWebhook has no isVerified column), so
687
+ * the delivery gate below is `webhookUrl` alone. If webhook verification
688
+ * is ever introduced, this select AND the gate both have to change.
689
+ */
690
+ expect(webhookSelect["isVerified"]).toBeUndefined();
691
+ });
692
+
693
+ test("userPush does NOT request deviceName even though the sender reads it", async () => {
694
+ const arg: FindOneByIdArg = await captureFindArg();
695
+ const pushSelect: JSONObject = arg.select["userPush"] as JSONObject;
696
+
697
+ /*
698
+ * KNOWN DEFECT (pinned as-is): the push send path reads
699
+ * `notificationRuleItem.userPush.deviceName` to label the device, but
700
+ * deviceName is not selected here, so it is always undefined and the
701
+ * `name` key is never spread onto the device payload. Harmless today
702
+ * (cosmetic label only) but it is a live select/consumer mismatch.
703
+ */
704
+ expect(pushSelect["deviceName"]).toBeUndefined();
705
+ expect(pushSelect["deviceToken"]).toBe(true);
706
+ expect(pushSelect["deviceType"]).toBe(true);
707
+ });
708
+
709
+ test("the rule is read exactly once per execution", async () => {
710
+ await captureFindArg();
711
+
712
+ expect(spies.findRule).toHaveBeenCalledTimes(1);
713
+ });
714
+ });
715
+
716
+ /*
717
+ * ----------------------------------------------------------------------- *
718
+ * (C continued) What the selected isVerified actually gates.
719
+ * -----------------------------------------------------------------------
720
+ */
721
+
722
+ describe("verification gating (what isVerified in the select buys)", () => {
723
+ test("a VERIFIED email is delivered and its timeline row is Sending", async () => {
724
+ spies.findRule.mockResolvedValue(
725
+ ruleItem({
726
+ userEmail: {
727
+ id: METHOD_ID,
728
+ email: new Email("responder@company.com"),
729
+ isVerified: true,
730
+ },
731
+ } as unknown as JSONObject) as never,
732
+ );
733
+
734
+ await UserNotificationRuleService.executeNotificationRuleItem(
735
+ RULE_ID,
736
+ executeOptions(),
737
+ );
738
+
739
+ expect(spies.mail).toHaveBeenCalledTimes(1);
740
+ expect(timelineRows).toHaveLength(1);
741
+ expect(timelineRows[0]?.status).toBe(UserNotificationStatus.Sending);
742
+ expect(timelineRows[0]?.statusMessage).toContain("responder@company.com");
743
+ // The timeline row is stamped with the identifiers a reader needs.
744
+ expect(timelineRows[0]?.userId?.toString()).toBe(USER_ID.toString());
745
+ expect(timelineRows[0]?.userNotificationRuleId?.toString()).toBe(
746
+ RULE_ID.toString(),
747
+ );
748
+ expect(timelineRows[0]?.userNotificationLogId?.toString()).toBe(
749
+ LOG_ID.toString(),
750
+ );
751
+ expect(timelineRows[0]?.projectId?.toString()).toBe(
752
+ PROJECT_ID.toString(),
753
+ );
754
+ });
755
+
756
+ test("no unverified channel is ever contacted, and each writes one Error row", async () => {
757
+ spies.findRule.mockResolvedValue(
758
+ ruleItem({
759
+ userEmail: {
760
+ id: METHOD_ID,
761
+ email: new Email("responder@company.com"),
762
+ isVerified: false,
763
+ },
764
+ userSms: {
765
+ id: METHOD_ID,
766
+ phone: new Phone("+11234567890"),
767
+ isVerified: false,
768
+ },
769
+ userWhatsApp: {
770
+ id: METHOD_ID,
771
+ phone: new Phone("+11234567891"),
772
+ isVerified: false,
773
+ },
774
+ userTelegram: {
775
+ id: METHOD_ID,
776
+ telegramChatId: "123456",
777
+ isVerified: false,
778
+ },
779
+ userCall: {
780
+ id: METHOD_ID,
781
+ phone: new Phone("+11234567892"),
782
+ isVerified: false,
783
+ },
784
+ userPush: {
785
+ id: METHOD_ID,
786
+ deviceToken: "device-token",
787
+ deviceType: "iOS",
788
+ isVerified: false,
789
+ },
790
+ } as unknown as JSONObject) as never,
791
+ );
792
+
793
+ await UserNotificationRuleService.executeNotificationRuleItem(
794
+ RULE_ID,
795
+ executeOptions(),
796
+ );
797
+
798
+ expect(spies.mail).not.toHaveBeenCalled();
799
+ expect(spies.sms).not.toHaveBeenCalled();
800
+ expect(spies.call).not.toHaveBeenCalled();
801
+ expect(spies.whatsApp).not.toHaveBeenCalled();
802
+ expect(spies.telegram).not.toHaveBeenCalled();
803
+ expect(spies.push).not.toHaveBeenCalled();
804
+
805
+ // One "not verified" Error row per unverified channel: 6 in total.
806
+ expect(timelineRows).toHaveLength(6);
807
+ for (const row of timelineRows) {
808
+ expect(row.status).toBe(UserNotificationStatus.Error);
809
+ expect(row.statusMessage).toContain("not verified");
810
+ }
811
+ });
812
+
813
+ test("the Telegram unverified branch keys off the RELATION, not the chat id", async () => {
814
+ spies.findRule.mockResolvedValue(
815
+ ruleItem({
816
+ userTelegram: {
817
+ id: METHOD_ID,
818
+ isVerified: false,
819
+ },
820
+ } as unknown as JSONObject) as never,
821
+ );
822
+
823
+ await UserNotificationRuleService.executeNotificationRuleItem(
824
+ RULE_ID,
825
+ executeOptions(),
826
+ );
827
+
828
+ /*
829
+ * Every other channel guards its "not verified" log on the address being
830
+ * present (`userSms?.phone && !isVerified`); Telegram alone guards on the
831
+ * relation existing, so a Telegram row with no chat id still produces an
832
+ * Error row. Pinned as current behaviour.
833
+ */
834
+ expect(spies.telegram).not.toHaveBeenCalled();
835
+ expect(timelineRows).toHaveLength(1);
836
+ expect(timelineRows[0]?.statusMessage).toContain("not verified");
837
+ });
838
+
839
+ test("a webhook is dispatched on webhookUrl alone - there is no verification gate", async () => {
840
+ spies.findRule.mockResolvedValue(
841
+ ruleItem({
842
+ userWebhook: {
843
+ id: METHOD_ID,
844
+ webhookUrl: "https://hooks.example.com/on-call",
845
+ name: "Pager bridge",
846
+ secret: "s3cr3t",
847
+ },
848
+ } as unknown as JSONObject) as never,
849
+ );
850
+
851
+ await UserNotificationRuleService.executeNotificationRuleItem(
852
+ RULE_ID,
853
+ executeOptions(),
854
+ );
855
+
856
+ expect(spies.webhook).toHaveBeenCalledTimes(1);
857
+ const payload: {
858
+ url: string;
859
+ eventType: string;
860
+ secret: string | undefined;
861
+ } = spies.webhook.mock.calls[0][0] as {
862
+ url: string;
863
+ eventType: string;
864
+ secret: string | undefined;
865
+ };
866
+ expect(payload.url).toBe("https://hooks.example.com/on-call");
867
+ expect(payload.eventType).toBe("on-call.incident.created");
868
+ // The selected `secret` is what signs the request - it must be selected.
869
+ expect(payload.secret).toBe("s3cr3t");
870
+ expect(timelineRows).toHaveLength(1);
871
+ expect(timelineRows[0]?.status).toBe(UserNotificationStatus.Sending);
872
+ });
873
+
874
+ test("a rule with no contactable channel at all sends nothing and logs nothing", async () => {
875
+ spies.findRule.mockResolvedValue(ruleItem() as never);
876
+
877
+ await UserNotificationRuleService.executeNotificationRuleItem(
878
+ RULE_ID,
879
+ executeOptions(),
880
+ );
881
+
882
+ for (const sender of everySender()) {
883
+ expect(sender).not.toHaveBeenCalled();
884
+ }
885
+ /*
886
+ * KNOWN GAP (pinned as-is): a hydrated rule pointing at a method that was
887
+ * cascade-deleted produces a completely silent execution - no send and no
888
+ * timeline row saying why.
889
+ */
890
+ expect(timelineRows).toHaveLength(0);
891
+ });
892
+ });
893
+
894
+ /*
895
+ * ----------------------------------------------------------------------- *
896
+ * (C continued) The trigger entity must resolve before anything is sent.
897
+ * -----------------------------------------------------------------------
898
+ */
899
+
900
+ describe("resolving the triggering entity", () => {
901
+ test("throws when the incident behind an IncidentCreated event is gone", async () => {
902
+ spies.incidentFind.mockResolvedValue(null as never);
903
+
904
+ await expect(
905
+ UserNotificationRuleService.executeNotificationRuleItem(
906
+ RULE_ID,
907
+ executeOptions(),
908
+ ),
909
+ ).rejects.toThrow(
910
+ "Incident, Alert, Alert Episode, or Incident Episode not found.",
911
+ );
912
+
913
+ for (const sender of everySender()) {
914
+ expect(sender).not.toHaveBeenCalled();
915
+ }
916
+ });
917
+
918
+ test("an IncidentCreated event with no triggeredByIncidentId never even queries the incident", async () => {
919
+ await expect(
920
+ UserNotificationRuleService.executeNotificationRuleItem(
921
+ RULE_ID,
922
+ executeOptions({ triggeredByIncidentId: undefined }),
923
+ ),
924
+ ).rejects.toThrow(BadDataException);
925
+
926
+ expect(spies.incidentFind).not.toHaveBeenCalled();
927
+ });
928
+
929
+ test("the event type - not the supplied ids - picks which entity is loaded", async () => {
930
+ await UserNotificationRuleService.executeNotificationRuleItem(
931
+ RULE_ID,
932
+ executeOptions({
933
+ userNotificationEventType: UserNotificationEventType.AlertCreated,
934
+ triggeredByAlertId: ALERT_ID,
935
+ triggeredByIncidentId: INCIDENT_ID,
936
+ }),
937
+ );
938
+
939
+ expect(spies.alertFind).toHaveBeenCalledTimes(1);
940
+ // IncidentCreated is not the event type, so the incident is never read.
941
+ expect(spies.incidentFind).not.toHaveBeenCalled();
942
+ });
943
+ });
944
+ });
945
+
946
+ /*
947
+ * ------------------------------------------------------------------------- *
948
+ * (D) startUserNotificationRulesExecution - the scheduling entrypoint.
949
+ * -------------------------------------------------------------------------
950
+ */
951
+
952
+ describe("UserNotificationRuleService.startUserNotificationRulesExecution", () => {
953
+ let createLog: jest.SpyInstance;
954
+ let workspaceRules: jest.SpyInstance;
955
+ let loggerError: jest.SpyInstance;
956
+
957
+ function startOptions(overrides: Partial<StartOptions> = {}): StartOptions {
958
+ return {
959
+ projectId: PROJECT_ID,
960
+ userNotificationEventType: UserNotificationEventType.IncidentCreated,
961
+ onCallPolicyId: POLICY_ID,
962
+ ...overrides,
963
+ };
964
+ }
965
+
966
+ function fullStartOptions(): StartOptions {
967
+ return {
968
+ projectId: PROJECT_ID,
969
+ triggeredByIncidentId: INCIDENT_ID,
970
+ triggeredByAlertId: ALERT_ID,
971
+ triggeredByAlertEpisodeId: ALERT_EPISODE_ID,
972
+ triggeredByIncidentEpisodeId: INCIDENT_EPISODE_ID,
973
+ userNotificationEventType: UserNotificationEventType.IncidentCreated,
974
+ onCallPolicyExecutionLogId: EXECUTION_LOG_ID,
975
+ onCallPolicyId: POLICY_ID,
976
+ onCallPolicyEscalationRuleId: ESCALATION_RULE_ID,
977
+ userBelongsToTeamId: TEAM_ID,
978
+ onCallDutyPolicyExecutionLogTimelineId: EXECUTION_LOG_TIMELINE_ID,
979
+ onCallScheduleId: SCHEDULE_ID,
980
+ overridedByUserId: OVERRIDE_USER_ID,
981
+ };
982
+ }
983
+
984
+ function createdLog(): UserOnCallLog {
985
+ return (createLog.mock.calls[0][0] as { data: UserOnCallLog }).data;
986
+ }
987
+
988
+ beforeEach(() => {
989
+ loggerError = jest.spyOn(logger, "error").mockImplementation((): void => {
990
+ return undefined;
991
+ });
992
+
993
+ createLog = jest
994
+ .spyOn(UserOnCallLogService, "create")
995
+ .mockResolvedValue({ id: LOG_ID } as unknown as UserOnCallLog as never);
996
+
997
+ workspaceRules = jest
998
+ .spyOn(
999
+ UserNotificationRuleService,
1000
+ "runWorkspaceRulesForOnCallNotification",
1001
+ )
1002
+ .mockResolvedValue(undefined as never);
1003
+ });
1004
+
1005
+ afterEach(() => {
1006
+ jest.restoreAllMocks();
1007
+ });
1008
+
1009
+ test("creates exactly one UserOnCallLog, as root", async () => {
1010
+ await UserNotificationRuleService.startUserNotificationRulesExecution(
1011
+ USER_ID,
1012
+ startOptions(),
1013
+ );
1014
+
1015
+ expect(createLog).toHaveBeenCalledTimes(1);
1016
+ const arg: { props: { isRoot: boolean } } = createLog.mock.calls[0][0] as {
1017
+ props: { isRoot: boolean };
1018
+ };
1019
+ expect(arg.props.isRoot).toBe(true);
1020
+ });
1021
+
1022
+ test("the log is Scheduled with statusMessage 'Scheduled' so the worker picks it up", async () => {
1023
+ await UserNotificationRuleService.startUserNotificationRulesExecution(
1024
+ USER_ID,
1025
+ startOptions(),
1026
+ );
1027
+
1028
+ const log: UserOnCallLog = createdLog();
1029
+ expect(log.status).toBe(UserNotificationExecutionStatus.Scheduled);
1030
+ expect(log.statusMessage).toBe("Scheduled");
1031
+ });
1032
+
1033
+ test("the user and project always land on the log", async () => {
1034
+ await UserNotificationRuleService.startUserNotificationRulesExecution(
1035
+ USER_ID,
1036
+ startOptions(),
1037
+ );
1038
+
1039
+ const log: UserOnCallLog = createdLog();
1040
+ expect(log.userId?.toString()).toBe(USER_ID.toString());
1041
+ expect(log.projectId?.toString()).toBe(PROJECT_ID.toString());
1042
+ expect(log.userNotificationEventType).toBe(
1043
+ UserNotificationEventType.IncidentCreated,
1044
+ );
1045
+ });
1046
+
1047
+ test("EVERY option field is forwarded onto the log when all of them are supplied", async () => {
1048
+ await UserNotificationRuleService.startUserNotificationRulesExecution(
1049
+ USER_ID,
1050
+ fullStartOptions(),
1051
+ );
1052
+
1053
+ const log: UserOnCallLog = createdLog();
1054
+
1055
+ expect(log.triggeredByIncidentId?.toString()).toBe(INCIDENT_ID.toString());
1056
+ expect(log.triggeredByAlertId?.toString()).toBe(ALERT_ID.toString());
1057
+ expect(log.triggeredByAlertEpisodeId?.toString()).toBe(
1058
+ ALERT_EPISODE_ID.toString(),
1059
+ );
1060
+ expect(log.triggeredByIncidentEpisodeId?.toString()).toBe(
1061
+ INCIDENT_EPISODE_ID.toString(),
1062
+ );
1063
+ // Renamed on the way in: onCallPolicy* -> onCallDutyPolicy*.
1064
+ expect(log.onCallDutyPolicyExecutionLogId?.toString()).toBe(
1065
+ EXECUTION_LOG_ID.toString(),
1066
+ );
1067
+ expect(log.onCallDutyPolicyId?.toString()).toBe(POLICY_ID.toString());
1068
+ expect(log.onCallDutyPolicyEscalationRuleId?.toString()).toBe(
1069
+ ESCALATION_RULE_ID.toString(),
1070
+ );
1071
+ expect(log.onCallDutyPolicyExecutionLogTimelineId?.toString()).toBe(
1072
+ EXECUTION_LOG_TIMELINE_ID.toString(),
1073
+ );
1074
+ expect(log.userBelongsToTeamId?.toString()).toBe(TEAM_ID.toString());
1075
+ // onCallScheduleId -> onCallDutyScheduleId.
1076
+ expect(log.onCallDutyScheduleId?.toString()).toBe(SCHEDULE_ID.toString());
1077
+ expect(log.overridedByUserId?.toString()).toBe(OVERRIDE_USER_ID.toString());
1078
+ });
1079
+
1080
+ test("optional fields left out stay unset on the log (no undefined-id writes)", async () => {
1081
+ await UserNotificationRuleService.startUserNotificationRulesExecution(
1082
+ USER_ID,
1083
+ startOptions({ onCallPolicyId: undefined }),
1084
+ );
1085
+
1086
+ const log: UserOnCallLog = createdLog();
1087
+ expect(log.triggeredByIncidentId).toBeUndefined();
1088
+ expect(log.triggeredByAlertId).toBeUndefined();
1089
+ expect(log.triggeredByAlertEpisodeId).toBeUndefined();
1090
+ expect(log.triggeredByIncidentEpisodeId).toBeUndefined();
1091
+ expect(log.onCallDutyPolicyId).toBeUndefined();
1092
+ expect(log.onCallDutyPolicyExecutionLogId).toBeUndefined();
1093
+ expect(log.onCallDutyPolicyEscalationRuleId).toBeUndefined();
1094
+ expect(log.onCallDutyPolicyExecutionLogTimelineId).toBeUndefined();
1095
+ expect(log.userBelongsToTeamId).toBeUndefined();
1096
+ expect(log.onCallDutyScheduleId).toBeUndefined();
1097
+ expect(log.overridedByUserId).toBeUndefined();
1098
+ // ...but the status fields are unconditional.
1099
+ expect(log.status).toBe(UserNotificationExecutionStatus.Scheduled);
1100
+ });
1101
+
1102
+ test("the workspace-invite call is handed projectId, alertId, incidentId and userId", async () => {
1103
+ await UserNotificationRuleService.startUserNotificationRulesExecution(
1104
+ USER_ID,
1105
+ startOptions({ triggeredByIncidentId: INCIDENT_ID }),
1106
+ );
1107
+
1108
+ expect(workspaceRules).toHaveBeenCalledTimes(1);
1109
+ const arg: {
1110
+ projectId: ObjectID;
1111
+ alertId: ObjectID | undefined;
1112
+ incidentId: ObjectID | undefined;
1113
+ userId: ObjectID;
1114
+ } = workspaceRules.mock.calls[0][0] as {
1115
+ projectId: ObjectID;
1116
+ alertId: ObjectID | undefined;
1117
+ incidentId: ObjectID | undefined;
1118
+ userId: ObjectID;
1119
+ };
1120
+ expect(arg.projectId.toString()).toBe(PROJECT_ID.toString());
1121
+ expect(arg.incidentId?.toString()).toBe(INCIDENT_ID.toString());
1122
+ expect(arg.alertId).toBeUndefined();
1123
+ expect(arg.userId.toString()).toBe(USER_ID.toString());
1124
+ });
1125
+
1126
+ test("the log is created BEFORE the workspace-invite call is fired", async () => {
1127
+ await UserNotificationRuleService.startUserNotificationRulesExecution(
1128
+ USER_ID,
1129
+ startOptions({ triggeredByIncidentId: INCIDENT_ID }),
1130
+ );
1131
+
1132
+ expect(createLog.mock.invocationCallOrder[0]).toBeLessThan(
1133
+ workspaceRules.mock.invocationCallOrder[0] as number,
1134
+ );
1135
+ });
1136
+
1137
+ test("a failure creating the log propagates, and no workspace invite is attempted", async () => {
1138
+ createLog.mockRejectedValue(new Error("pool timeout") as never);
1139
+
1140
+ await expect(
1141
+ UserNotificationRuleService.startUserNotificationRulesExecution(
1142
+ USER_ID,
1143
+ startOptions(),
1144
+ ),
1145
+ ).rejects.toThrow("pool timeout");
1146
+
1147
+ expect(workspaceRules).not.toHaveBeenCalled();
1148
+ });
1149
+
1150
+ test("a REJECTION from the workspace-invite call does NOT reject the scheduling", async () => {
1151
+ workspaceRules.mockRejectedValue(
1152
+ new Error("slack workspace unreachable") as never,
1153
+ );
1154
+
1155
+ /*
1156
+ * This is the whole reason the call is `.catch`-ed rather than awaited: an
1157
+ * unreachable Slack must never stop a page from being scheduled. If this
1158
+ * ever starts rejecting, every on-call notification in a project with a
1159
+ * broken workspace integration disappears.
1160
+ */
1161
+ await expect(
1162
+ UserNotificationRuleService.startUserNotificationRulesExecution(
1163
+ USER_ID,
1164
+ startOptions({ triggeredByIncidentId: INCIDENT_ID }),
1165
+ ),
1166
+ ).resolves.toBeUndefined();
1167
+
1168
+ await flushMicrotasks();
1169
+
1170
+ // It is swallowed into the log, not lost silently.
1171
+ expect(loggerError).toHaveBeenCalled();
1172
+ expect(createLog).toHaveBeenCalledTimes(1);
1173
+ });
1174
+
1175
+ test("the swallowed workspace error is logged with the project and user attributes", async () => {
1176
+ workspaceRules.mockRejectedValue(new Error("slack down") as never);
1177
+
1178
+ await UserNotificationRuleService.startUserNotificationRulesExecution(
1179
+ USER_ID,
1180
+ startOptions({ triggeredByIncidentId: INCIDENT_ID }),
1181
+ );
1182
+ await flushMicrotasks();
1183
+
1184
+ const attributes: { projectId: string; userId: string } = loggerError.mock
1185
+ .calls[0][1] as { projectId: string; userId: string };
1186
+ expect(attributes.projectId).toBe(PROJECT_ID.toString());
1187
+ expect(attributes.userId).toBe(USER_ID.toString());
1188
+ });
1189
+
1190
+ test("the workspace-invite call is NOT awaited (scheduling returns while it is still pending)", async () => {
1191
+ let release: () => void = (): void => {
1192
+ return undefined;
1193
+ };
1194
+ const pending: Promise<void> = new Promise<void>(
1195
+ (resolve: () => void): void => {
1196
+ release = resolve;
1197
+ },
1198
+ );
1199
+ workspaceRules.mockReturnValue(pending);
1200
+
1201
+ /*
1202
+ * If startUserNotificationRulesExecution awaited the workspace call, this
1203
+ * await would never settle and the test would time out. Reaching the next
1204
+ * line IS the assertion.
1205
+ */
1206
+ await UserNotificationRuleService.startUserNotificationRulesExecution(
1207
+ USER_ID,
1208
+ startOptions({ triggeredByIncidentId: INCIDENT_ID }),
1209
+ );
1210
+
1211
+ expect(workspaceRules).toHaveBeenCalledTimes(1);
1212
+
1213
+ release();
1214
+ await pending;
1215
+ });
1216
+
1217
+ test("an episode-triggered execution has no incident or alert id, so the workspace call always errors", async () => {
1218
+ /*
1219
+ * Discovered behaviour, pinned as-is: startUserNotificationRulesExecution
1220
+ * forwards `alertId`/`incidentId` verbatim, and
1221
+ * runWorkspaceRulesForOnCallNotification throws when BOTH are missing. For
1222
+ * AlertEpisodeCreated / IncidentEpisodeCreated executions that is always
1223
+ * the case, so every episode page logs a BadDataException on this path.
1224
+ * Harmless to delivery (it is caught), but it is permanent log noise.
1225
+ */
1226
+ workspaceRules.mockRestore();
1227
+
1228
+ const getRules: jest.SpyInstance = jest.spyOn(
1229
+ WorkspaceNotificationRuleService,
1230
+ "getNotificationRulesWhereInviteOwnersIsTrue",
1231
+ );
1232
+
1233
+ await expect(
1234
+ UserNotificationRuleService.startUserNotificationRulesExecution(
1235
+ USER_ID,
1236
+ startOptions({
1237
+ userNotificationEventType:
1238
+ UserNotificationEventType.AlertEpisodeCreated,
1239
+ triggeredByAlertEpisodeId: ALERT_EPISODE_ID,
1240
+ }),
1241
+ ),
1242
+ ).resolves.toBeUndefined();
1243
+
1244
+ await flushMicrotasks();
1245
+
1246
+ expect(createLog).toHaveBeenCalledTimes(1);
1247
+ expect(getRules).not.toHaveBeenCalled();
1248
+ expect(loggerError).toHaveBeenCalled();
1249
+ expect(loggerError.mock.calls[0][0]).toBeInstanceOf(BadDataException);
1250
+ });
1251
+ });
1252
+
1253
+ /*
1254
+ * ------------------------------------------------------------------------- *
1255
+ * (E) runWorkspaceRulesForOnCallNotification.
1256
+ * -------------------------------------------------------------------------
1257
+ */
1258
+
1259
+ describe("UserNotificationRuleService.runWorkspaceRulesForOnCallNotification", () => {
1260
+ let getRules: jest.SpyInstance;
1261
+ let inviteUsers: jest.SpyInstance;
1262
+ let incidentChannels: jest.SpyInstance;
1263
+ let alertChannels: jest.SpyInstance;
1264
+ let loggerError: jest.SpyInstance;
1265
+
1266
+ beforeEach(() => {
1267
+ loggerError = jest.spyOn(logger, "error").mockImplementation((): void => {
1268
+ return undefined;
1269
+ });
1270
+
1271
+ getRules = jest
1272
+ .spyOn(
1273
+ WorkspaceNotificationRuleService,
1274
+ "getNotificationRulesWhereInviteOwnersIsTrue",
1275
+ )
1276
+ .mockResolvedValue([] as never);
1277
+
1278
+ inviteUsers = jest
1279
+ .spyOn(
1280
+ WorkspaceNotificationRuleService,
1281
+ "inviteUsersBasedOnRulesAndWorkspaceChannels",
1282
+ )
1283
+ .mockResolvedValue(undefined as never);
1284
+
1285
+ incidentChannels = jest
1286
+ .spyOn(IncidentService, "getWorkspaceChannelForIncident")
1287
+ .mockResolvedValue([] as never);
1288
+
1289
+ alertChannels = jest
1290
+ .spyOn(AlertService, "getWorkspaceChannelForAlert")
1291
+ .mockResolvedValue([] as never);
1292
+ });
1293
+
1294
+ afterEach(() => {
1295
+ jest.restoreAllMocks();
1296
+ });
1297
+
1298
+ test("throws BadDataException when BOTH incidentId and alertId are supplied", async () => {
1299
+ await expect(
1300
+ UserNotificationRuleService.runWorkspaceRulesForOnCallNotification({
1301
+ projectId: PROJECT_ID,
1302
+ incidentId: INCIDENT_ID,
1303
+ alertId: ALERT_ID,
1304
+ userId: USER_ID,
1305
+ }),
1306
+ ).rejects.toThrow(BadDataException);
1307
+ });
1308
+
1309
+ test("the both-supplied message is 'Either incidentId or alertId is required.'", async () => {
1310
+ /*
1311
+ * Pinned as-is even though it reads wrongly for this branch: the ambiguous
1312
+ * case ("you gave me both") reuses the missing-case message verbatim.
1313
+ */
1314
+ await expect(
1315
+ UserNotificationRuleService.runWorkspaceRulesForOnCallNotification({
1316
+ projectId: PROJECT_ID,
1317
+ incidentId: INCIDENT_ID,
1318
+ alertId: ALERT_ID,
1319
+ userId: USER_ID,
1320
+ }),
1321
+ ).rejects.toThrow("Either incidentId or alertId is required.");
1322
+ });
1323
+
1324
+ test("supplying both short-circuits before any workspace query", async () => {
1325
+ await expect(
1326
+ UserNotificationRuleService.runWorkspaceRulesForOnCallNotification({
1327
+ projectId: PROJECT_ID,
1328
+ incidentId: INCIDENT_ID,
1329
+ alertId: ALERT_ID,
1330
+ userId: USER_ID,
1331
+ }),
1332
+ ).rejects.toThrow(BadDataException);
1333
+
1334
+ expect(getRules).not.toHaveBeenCalled();
1335
+ expect(incidentChannels).not.toHaveBeenCalled();
1336
+ expect(alertChannels).not.toHaveBeenCalled();
1337
+ expect(inviteUsers).not.toHaveBeenCalled();
1338
+ });
1339
+
1340
+ test("throws the same BadDataException when NEITHER is supplied", async () => {
1341
+ await expect(
1342
+ UserNotificationRuleService.runWorkspaceRulesForOnCallNotification({
1343
+ projectId: PROJECT_ID,
1344
+ userId: USER_ID,
1345
+ }),
1346
+ ).rejects.toThrow("Either incidentId or alertId is required.");
1347
+
1348
+ expect(getRules).not.toHaveBeenCalled();
1349
+ });
1350
+
1351
+ test("the incident path queries incident rules and incident channels only", async () => {
1352
+ await UserNotificationRuleService.runWorkspaceRulesForOnCallNotification({
1353
+ projectId: PROJECT_ID,
1354
+ incidentId: INCIDENT_ID,
1355
+ userId: USER_ID,
1356
+ });
1357
+
1358
+ const rulesArg: {
1359
+ projectId: ObjectID;
1360
+ notificationFor: { incidentId?: ObjectID; alertId?: ObjectID };
1361
+ notificationRuleEventType: NotificationRuleEventType;
1362
+ } = getRules.mock.calls[0][0] as {
1363
+ projectId: ObjectID;
1364
+ notificationFor: { incidentId?: ObjectID; alertId?: ObjectID };
1365
+ notificationRuleEventType: NotificationRuleEventType;
1366
+ };
1367
+ expect(rulesArg.projectId.toString()).toBe(PROJECT_ID.toString());
1368
+ expect(rulesArg.notificationFor.incidentId?.toString()).toBe(
1369
+ INCIDENT_ID.toString(),
1370
+ );
1371
+ expect(rulesArg.notificationFor.alertId).toBeUndefined();
1372
+ expect(rulesArg.notificationRuleEventType).toBe(
1373
+ NotificationRuleEventType.Incident,
1374
+ );
1375
+
1376
+ expect(incidentChannels).toHaveBeenCalledTimes(1);
1377
+ expect(alertChannels).not.toHaveBeenCalled();
1378
+ });
1379
+
1380
+ test("the alert path queries alert rules and alert channels only", async () => {
1381
+ await UserNotificationRuleService.runWorkspaceRulesForOnCallNotification({
1382
+ projectId: PROJECT_ID,
1383
+ alertId: ALERT_ID,
1384
+ userId: USER_ID,
1385
+ });
1386
+
1387
+ const rulesArg: {
1388
+ notificationFor: { incidentId?: ObjectID; alertId?: ObjectID };
1389
+ notificationRuleEventType: NotificationRuleEventType;
1390
+ } = getRules.mock.calls[0][0] as {
1391
+ notificationFor: { incidentId?: ObjectID; alertId?: ObjectID };
1392
+ notificationRuleEventType: NotificationRuleEventType;
1393
+ };
1394
+ expect(rulesArg.notificationFor.alertId?.toString()).toBe(
1395
+ ALERT_ID.toString(),
1396
+ );
1397
+ expect(rulesArg.notificationFor.incidentId).toBeUndefined();
1398
+ expect(rulesArg.notificationRuleEventType).toBe(
1399
+ NotificationRuleEventType.Alert,
1400
+ );
1401
+
1402
+ expect(alertChannels).toHaveBeenCalledTimes(1);
1403
+ expect(incidentChannels).not.toHaveBeenCalled();
1404
+ });
1405
+
1406
+ test("only the notified user is invited, with the resolved rules and channels", async () => {
1407
+ const rules: Array<unknown> = [{ _id: "rule-1" }];
1408
+ const channels: Array<unknown> = [{ id: "channel-1", name: "#incidents" }];
1409
+ getRules.mockResolvedValue(rules as never);
1410
+ incidentChannels.mockResolvedValue(channels as never);
1411
+
1412
+ await UserNotificationRuleService.runWorkspaceRulesForOnCallNotification({
1413
+ projectId: PROJECT_ID,
1414
+ incidentId: INCIDENT_ID,
1415
+ userId: USER_ID,
1416
+ });
1417
+
1418
+ expect(inviteUsers).toHaveBeenCalledTimes(1);
1419
+ const inviteArg: {
1420
+ notificationRules: Array<unknown>;
1421
+ projectId: ObjectID;
1422
+ workspaceChannels: Array<unknown>;
1423
+ userIds: Array<ObjectID>;
1424
+ } = inviteUsers.mock.calls[0][0] as {
1425
+ notificationRules: Array<unknown>;
1426
+ projectId: ObjectID;
1427
+ workspaceChannels: Array<unknown>;
1428
+ userIds: Array<ObjectID>;
1429
+ };
1430
+ expect(inviteArg.notificationRules).toBe(rules);
1431
+ expect(inviteArg.workspaceChannels).toBe(channels);
1432
+ expect(inviteArg.projectId.toString()).toBe(PROJECT_ID.toString());
1433
+ expect(inviteArg.userIds).toHaveLength(1);
1434
+ expect(inviteArg.userIds[0]?.toString()).toBe(USER_ID.toString());
1435
+ });
1436
+
1437
+ test("a failing invite is swallowed and logged - it never rejects the caller", async () => {
1438
+ inviteUsers.mockRejectedValue(new Error("slack api 500") as never);
1439
+
1440
+ await expect(
1441
+ UserNotificationRuleService.runWorkspaceRulesForOnCallNotification({
1442
+ projectId: PROJECT_ID,
1443
+ incidentId: INCIDENT_ID,
1444
+ userId: USER_ID,
1445
+ }),
1446
+ ).resolves.toBeUndefined();
1447
+
1448
+ await flushMicrotasks();
1449
+
1450
+ expect(loggerError).toHaveBeenCalled();
1451
+ });
1452
+
1453
+ test("a failing channel lookup DOES reject (it is awaited, unlike the invite)", async () => {
1454
+ incidentChannels.mockRejectedValue(
1455
+ new Error("workspace api down") as never,
1456
+ );
1457
+
1458
+ await expect(
1459
+ UserNotificationRuleService.runWorkspaceRulesForOnCallNotification({
1460
+ projectId: PROJECT_ID,
1461
+ incidentId: INCIDENT_ID,
1462
+ userId: USER_ID,
1463
+ }),
1464
+ ).rejects.toThrow("workspace api down");
1465
+
1466
+ expect(inviteUsers).not.toHaveBeenCalled();
1467
+ });
1468
+ });