@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,1183 @@
1
+ import DatabaseConfig from "../DatabaseConfig";
2
+ import BaseService from "./BaseService";
3
+ import MailService from "./MailService";
4
+ import ProjectService from "./ProjectService";
5
+ import TeamMemberService from "./TeamMemberService";
6
+ import UserCallService from "./UserCallService";
7
+ import UserEmailService from "./UserEmailService";
8
+ import UserPushService from "./UserPushService";
9
+ import UserService from "./UserService";
10
+ import UserSmsService from "./UserSmsService";
11
+ import UserTelegramService from "./UserTelegramService";
12
+ import UserWebhookService from "./UserWebhookService";
13
+ import UserWhatsAppService from "./UserWhatsAppService";
14
+ import type AuditLogServiceType from "./AuditLogService";
15
+ import { resolveReferenceId } from "../Utils/Database/ProjectScopedReferenceValidator";
16
+ import logger, { LogAttributes } from "../Utils/Logger";
17
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
18
+ import URL from "../../Types/API/URL";
19
+ import AuditLogAction from "../../Types/AuditLog/AuditLogAction";
20
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
21
+ import Dictionary from "../../Types/Dictionary";
22
+ import EmailTemplateType from "../../Types/Email/EmailTemplateType";
23
+ import BadDataException from "../../Types/Exception/BadDataException";
24
+ import { JSONObject } from "../../Types/JSON";
25
+ import ObjectID from "../../Types/ObjectID";
26
+ import Project from "../../Models/DatabaseModels/Project";
27
+ import TeamMember from "../../Models/DatabaseModels/TeamMember";
28
+ import User from "../../Models/DatabaseModels/User";
29
+ import UserNotificationRule from "../../Models/DatabaseModels/UserNotificationRule";
30
+
31
+ /*
32
+ * THE SHAPE OF THE PROBLEM THIS FILE EXISTS TO SOLVE
33
+ *
34
+ * A UserNotificationRule row is a pair: an OWNERSHIP column (userId) that
35
+ * decides whose on-call pages select the row, and a METHOD foreign key that
36
+ * decides which address the page is delivered to. Those two halves are read at
37
+ * completely different moments by completely different code — the ownership
38
+ * column by UserOnCallLogService when it works out who to page, the method
39
+ * relation by UserNotificationRuleService when it works out where to send — and
40
+ * NOTHING in the ORM, the permission layer or the API surface ever compares
41
+ * them.
42
+ *
43
+ * While every notification model was CurrentUser-only that mismatch was
44
+ * unreachable in practice, because a caller could only ever name their own id
45
+ * in both halves. Phase 3 deliberately widens the rule model so a project admin
46
+ * can repair somebody else's configuration, and the moment an admin may write a
47
+ * row whose userId is not their own, "userId says Bob, userWebhookId says the
48
+ * admin's own webhook" becomes a row an attacker can ask for. It would route
49
+ * every one of Bob's pages to an endpoint the attacker controls, and Bob would
50
+ * see nothing: his rules page still says he is paged, his on-call log still
51
+ * says a page went out.
52
+ *
53
+ * So the widened permission is only half the feature. The other half is here:
54
+ * the value-level invariants that the permission layer structurally cannot
55
+ * express, because it reasons about tables and columns and never about the
56
+ * relationship BETWEEN two column values in one row.
57
+ *
58
+ * R1 A rule may only be written for a user who is a member of the project
59
+ * the write is scoped to. Without this, holding ProjectAdmin anywhere
60
+ * lets you write rules for a user id belonging to any other project.
61
+ *
62
+ * R3 A rule's method FK must reference a method row owned by the SAME user
63
+ * as the rule. This is the anti-hijack invariant, and on the update path
64
+ * the rule's owner is re-read FROM THE DATABASE — a userId in the request
65
+ * body is the attacker's own input and proves nothing.
66
+ *
67
+ * R6 When the actor is not the owner, say so out loud: an audit trail keyed
68
+ * on the server-resolved actor versus the row's PERSISTED owner, and a
69
+ * mail to the person whose pages just changed.
70
+ *
71
+ * None of these are UI concerns. POST/PATCH /api/user-notification-rule stays
72
+ * reachable with any member session and no dashboard involved, so every one of
73
+ * them is enforced in the service hooks that the API route runs through.
74
+ */
75
+
76
+ /*
77
+ * One of the seven ways a rule can name a delivery address, reduced to what the
78
+ * ownership guard needs: which column carried it (for the error message and the
79
+ * audit line) and which row it points at.
80
+ */
81
+ export interface NotificationMethodReference {
82
+ /** The FK column on UserNotificationRule, e.g. "userWebhookId". */
83
+ idColumn: string;
84
+ /*
85
+ * The property the payload actually used to carry this id: either the FK
86
+ * column itself or the relation slot beside it. Both write the one database
87
+ * column, and a payload may carry both — so a reference has to remember which
88
+ * spelling it came out of, or the ambiguity check below has nothing to talk
89
+ * about.
90
+ */
91
+ suppliedColumn: string;
92
+ /** Human-readable channel name used verbatim in rejection messages. */
93
+ label: string;
94
+ /** The notification-method row the rule points at. */
95
+ methodId: ObjectID;
96
+ }
97
+
98
+ /*
99
+ * A rule-shaped bag of values to read the guarded columns out of — the seven
100
+ * method references AND the ownership column, because both halves of the pair
101
+ * this file exists to compare arrive through the same payload.
102
+ *
103
+ * Create hands us a hydrated UserNotificationRule; update hands us a
104
+ * PartialEntity whose slots may hold an ObjectID, a bare uuid string or a
105
+ * relation object depending on how far through sanitisation the request has
106
+ * travelled. Rather than overload on those, callers cast to this and
107
+ * resolveReferenceId untangles the shapes — the same helper the project-scoped
108
+ * reference guards use, for exactly the same reason.
109
+ */
110
+ export type RuleColumnCarrier = Record<string, unknown>;
111
+
112
+ /*
113
+ * The ownership column in both of its spellings, resolved from the model rather
114
+ * than restated as two string literals.
115
+ */
116
+ interface RuleOwnerColumns {
117
+ /** The scalar @CurrentUserCanAccessRecordBy points at, i.e. "userId". */
118
+ idColumn: string;
119
+ /** The ManyToOne beside it whose @JoinColumn names that same scalar. */
120
+ relationColumn: string;
121
+ }
122
+
123
+ /*
124
+ * Why this reads a row rather than being handed one.
125
+ *
126
+ * Every lookup below runs with isRoot props. That is not laziness about
127
+ * permissions: the question being asked is a question about the DATABASE'S
128
+ * state ("who really owns method X", "is user Y really in project P"), and
129
+ * asking it through the caller's own permission scope would let the caller's
130
+ * scope shape the answer. A caller who cannot READ the victim's method row
131
+ * would get `null` back and, under any "not found means fine" reading, sail
132
+ * straight through the guard that exists to stop them.
133
+ */
134
+ interface NotificationMethodDescriptor {
135
+ idColumn: string;
136
+ relationColumn: string;
137
+ label: string;
138
+ findOwnerUserId: (methodId: ObjectID) => Promise<ObjectID | undefined>;
139
+ }
140
+
141
+ export class UserNotificationRuleAdminService extends BaseService {
142
+ /*
143
+ * Built per call, never hoisted to module scope.
144
+ *
145
+ * UserEmailService and its six siblings import UserNotificationRuleService,
146
+ * which imports this file — a genuine require cycle. Capturing the service
147
+ * objects in a module-level constant would read `default` while the sibling
148
+ * module is still mid-evaluation and freeze `undefined` into the table. Built
149
+ * inside a method, every service reference resolves at call time, long after
150
+ * the cycle has settled.
151
+ */
152
+ private getNotificationMethodDescriptors(): Array<NotificationMethodDescriptor> {
153
+ return [
154
+ {
155
+ idColumn: "userEmailId",
156
+ relationColumn: "userEmail",
157
+ label: "Email",
158
+ findOwnerUserId: async (
159
+ methodId: ObjectID,
160
+ ): Promise<ObjectID | undefined> => {
161
+ return (
162
+ await UserEmailService.findOneById({
163
+ id: methodId,
164
+ select: { _id: true, userId: true },
165
+ props: { isRoot: true },
166
+ })
167
+ )?.userId;
168
+ },
169
+ },
170
+ {
171
+ idColumn: "userSmsId",
172
+ relationColumn: "userSms",
173
+ label: "SMS",
174
+ findOwnerUserId: async (
175
+ methodId: ObjectID,
176
+ ): Promise<ObjectID | undefined> => {
177
+ return (
178
+ await UserSmsService.findOneById({
179
+ id: methodId,
180
+ select: { _id: true, userId: true },
181
+ props: { isRoot: true },
182
+ })
183
+ )?.userId;
184
+ },
185
+ },
186
+ {
187
+ idColumn: "userCallId",
188
+ relationColumn: "userCall",
189
+ label: "Call",
190
+ findOwnerUserId: async (
191
+ methodId: ObjectID,
192
+ ): Promise<ObjectID | undefined> => {
193
+ return (
194
+ await UserCallService.findOneById({
195
+ id: methodId,
196
+ select: { _id: true, userId: true },
197
+ props: { isRoot: true },
198
+ })
199
+ )?.userId;
200
+ },
201
+ },
202
+ {
203
+ idColumn: "userWhatsAppId",
204
+ relationColumn: "userWhatsApp",
205
+ label: "WhatsApp",
206
+ findOwnerUserId: async (
207
+ methodId: ObjectID,
208
+ ): Promise<ObjectID | undefined> => {
209
+ return (
210
+ await UserWhatsAppService.findOneById({
211
+ id: methodId,
212
+ select: { _id: true, userId: true },
213
+ props: { isRoot: true },
214
+ })
215
+ )?.userId;
216
+ },
217
+ },
218
+ {
219
+ idColumn: "userTelegramId",
220
+ relationColumn: "userTelegram",
221
+ label: "Telegram",
222
+ findOwnerUserId: async (
223
+ methodId: ObjectID,
224
+ ): Promise<ObjectID | undefined> => {
225
+ return (
226
+ await UserTelegramService.findOneById({
227
+ id: methodId,
228
+ select: { _id: true, userId: true },
229
+ props: { isRoot: true },
230
+ })
231
+ )?.userId;
232
+ },
233
+ },
234
+ {
235
+ idColumn: "userPushId",
236
+ relationColumn: "userPush",
237
+ label: "Push",
238
+ findOwnerUserId: async (
239
+ methodId: ObjectID,
240
+ ): Promise<ObjectID | undefined> => {
241
+ return (
242
+ await UserPushService.findOneById({
243
+ id: methodId,
244
+ select: { _id: true, userId: true },
245
+ props: { isRoot: true },
246
+ })
247
+ )?.userId;
248
+ },
249
+ },
250
+ {
251
+ idColumn: "userWebhookId",
252
+ relationColumn: "userWebhook",
253
+ label: "Webhook",
254
+ findOwnerUserId: async (
255
+ methodId: ObjectID,
256
+ ): Promise<ObjectID | undefined> => {
257
+ return (
258
+ await UserWebhookService.findOneById({
259
+ id: methodId,
260
+ select: { _id: true, userId: true },
261
+ props: { isRoot: true },
262
+ })
263
+ )?.userId;
264
+ },
265
+ },
266
+ ];
267
+ }
268
+
269
+ /*
270
+ * The seven FK columns, in one place, so a future eighth channel is a single
271
+ * entry rather than an eighth thing to remember. A guard that covers six of
272
+ * seven covers none: the attacker picks the seventh.
273
+ */
274
+ public getNotificationMethodIdColumns(): Array<string> {
275
+ return this.getNotificationMethodDescriptors().map(
276
+ (descriptor: NotificationMethodDescriptor): string => {
277
+ return descriptor.idColumn;
278
+ },
279
+ );
280
+ }
281
+
282
+ /*
283
+ * The ownership column's two spellings, derived from the model rather than
284
+ * restated here as literals.
285
+ *
286
+ * `userId` is a declared @Column; `user` is a @ManyToOne whose @JoinColumn
287
+ * names that same physical column. Two decorated members, one join column,
288
+ * and a payload may carry either or both — exactly the situation that made
289
+ * the method FKs bypassable, reproduced on the column that decides whose
290
+ * pages the row selects.
291
+ *
292
+ * The derivation ("relation name is the scalar minus its `Id` suffix") is the
293
+ * one CreatePermission.checkCreateOwnership uses, and it is deliberate that
294
+ * both places derive rather than hard-code: a model that renames its
295
+ * ownership column must not leave a guard silently reading a property that no
296
+ * longer exists.
297
+ */
298
+ private getRuleOwnerColumns(): RuleOwnerColumns | null {
299
+ const idColumn: string | null = new UserNotificationRule().getUserColumn();
300
+
301
+ if (!idColumn || !idColumn.endsWith("Id")) {
302
+ /*
303
+ * No user-scoped column, or one that does not follow the convention, so
304
+ * there is no second spelling to reconcile. Genuinely a no-op rather than
305
+ * a guard opening: with no ownership column there is no ownership to
306
+ * disagree about. Same reasoning as CreatePermission's `if (!userColumn)`.
307
+ */
308
+ return null;
309
+ }
310
+
311
+ return {
312
+ idColumn: idColumn,
313
+ relationColumn: idColumn.slice(0, -2),
314
+ };
315
+ }
316
+
317
+ /**
318
+ * Refuse a payload whose two spellings of the ownership column name two
319
+ * different users.
320
+ *
321
+ * The exact counterpart of assertOneMethodPerNotificationChannel below, on
322
+ * the other half of the pair this file exists to keep in agreement. A payload
323
+ * saying `userId: <victim>, user: { _id: <me> }` is not a client mistake — no
324
+ * dashboard sends both — it is a request for the guard and the ORM to read
325
+ * different owners, which is precisely how a validated write becomes a
326
+ * different persisted row.
327
+ *
328
+ * Refusing rather than silently preferring one spelling means the correctness
329
+ * of this file never rests on our reading of TypeORM's precedence rule. The
330
+ * fold below then removes the surviving redundancy, so nothing downstream —
331
+ * the roster check, the method-ownership check, CreatePermission, the audit
332
+ * line — has a precedence question left to resolve.
333
+ */
334
+ public assertOneRuleOwner(carrier: RuleColumnCarrier): void {
335
+ const columns: RuleOwnerColumns | null = this.getRuleOwnerColumns();
336
+
337
+ if (!columns) {
338
+ return;
339
+ }
340
+
341
+ const fromIdColumn: ObjectID | string | undefined = resolveReferenceId(
342
+ carrier[columns.idColumn],
343
+ );
344
+ const fromRelation: ObjectID | string | undefined = resolveReferenceId(
345
+ carrier[columns.relationColumn],
346
+ );
347
+
348
+ if (!fromIdColumn || !fromRelation) {
349
+ return;
350
+ }
351
+
352
+ /*
353
+ * Case-insensitively, for the reason ProjectScopedReferenceValidator
354
+ * normalises ids: ObjectID keeps whatever case it was handed while Postgres
355
+ * renders `uuid` lower case, so one id in two cases is still one id and
356
+ * must not read as a contradiction.
357
+ */
358
+ if (
359
+ fromIdColumn.toString().toLowerCase() ===
360
+ fromRelation.toString().toLowerCase()
361
+ ) {
362
+ return;
363
+ }
364
+
365
+ throw new BadDataException(
366
+ `This notification rule names two different users: ${columns.idColumn} says ${fromIdColumn.toString()} and ${columns.relationColumn} says ${fromRelation.toString()}. Send only one of them.`,
367
+ );
368
+ }
369
+
370
+ /**
371
+ * Fold the ownership relation into the ownership scalar so exactly one
372
+ * spelling survives a create.
373
+ *
374
+ * This is the same reduction collapseNotificationMethodRelationsOnCreate
375
+ * performs for the seven method FKs, and the same one
376
+ * CreatePermission.checkCreateOwnership performs for this very column — it
377
+ * validates `user` identically to `userId` and then CLEARS it, because after
378
+ * clearing there is no second source of truth left to disagree with the
379
+ * first. What CreatePermission cannot do is cover the administrator: it
380
+ * returns early for a caller holding a real role permission in the model's
381
+ * create list, which is exactly the caller this phase introduced and exactly
382
+ * the caller who may legitimately name somebody else. On that path the
383
+ * relation reached TypeORM unreduced.
384
+ *
385
+ * The relation's id is what is kept, because that is the value TypeORM would
386
+ * have written: the declared @Column and the relation's @JoinColumn share one
387
+ * ColumnMetadata, and getEntityValue reads the relation slot first, falling
388
+ * back to the scalar only when the relation holds no object. A relation slot
389
+ * that is present but carries no id therefore resolves to nothing, and
390
+ * clearing the scalar alongside it reproduces the NULL the ORM would have
391
+ * written rather than inventing an owner the row will not have.
392
+ *
393
+ * CREATE ONLY, though for a different reason than the method columns: `user`
394
+ * and `userId` are `update: []` for BOTH spellings on this model, so there is
395
+ * no update-path fold to consider at all — an update naming either one is
396
+ * refused outright by ColumnPermission.
397
+ */
398
+ public collapseRuleOwnerRelationOnCreate(carrier: RuleColumnCarrier): void {
399
+ const columns: RuleOwnerColumns | null = this.getRuleOwnerColumns();
400
+
401
+ if (!columns) {
402
+ return;
403
+ }
404
+
405
+ const relationValue: unknown = carrier[columns.relationColumn];
406
+
407
+ if (relationValue === undefined || relationValue === null) {
408
+ // Nothing in this spelling; TypeORM falls through to the scalar already.
409
+ return;
410
+ }
411
+
412
+ const resolved: ObjectID | string | undefined =
413
+ resolveReferenceId(relationValue);
414
+
415
+ carrier[columns.idColumn] = resolved
416
+ ? resolved instanceof ObjectID
417
+ ? resolved
418
+ : new ObjectID(resolved)
419
+ : undefined;
420
+
421
+ carrier[columns.relationColumn] = undefined;
422
+ }
423
+
424
+ /**
425
+ * Pull EVERY notification-method reference out of a create payload or an
426
+ * update patch — every channel, and every spelling of every channel.
427
+ *
428
+ * THE BUG THIS SHAPE EXISTS TO PREVENT. `userWebhookId` and `userWebhook` are
429
+ * two decorated members over ONE physical join column, and a request may
430
+ * carry both. This method used to resolve them as
431
+ * `carrier[idColumn] || carrier[relationColumn]`, which validates the FK
432
+ * column and never looks at the relation when both are present. TypeORM
433
+ * resolves the same conflict the other way round: the declared @Column and
434
+ * the relation's @JoinColumn share a single ColumnMetadata, and
435
+ * ColumnMetadata.getEntityValue reads the RELATION first, falling back to the
436
+ * scalar only when the relation slot holds no object.
437
+ *
438
+ * So the id that was checked and the id that was written were different ids,
439
+ * and the caller chose both. Put the rule owner's own method in the FK column
440
+ * to satisfy the guard, and your own row in the relation slot to be
441
+ * persisted, and R3 — the entire anti-hijack invariant — is a formality.
442
+ *
443
+ * The rule is therefore: never short-circuit. Emit one reference per spelling
444
+ * actually present, so the ownership check below has to answer for all of
445
+ * them, and a payload can no longer be right in the half that is inspected
446
+ * and wrong in the half that is written.
447
+ *
448
+ * Duplicates are folded only when they are the SAME id in the same column,
449
+ * where the second lookup could not produce a different answer. Two spellings
450
+ * naming two DIFFERENT ids stay two references on purpose — that is precisely
451
+ * the case worth an extra query.
452
+ *
453
+ * A rule that names no method at all yields an empty array and the ownership
454
+ * guard becomes a no-op — correct, because an opt-out row genuinely has no
455
+ * address to hijack.
456
+ */
457
+ public collectNotificationMethodReferences(
458
+ carrier: RuleColumnCarrier,
459
+ ): Array<NotificationMethodReference> {
460
+ const references: Array<NotificationMethodReference> = [];
461
+ const seen: Set<string> = new Set<string>();
462
+
463
+ for (const descriptor of this.getNotificationMethodDescriptors()) {
464
+ const spellings: Array<string> = [
465
+ descriptor.idColumn,
466
+ descriptor.relationColumn,
467
+ ];
468
+
469
+ for (const suppliedColumn of spellings) {
470
+ const resolved: ObjectID | string | undefined = resolveReferenceId(
471
+ carrier[suppliedColumn],
472
+ );
473
+
474
+ if (!resolved) {
475
+ continue;
476
+ }
477
+
478
+ const methodId: ObjectID =
479
+ resolved instanceof ObjectID ? resolved : new ObjectID(resolved);
480
+
481
+ /*
482
+ * Ids are compared case-insensitively for the same reason
483
+ * ProjectScopedReferenceValidator normalises them: ObjectID keeps
484
+ * whatever case it was handed, while Postgres renders `uuid` in lower
485
+ * case, so an uppercase spelling and a lowercase one are one id.
486
+ */
487
+ const key: string = `${descriptor.idColumn}:${methodId
488
+ .toString()
489
+ .toLowerCase()}`;
490
+
491
+ if (seen.has(key)) {
492
+ continue;
493
+ }
494
+
495
+ seen.add(key);
496
+
497
+ references.push({
498
+ idColumn: descriptor.idColumn,
499
+ suppliedColumn: suppliedColumn,
500
+ label: descriptor.label,
501
+ methodId: methodId,
502
+ });
503
+ }
504
+ }
505
+
506
+ return references;
507
+ }
508
+
509
+ /**
510
+ * Refuse a payload whose two spellings of one method column name two
511
+ * different methods.
512
+ *
513
+ * Validating both spellings (above) closes the hijack: whichever one the ORM
514
+ * picks, it has been checked against the rule's owner. What it does not do is
515
+ * make the write PREDICTABLE — with both slots filled, which address the rule
516
+ * ends up delivering to is decided by a TypeORM precedence rule that no
517
+ * reader of this codebase should have to know, and that a TypeORM upgrade is
518
+ * free to change.
519
+ *
520
+ * "Both spellings, two different methods" is not something a client does by
521
+ * accident; the dashboard sends one. So there is no legitimate request to
522
+ * preserve here, and refusing is strictly better than guessing: the caller is
523
+ * told exactly what is contradictory, and nothing downstream has a precedence
524
+ * question left to resolve.
525
+ *
526
+ * Deliberately NOT run before the ownership check. A payload that is both
527
+ * ambiguous and a hijack attempt should be reported as the hijack — that is
528
+ * the finding an operator needs to see, and "you sent the same field twice"
529
+ * would bury it.
530
+ */
531
+ public assertOneMethodPerNotificationChannel(
532
+ carrier: RuleColumnCarrier,
533
+ ): void {
534
+ for (const descriptor of this.getNotificationMethodDescriptors()) {
535
+ const fromIdColumn: ObjectID | string | undefined = resolveReferenceId(
536
+ carrier[descriptor.idColumn],
537
+ );
538
+ const fromRelation: ObjectID | string | undefined = resolveReferenceId(
539
+ carrier[descriptor.relationColumn],
540
+ );
541
+
542
+ if (!fromIdColumn || !fromRelation) {
543
+ continue;
544
+ }
545
+
546
+ if (
547
+ fromIdColumn.toString().toLowerCase() ===
548
+ fromRelation.toString().toLowerCase()
549
+ ) {
550
+ continue;
551
+ }
552
+
553
+ throw new BadDataException(
554
+ `This notification rule names two different ${descriptor.label} notification methods: ${descriptor.idColumn} says ${fromIdColumn.toString()} and ${descriptor.relationColumn} says ${fromRelation.toString()}. Send only one of them.`,
555
+ );
556
+ }
557
+ }
558
+
559
+ /**
560
+ * Fold the relation spelling into the FK column so exactly one spelling
561
+ * survives — the create-path reduction, and the reason the ORM never gets to
562
+ * choose.
563
+ *
564
+ * This mirrors CreatePermission.checkCreateOwnership, which validates the
565
+ * `user` relation identically to the `userId` scalar and then CLEARS it. The
566
+ * point of clearing rather than merely checking is that after it there is no
567
+ * second source of truth left to disagree with the first.
568
+ *
569
+ * The relation's id is what is kept, because that is the value TypeORM would
570
+ * have written: getEntityValue reads the relation slot first. A relation slot
571
+ * that is present but carries no id resolves to nothing, and clearing the FK
572
+ * column alongside it reproduces the NULL the ORM would have written — which
573
+ * matters, because that NULL is what turns a rule into one that pages
574
+ * nowhere, and the create invariants below have to be able to see it.
575
+ *
576
+ * CREATE ONLY. On update the two spellings do not have the same access
577
+ * control: the relation members are `update: []` on UserNotificationRule
578
+ * while the `*Id` members are open to an administrator, so moving a value
579
+ * from the relation slot into the FK column would launder a column write that
580
+ * ColumnPermission (which runs after the update hook) exists to refuse. On
581
+ * that path ambiguity is resolved by refusal instead — see
582
+ * assertOneMethodPerNotificationChannel.
583
+ */
584
+ public collapseNotificationMethodRelationsOnCreate(
585
+ carrier: RuleColumnCarrier,
586
+ ): void {
587
+ for (const descriptor of this.getNotificationMethodDescriptors()) {
588
+ const relationValue: unknown = carrier[descriptor.relationColumn];
589
+
590
+ if (relationValue === undefined || relationValue === null) {
591
+ /*
592
+ * Nothing supplied in this spelling. TypeORM falls through to the
593
+ * scalar in exactly this case, so there is nothing to fold and nothing
594
+ * to clear.
595
+ */
596
+ continue;
597
+ }
598
+
599
+ const resolved: ObjectID | string | undefined =
600
+ resolveReferenceId(relationValue);
601
+
602
+ carrier[descriptor.idColumn] = resolved
603
+ ? resolved instanceof ObjectID
604
+ ? resolved
605
+ : new ObjectID(resolved)
606
+ : undefined;
607
+
608
+ carrier[descriptor.relationColumn] = undefined;
609
+ }
610
+ }
611
+
612
+ /**
613
+ * Does this payload name a delivery address at all, in any channel, in either
614
+ * spelling?
615
+ *
616
+ * Driven off the descriptor table rather than a hand-written list of fourteen
617
+ * property names. A hand-written list is how an eighth channel ends up
618
+ * exempt from the "a rule must be able to reach somebody" invariant, and an
619
+ * exempt channel is a rule that silently pages nobody.
620
+ */
621
+ public carriesAnyNotificationMethod(carrier: RuleColumnCarrier): boolean {
622
+ for (const descriptor of this.getNotificationMethodDescriptors()) {
623
+ if (carrier[descriptor.idColumn] || carrier[descriptor.relationColumn]) {
624
+ return true;
625
+ }
626
+ }
627
+
628
+ return false;
629
+ }
630
+
631
+ /**
632
+ * Does this patch MENTION a delivery address, whatever it sets it to?
633
+ *
634
+ * Distinct from carriesAnyNotificationMethod, and the difference is the whole
635
+ * point: `userEmailId: null` carries no method but very much mentions one. It
636
+ * is the write that removes a rule's only way of reaching somebody, so it is
637
+ * exactly the patch the coherence check must not skip.
638
+ */
639
+ public mentionsAnyNotificationMethodColumn(
640
+ carrier: RuleColumnCarrier,
641
+ ): boolean {
642
+ for (const descriptor of this.getNotificationMethodDescriptors()) {
643
+ if (
644
+ carrier[descriptor.idColumn] !== undefined ||
645
+ carrier[descriptor.relationColumn] !== undefined
646
+ ) {
647
+ return true;
648
+ }
649
+ }
650
+
651
+ return false;
652
+ }
653
+
654
+ /**
655
+ * The row's delivery addresses as they would stand AFTER a patch is applied.
656
+ *
657
+ * The create-time invariants ("a rule that pages must name a method", "an
658
+ * opt-out rule must not") are properties of the ROW, and update can break
659
+ * both of them: flipping `isOptOut` on a rule that carries an email, or
660
+ * nulling the only method on a rule that is still meant to page. Neither is
661
+ * visible from the patch alone, so the persisted row has to be read and the
662
+ * two combined.
663
+ *
664
+ * Precedence between the two spellings is the ORM's, not ours: the relation
665
+ * slot wins when it is present, because that is what would be written. A
666
+ * column the patch does not mention keeps whatever the row already had.
667
+ */
668
+ public getNotificationMethodIdsAfterPatch(data: {
669
+ patch: RuleColumnCarrier;
670
+ currentRow: RuleColumnCarrier;
671
+ }): Array<ObjectID> {
672
+ const methodIds: Array<ObjectID> = [];
673
+
674
+ for (const descriptor of this.getNotificationMethodDescriptors()) {
675
+ let resolved: ObjectID | string | undefined = undefined;
676
+
677
+ if (data.patch[descriptor.relationColumn] !== undefined) {
678
+ resolved = resolveReferenceId(data.patch[descriptor.relationColumn]);
679
+ } else if (data.patch[descriptor.idColumn] !== undefined) {
680
+ resolved = resolveReferenceId(data.patch[descriptor.idColumn]);
681
+ } else {
682
+ resolved = resolveReferenceId(data.currentRow[descriptor.idColumn]);
683
+ }
684
+
685
+ if (!resolved) {
686
+ continue;
687
+ }
688
+
689
+ methodIds.push(
690
+ resolved instanceof ObjectID ? resolved : new ObjectID(resolved),
691
+ );
692
+ }
693
+
694
+ return methodIds;
695
+ }
696
+
697
+ /**
698
+ * R1 — the target of an on-behalf-of write must belong to the project the
699
+ * write is scoped to.
700
+ *
701
+ * The create-path ownership gate (CreatePermission.checkCreateOwnership)
702
+ * deliberately steps aside for a caller who holds a real role permission in
703
+ * the model's create list, so that this feature can exist at all. What it
704
+ * hands over is a caller who may name SOME other user — it says nothing about
705
+ * WHICH other users are in scope, because it has no notion of a project
706
+ * roster. Left there, holding ProjectAdmin on one throwaway project would be
707
+ * a licence to write notification rules for any user id in the installation.
708
+ *
709
+ * Membership is read straight from TeamMember with isRoot props and no cache.
710
+ * TeamMemberService.getTeamIdsForUser would have answered the same question
711
+ * with one fewer query, but it memoises for 60 seconds — and a security
712
+ * decision that keeps saying "yes" for a minute after the user was removed
713
+ * from the project is not a security decision.
714
+ *
715
+ * `hasAcceptedInvitation` is part of the test because it is this codebase's
716
+ * own definition of membership (the Owned permission scope resolves teams the
717
+ * same way), and because a pending invitation is an admin-created row: any
718
+ * admin can create one for any email address, so treating one as membership
719
+ * would hand back most of what this guard just took away. Nothing legitimate
720
+ * is lost — a rule must carry a notification method to be created at all, and
721
+ * a user who has not joined the project has none.
722
+ */
723
+ @CaptureSpan()
724
+ public async assertTargetUserIsProjectMember(data: {
725
+ targetUserId: ObjectID;
726
+ props: DatabaseCommonInteractionProps;
727
+ }): Promise<void> {
728
+ const projectId: ObjectID | undefined = data.props.tenantId;
729
+
730
+ if (!projectId) {
731
+ /*
732
+ * A non-root caller writing another user's rule without a tenant scope
733
+ * has nothing to be an admin OF. There is no roster to check them
734
+ * against, so there is no way to say yes.
735
+ */
736
+ throw new BadDataException(
737
+ "A project is required to create a notification rule for another user.",
738
+ );
739
+ }
740
+
741
+ const membership: TeamMember | null = await TeamMemberService.findOneBy({
742
+ query: {
743
+ userId: data.targetUserId,
744
+ projectId: projectId,
745
+ hasAcceptedInvitation: true,
746
+ },
747
+ select: {
748
+ _id: true,
749
+ },
750
+ props: {
751
+ isRoot: true,
752
+ },
753
+ });
754
+
755
+ if (!membership) {
756
+ throw new BadDataException(
757
+ `Cannot create a notification rule for user ${data.targetUserId.toString()} because they are not a member of this project.`,
758
+ );
759
+ }
760
+ }
761
+
762
+ /**
763
+ * R3 — the anti-hijack invariant, and the single most important guard in this
764
+ * phase.
765
+ *
766
+ * A rule's method FK is the address its pages are delivered to. Its userId is
767
+ * whose pages select it. If those two can name different people, an admin
768
+ * editing a colleague's rule to point at the ADMIN's own webhook silently
769
+ * redirects that colleague's pages, and every surface either of them can see
770
+ * still reports a healthy configuration.
771
+ *
772
+ * `ownerUserId` MUST be the rule's persisted owner, not a value out of the
773
+ * request body. On update the caller controls the body, so a body-supplied
774
+ * userId lets them claim the row is theirs while writing somebody else's; the
775
+ * callers in UserNotificationRuleService therefore re-read it from the
776
+ * database first, and pass what the database said.
777
+ *
778
+ * A method row that does not exist is rejected rather than ignored. "Not
779
+ * found" and "not yours" are the same answer here — in both cases the caller
780
+ * named a row they have no business naming — and a guard whose failure mode
781
+ * is `undefined === undefined` is a guard that opens on the one input it was
782
+ * written to reject.
783
+ */
784
+ @CaptureSpan()
785
+ public async assertNotificationMethodsBelongToUser(data: {
786
+ ownerUserId: ObjectID | undefined;
787
+ references: Array<NotificationMethodReference>;
788
+ }): Promise<void> {
789
+ if (data.references.length === 0) {
790
+ return;
791
+ }
792
+
793
+ if (!data.ownerUserId) {
794
+ /*
795
+ * An unowned rule is not a safe rule. Its userId decides whose pages
796
+ * select it, so a row that names an address but no owner is a row nobody
797
+ * can be shown and nobody can audit. Reject rather than skip the check.
798
+ */
799
+ throw new BadDataException(
800
+ "A notification rule that names a notification method must have an owner.",
801
+ );
802
+ }
803
+
804
+ const descriptorsByColumn: Map<string, NotificationMethodDescriptor> =
805
+ new Map<string, NotificationMethodDescriptor>();
806
+
807
+ for (const descriptor of this.getNotificationMethodDescriptors()) {
808
+ descriptorsByColumn.set(descriptor.idColumn, descriptor);
809
+ }
810
+
811
+ for (const reference of data.references) {
812
+ const descriptor: NotificationMethodDescriptor | undefined =
813
+ descriptorsByColumn.get(reference.idColumn);
814
+
815
+ if (!descriptor) {
816
+ /*
817
+ * Unreachable while references only ever come from
818
+ * collectNotificationMethodReferences, which builds them from this same
819
+ * table. Refusing an unknown column rather than skipping it keeps that
820
+ * true if the two ever drift.
821
+ */
822
+ throw new BadDataException(
823
+ `Unknown notification method column ${reference.idColumn}.`,
824
+ );
825
+ }
826
+
827
+ const methodOwnerUserId: ObjectID | undefined =
828
+ await descriptor.findOwnerUserId(reference.methodId);
829
+
830
+ if (!methodOwnerUserId) {
831
+ throw new BadDataException(
832
+ `The ${descriptor.label} notification method referenced by this rule does not exist.`,
833
+ );
834
+ }
835
+
836
+ if (methodOwnerUserId.toString() !== data.ownerUserId.toString()) {
837
+ /*
838
+ * The spelling is named at the end rather than woven into the sentence
839
+ * so that the wording support runbooks and tests match on stays intact.
840
+ * It earns its place because the two spellings are one column: told only
841
+ * "your Email method is wrong", a caller looking at a payload whose
842
+ * `userEmailId` is perfectly correct has no way to see that the relation
843
+ * slot beside it is the problem.
844
+ */
845
+ throw new BadDataException(
846
+ `The ${descriptor.label} notification method referenced by this rule belongs to a different user. A notification rule can only use notification methods owned by the user the rule belongs to. The offending value was sent in ${reference.suppliedColumn}.`,
847
+ );
848
+ }
849
+ }
850
+ }
851
+
852
+ /**
853
+ * R6 — record and announce a change one person made to another person's
854
+ * paging configuration.
855
+ *
856
+ * Both halves are keyed on `props.userId` — the actor the SERVER resolved
857
+ * from the session — versus the row's PERSISTED userId, read back after the
858
+ * write. Nothing here reads the request body: the body is the thing under
859
+ * suspicion, and an audit line that an attacker can author is worse than no
860
+ * audit line, because it looks like evidence.
861
+ *
862
+ * Nothing in here may break the write. The row is already committed by the
863
+ * time this runs; throwing now would report a failure for a change that
864
+ * happened, and the caller would be entitled to believe it did not. So the
865
+ * whole body is a try/catch, and the mail is fire-and-forget on top of that.
866
+ */
867
+ @CaptureSpan()
868
+ public async recordAdminRuleChange(data: {
869
+ action: AuditLogAction;
870
+ actorUserId: ObjectID;
871
+ ownerUserId: ObjectID;
872
+ projectId: ObjectID | undefined;
873
+ /*
874
+ * `null` as well as `undefined`, because BaseModel.id is a getter over
875
+ * `_id` and returns null for a row that has none. Both mean the same thing
876
+ * here — no row to point the audit entry at — and typing only one of them
877
+ * makes every call site cast.
878
+ */
879
+ ruleId: ObjectID | null | undefined;
880
+ /*
881
+ * The row as it stood before the write. Absent on create. On delete this is
882
+ * the whole of the record that is left: the row is gone, so this snapshot
883
+ * is the only description of what the project just lost.
884
+ */
885
+ before?: UserNotificationRule | undefined;
886
+ /** The row as it stands after the write. Absent on update and delete. */
887
+ after?: UserNotificationRule | undefined;
888
+ /** The patch, for the update diff. Absent on create and delete. */
889
+ updatedFields?: JSONObject | undefined;
890
+ /*
891
+ * Whether to mail the owner. The audit entry is per ROW because that is
892
+ * what an investigator needs to reconstruct; the mail is per PERSON,
893
+ * because one request that touches twenty of somebody's rules is still one
894
+ * thing that happened to them, and twenty identical mails is how a warning
895
+ * becomes a filter rule.
896
+ */
897
+ notifyOwner: boolean;
898
+ props: DatabaseCommonInteractionProps;
899
+ }): Promise<void> {
900
+ try {
901
+ /*
902
+ * The dependable half of the trail. AuditLogService below only writes on
903
+ * enterprise builds with audit logs switched on for the project, which is
904
+ * a minority of installs — and "an admin edited somebody else's paging"
905
+ * is exactly the event an operator needs to be able to find on the other
906
+ * ones too.
907
+ */
908
+ logger.info(
909
+ `On-call notification rule ${data.action.toLowerCase()}d for user ${data.ownerUserId.toString()} by a different user ${data.actorUserId.toString()}.`,
910
+ {
911
+ projectId: data.projectId?.toString(),
912
+ userId: data.ownerUserId.toString(),
913
+ actorUserId: data.actorUserId.toString(),
914
+ userNotificationRuleId: data.ruleId?.toString(),
915
+ action: data.action,
916
+ } as LogAttributes,
917
+ );
918
+
919
+ await this.writeAuditLog(data);
920
+
921
+ if (!data.notifyOwner) {
922
+ return;
923
+ }
924
+
925
+ /*
926
+ * Fire-and-forget by construction: the owner's mail involves three more
927
+ * reads and an SMTP round trip, none of which the writing request should
928
+ * wait on and none of which may surface as a failed write.
929
+ */
930
+ this.notifyOwnerOfAdminChange({
931
+ action: data.action,
932
+ actorUserId: data.actorUserId,
933
+ ownerUserId: data.ownerUserId,
934
+ projectId: data.projectId,
935
+ }).catch((error: Error): void => {
936
+ logger.error(
937
+ `UserNotificationRuleAdminService: failed to tell user ${data.ownerUserId.toString()} that an admin changed their on-call notification rules.`,
938
+ );
939
+ logger.error(error);
940
+ });
941
+ } catch (error) {
942
+ logger.error(
943
+ "UserNotificationRuleAdminService: failed to record an administrative notification rule change.",
944
+ );
945
+ logger.error(error);
946
+ }
947
+ }
948
+
949
+ /*
950
+ * The AuditLog analytics row, written directly rather than through
951
+ * DatabaseService's own audit hook.
952
+ *
953
+ * DatabaseService writes one automatically for models decorated with
954
+ * @EnableAuditLog, and UserNotificationRule is not one of them — so without
955
+ * this call an administrative edit leaves no row at all. The decorator is
956
+ * checked anyway so that adding it later produces one entry rather than two:
957
+ * a duplicated audit record is not merely noise, it makes a reader count two
958
+ * changes where one happened.
959
+ *
960
+ * Required lazily for the same reason DatabaseService requires it lazily —
961
+ * AuditLogService depends on ProjectService and UserService, both of which
962
+ * extend DatabaseService, so a top-level import can leave the base class
963
+ * undefined at class-extension time.
964
+ */
965
+ private async writeAuditLog(data: {
966
+ action: AuditLogAction;
967
+ ruleId: ObjectID | null | undefined;
968
+ before?: UserNotificationRule | undefined;
969
+ after?: UserNotificationRule | undefined;
970
+ updatedFields?: JSONObject | undefined;
971
+ props: DatabaseCommonInteractionProps;
972
+ }): Promise<void> {
973
+ const model: UserNotificationRule = new UserNotificationRule();
974
+
975
+ if (model.enableAuditLogOn) {
976
+ // DatabaseService already writes this row; a second one would double-count.
977
+ return;
978
+ }
979
+
980
+ const auditLogService: typeof AuditLogServiceType =
981
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
982
+ require("./AuditLogService").default;
983
+
984
+ if (data.action === AuditLogAction.Create && data.after) {
985
+ await auditLogService.recordCreate({
986
+ model: model,
987
+ createdItem: data.after,
988
+ props: data.props,
989
+ });
990
+
991
+ return;
992
+ }
993
+
994
+ if (data.action === AuditLogAction.Update && data.before && data.ruleId) {
995
+ await auditLogService.recordUpdate({
996
+ model: model,
997
+ before: data.before,
998
+ updatedFields: data.updatedFields || {},
999
+ itemId: data.ruleId,
1000
+ props: data.props,
1001
+ });
1002
+
1003
+ return;
1004
+ }
1005
+
1006
+ /*
1007
+ * Delete is the one action whose audit entry cannot be reconstructed after
1008
+ * the fact. An edited row can still be read; a deleted one cannot, so the
1009
+ * snapshot captured before the write is the entire record of what the
1010
+ * responder's paging used to be.
1011
+ */
1012
+ if (data.action === AuditLogAction.Delete && data.before && data.ruleId) {
1013
+ await auditLogService.recordDelete({
1014
+ model: model,
1015
+ deletedItem: data.before,
1016
+ itemId: data.ruleId,
1017
+ props: data.props,
1018
+ });
1019
+ }
1020
+ }
1021
+
1022
+ /*
1023
+ * Tell the person whose pages just changed.
1024
+ *
1025
+ * This is the part of the phase that makes admin repair safe to hand out
1026
+ * rather than merely possible: an admin fixing a colleague's rules is a
1027
+ * normal, welcome thing, and an attacker redirecting them is not, and from
1028
+ * the server's side those two are the same request. The only reliable way to
1029
+ * tell them apart is to ask the one person who always knows which it was.
1030
+ */
1031
+ private async notifyOwnerOfAdminChange(data: {
1032
+ action: AuditLogAction;
1033
+ actorUserId: ObjectID;
1034
+ ownerUserId: ObjectID;
1035
+ projectId: ObjectID | undefined;
1036
+ }): Promise<void> {
1037
+ const owner: User | null = await UserService.findOneById({
1038
+ id: data.ownerUserId,
1039
+ select: {
1040
+ _id: true,
1041
+ name: true,
1042
+ email: true,
1043
+ },
1044
+ props: {
1045
+ isRoot: true,
1046
+ },
1047
+ });
1048
+
1049
+ if (!owner || !owner.email) {
1050
+ return;
1051
+ }
1052
+
1053
+ const actor: User | null = await UserService.findOneById({
1054
+ id: data.actorUserId,
1055
+ select: {
1056
+ _id: true,
1057
+ name: true,
1058
+ email: true,
1059
+ },
1060
+ props: {
1061
+ isRoot: true,
1062
+ },
1063
+ });
1064
+
1065
+ /*
1066
+ * Naming the actor by email as well as by name is deliberate. Display names
1067
+ * are not unique and are user-editable, so "Alex changed your rules" is not
1068
+ * something the reader can act on; an address is.
1069
+ */
1070
+ const actorDescription: string = actor
1071
+ ? `${actor.name?.toString() || "A project administrator"} (${
1072
+ actor.email?.toString() || data.actorUserId.toString()
1073
+ })`
1074
+ : `A project administrator (${data.actorUserId.toString()})`;
1075
+
1076
+ let projectName: string = "your project";
1077
+
1078
+ if (data.projectId) {
1079
+ const project: Project | null = await ProjectService.findOneById({
1080
+ id: data.projectId,
1081
+ select: {
1082
+ _id: true,
1083
+ name: true,
1084
+ },
1085
+ props: {
1086
+ isRoot: true,
1087
+ },
1088
+ });
1089
+
1090
+ if (project?.name) {
1091
+ projectName = project.name;
1092
+ }
1093
+ }
1094
+
1095
+ let verb: string = "changed";
1096
+
1097
+ if (data.action === AuditLogAction.Create) {
1098
+ verb = "added";
1099
+ }
1100
+
1101
+ if (data.action === AuditLogAction.Delete) {
1102
+ verb = "deleted";
1103
+ }
1104
+
1105
+ const subject: string = `Your on-call notification rules were ${verb} by an administrator`;
1106
+
1107
+ const settingsLink: string = data.projectId
1108
+ ? (
1109
+ await this.getNotificationRulesLinkInDashboard(data.projectId)
1110
+ ).toString()
1111
+ : "";
1112
+
1113
+ /*
1114
+ * Deletion gets its own sentence rather than the generic one. "Somebody
1115
+ * changed your rules" is a prompt to go and look; "you may no longer be
1116
+ * paged" is the consequence, and it is the only one of the three actions
1117
+ * that can leave a responder silently unreachable — which is the failure
1118
+ * this whole epic exists to stop happening unnoticed.
1119
+ */
1120
+ const consequence: string =
1121
+ data.action === AuditLogAction.Delete
1122
+ ? "Your notification rules decide how OneUptime reaches you when you are paged. With them removed you may no longer be notified when you are on call, so add new rules if this was not what you expected, and tell your project owners."
1123
+ : "Your notification rules decide how OneUptime reaches you when you are paged. If you were not expecting this change, review your rules now and tell your project owners.";
1124
+
1125
+ const message: string = `${this.escapeHtml(actorDescription)} ${verb} your on-call notification rules in ${this.escapeHtml(
1126
+ projectName,
1127
+ )}.<br/><br/>${consequence}${
1128
+ settingsLink
1129
+ ? `<br/><br/><a href="${this.escapeHtml(settingsLink)}">Review your notification rules</a>`
1130
+ : ""
1131
+ }`;
1132
+
1133
+ const vars: Dictionary<string> = {
1134
+ subject: subject,
1135
+ message: message,
1136
+ };
1137
+
1138
+ await MailService.sendMail(
1139
+ {
1140
+ toEmail: owner.email,
1141
+ templateType: EmailTemplateType.SimpleMessage,
1142
+ vars: vars,
1143
+ subject: subject,
1144
+ },
1145
+ {
1146
+ projectId: data.projectId,
1147
+ userId: owner.id!,
1148
+ },
1149
+ );
1150
+ }
1151
+
1152
+ private async getNotificationRulesLinkInDashboard(
1153
+ projectId: ObjectID,
1154
+ ): Promise<URL> {
1155
+ const dashboardUrl: URL = await DatabaseConfig.getDashboardUrl();
1156
+
1157
+ /*
1158
+ * Spelled out rather than imported: Common/Server cannot reach the
1159
+ * Dashboard's RouteMap, the same reason
1160
+ * OnCallNotificationAlertingService.getNotificationRulesLinkInDashboard
1161
+ * duplicates its path segments.
1162
+ */
1163
+ return URL.fromString(dashboardUrl.toString()).addRoute(
1164
+ `/${projectId.toString()}/user-settings/notification-methods`,
1165
+ );
1166
+ }
1167
+
1168
+ /*
1169
+ * SimpleMessage.hbs renders `message` through a triple-stache InfoBlock
1170
+ * partial, so nothing between here and the recipient's inbox escapes
1171
+ * anything. Project names and user names are attacker-influenced free text.
1172
+ */
1173
+ private escapeHtml(value: string): string {
1174
+ return value
1175
+ .replace(/&/g, "&amp;")
1176
+ .replace(/</g, "&lt;")
1177
+ .replace(/>/g, "&gt;")
1178
+ .replace(/"/g, "&quot;")
1179
+ .replace(/'/g, "&#39;");
1180
+ }
1181
+ }
1182
+
1183
+ export default new UserNotificationRuleAdminService();