@oneuptime/common 14.0.1 → 14.0.3

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 (1241) hide show
  1. package/Models/DatabaseModels/AlertEpisodeMember.ts +8 -1
  2. package/Models/DatabaseModels/AlertFeed.ts +2 -0
  3. package/Models/DatabaseModels/AutoRemediationSuggestion.ts +63 -0
  4. package/Models/DatabaseModels/IncidentAlert.ts +540 -0
  5. package/Models/DatabaseModels/IncidentEpisodeMember.ts +8 -1
  6. package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +9 -2
  7. package/Models/DatabaseModels/IncidentFeed.ts +2 -0
  8. package/Models/DatabaseModels/IncidentPublicNote.ts +9 -2
  9. package/Models/DatabaseModels/Index.ts +2 -0
  10. package/Models/DatabaseModels/KubernetesCluster.ts +429 -0
  11. package/Models/DatabaseModels/Monitor.ts +48 -0
  12. package/Models/DatabaseModels/Project.ts +60 -0
  13. package/Models/DatabaseModels/RumApplication.ts +52 -1
  14. package/Models/DatabaseModels/Runner.ts +5 -4
  15. package/Models/DatabaseModels/RunnerJob.ts +66 -0
  16. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +10 -2
  17. package/Models/DatabaseModels/WorkflowVariable.ts +479 -2
  18. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +79 -25
  19. package/Server/API/AIInvestigationAPI.ts +341 -0
  20. package/Server/API/AutoRemediationAPI.ts +184 -2
  21. package/Server/API/CommonAPI.ts +70 -0
  22. package/Server/API/KubernetesClusterAiAccessAPI.ts +793 -0
  23. package/Server/API/MicrosoftTeamsAPI.ts +770 -315
  24. package/Server/API/MonitorAPI.ts +140 -0
  25. package/Server/API/OnCallScheduleTimelineAPI.ts +5 -21
  26. package/Server/API/SlackAPI.ts +447 -99
  27. package/Server/API/StatusPageAPI.ts +146 -26
  28. package/Server/API/TelemetryAPI.ts +216 -5
  29. package/Server/API/UserTwoFactorBackupCodeAPI.ts +1 -0
  30. package/Server/API/WorkflowVariableAPI.ts +156 -0
  31. package/Server/Infrastructure/GlobalCache.ts +35 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1794300000000-AddOAuth2WorkflowVariables.ts +97 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/1794400000000-AddKubernetesClusterAiAccess.ts +129 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/1794500000000-AddIncomingEmailCustomAddressToMonitor.ts +25 -0
  35. package/Server/Infrastructure/Postgres/SchemaMigrations/1794600000000-AddAuthTokenExpiresAtToWorkspaceProjectAuthToken.ts +20 -0
  36. package/Server/Infrastructure/Postgres/SchemaMigrations/1794700000000-RemoveAppAccessTokenFromWorkspaceProjectAuthTokenMiscData.ts +38 -0
  37. package/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.ts +28 -0
  38. package/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.ts +89 -0
  39. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
  40. package/Server/Middleware/MasterAdminAuthorization.ts +28 -0
  41. package/Server/Middleware/TelemetryIngest.ts +47 -2
  42. package/Server/Middleware/UserAuthorization.ts +56 -2
  43. package/Server/Services/AIAgentService.ts +1 -0
  44. package/Server/Services/AccessTokenService.ts +121 -48
  45. package/Server/Services/AlertEpisodeMemberService.ts +9 -0
  46. package/Server/Services/AlertEpisodeService.ts +14 -1
  47. package/Server/Services/AlertService.ts +134 -22
  48. package/Server/Services/AutoRemediationRuleEngineService.ts +968 -39
  49. package/Server/Services/AutoRemediationRuleService.ts +118 -0
  50. package/Server/Services/BillingService.ts +1 -0
  51. package/Server/Services/InboundEmail/Providers/SendGridInboundProvider.ts +16 -22
  52. package/Server/Services/IncidentAlertService.ts +1811 -0
  53. package/Server/Services/IncidentEpisodeMemberService.ts +9 -0
  54. package/Server/Services/IncidentEpisodePublicNoteService.ts +66 -0
  55. package/Server/Services/IncidentEpisodeRoleMemberService.ts +27 -0
  56. package/Server/Services/IncidentEpisodeService.ts +14 -1
  57. package/Server/Services/IncidentGroupingEngineService.ts +11 -0
  58. package/Server/Services/IncidentMemberService.ts +21 -0
  59. package/Server/Services/IncidentPublicNoteService.ts +63 -0
  60. package/Server/Services/IncidentService.ts +330 -30
  61. package/Server/Services/IncidentStateTimelineService.ts +39 -0
  62. package/Server/Services/IncidentTemplateService.ts +83 -3
  63. package/Server/Services/Index.ts +2 -0
  64. package/Server/Services/KubernetesClusterAiAccessService.ts +1943 -0
  65. package/Server/Services/KubernetesClusterService.ts +1570 -1
  66. package/Server/Services/LogAggregationService.ts +14 -6
  67. package/Server/Services/MonitorService.ts +651 -52
  68. package/Server/Services/MonitorStatusTimelineService.ts +639 -2
  69. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +2 -0
  70. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +2 -0
  71. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +2 -0
  72. package/Server/Services/OnCallDutyPolicyScheduleService.ts +3 -0
  73. package/Server/Services/OnCallNotificationAlertingService.ts +36 -12
  74. package/Server/Services/OnCallSetupReminderService.ts +1 -0
  75. package/Server/Services/ProbeService.ts +7 -1
  76. package/Server/Services/ProjectService.ts +11 -1
  77. package/Server/Services/RunbookCredentialService.ts +26 -1
  78. package/Server/Services/RunbookSecretService.ts +36 -0
  79. package/Server/Services/RunnerJobService.ts +941 -23
  80. package/Server/Services/RunnerService.ts +439 -6
  81. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +66 -0
  82. package/Server/Services/ScheduledMaintenanceService.ts +124 -19
  83. package/Server/Services/ScheduledMaintenanceTemplateService.ts +82 -3
  84. package/Server/Services/ServiceLevelObjectiveService.ts +14 -1
  85. package/Server/Services/StatusPagePrivateUserService.ts +1 -0
  86. package/Server/Services/StatusPageService.ts +301 -74
  87. package/Server/Services/StatusPageSubscriberService.ts +4 -0
  88. package/Server/Services/TeamMemberService.ts +309 -7
  89. package/Server/Services/TraceAggregationService.ts +10 -6
  90. package/Server/Services/UserEmailService.ts +1 -0
  91. package/Server/Services/UserNotificationMethodAdminService.ts +1 -0
  92. package/Server/Services/UserNotificationRuleAdminService.ts +1 -0
  93. package/Server/Services/UserNotificationRuleService.ts +4 -0
  94. package/Server/Services/UserService.ts +122 -1
  95. package/Server/Services/WorkflowVariableService.ts +593 -8
  96. package/Server/Services/WorkspaceNotificationRuleService.ts +588 -8
  97. package/Server/Services/WorkspaceProjectAuthTokenService.ts +170 -1
  98. package/Server/Types/Database/QueryHelper.ts +22 -0
  99. package/Server/Types/Markdown.ts +502 -27
  100. package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +182 -0
  101. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +525 -0
  102. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +854 -0
  103. package/Server/Utils/AI/CodeFix/CodeFixAgentAuth.ts +22 -2
  104. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1916 -307
  105. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +1601 -74
  106. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +139 -7
  107. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +58 -1
  108. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +54 -1
  109. package/Server/Utils/AI/Toolbox/AIActionTools.ts +14 -6
  110. package/Server/Utils/AI/Toolbox/ResourceTools.ts +4 -2
  111. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +1341 -150
  112. package/Server/Utils/AutoRemediation/RemediationVerifier.ts +375 -4
  113. package/Server/Utils/Database/AffectedResourceRelations.ts +127 -0
  114. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +240 -1
  115. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +1 -0
  116. package/Server/Utils/Monitor/MonitorAlert.ts +83 -9
  117. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +5 -1
  118. package/Server/Utils/Monitor/MonitorIncident.ts +104 -9
  119. package/Server/Utils/Monitor/MonitorPayloadRedaction.ts +124 -7
  120. package/Server/Utils/Monitor/ProbeMonitorsNotification.ts +407 -0
  121. package/Server/Utils/OnCall/OnCallShiftReminderRunner.ts +1 -0
  122. package/Server/Utils/PushNotificationUtil.ts +45 -0
  123. package/Server/Utils/Rules/OwnerRuleAssignment.ts +40 -3
  124. package/Server/Utils/Runbook/RunbookExecutePermission.ts +56 -6
  125. package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +24 -2
  126. package/Server/Utils/SessionReplay/SessionReplayReadService.ts +223 -33
  127. package/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.ts +559 -0
  128. package/Server/Utils/StartServer.ts +4 -3
  129. package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +528 -0
  130. package/Server/Utils/TwoFactorBackupCodeNotification.ts +1 -0
  131. package/Server/Utils/UserPermission/UserPermission.ts +16 -0
  132. package/Server/Utils/Workflow/OAuth2TokenClient.ts +704 -0
  133. package/Server/Utils/Workflow/WorkflowVariableOAuthToken.ts +318 -0
  134. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +47 -7
  135. package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +57 -16
  136. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +193 -214
  137. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +57 -13
  138. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.ts +54 -17
  139. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +179 -161
  140. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +281 -167
  141. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsServiceUrl.ts +114 -0
  142. package/Server/Utils/Workspace/MicrosoftTeams/ReactionNoteSync.ts +895 -0
  143. package/Server/Utils/Workspace/Slack/Actions/ActionTypes.ts +7 -9
  144. package/Server/Utils/Workspace/Slack/Actions/Alert.ts +96 -227
  145. package/Server/Utils/Workspace/Slack/Actions/AlertEpisode.ts +93 -214
  146. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +30 -3
  147. package/Server/Utils/Workspace/Slack/Actions/Authorization.ts +99 -0
  148. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +117 -283
  149. package/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.ts +101 -196
  150. package/Server/Utils/Workspace/Slack/Actions/ReactionNote.ts +329 -0
  151. package/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.ts +111 -287
  152. package/Server/Utils/Workspace/Slack/Slack.ts +86 -17
  153. package/Server/Utils/Workspace/Slack/app-manifest.json +2 -0
  154. package/Server/Utils/Workspace/Workspace.ts +171 -54
  155. package/Server/Utils/Workspace/WorkspaceActionAuthorization.ts +252 -0
  156. package/Server/Utils/Workspace/WorkspaceBase.ts +39 -0
  157. package/Server/Utils/Workspace/WorkspaceOAuthState.ts +280 -0
  158. package/Server/Utils/Workspace/WorkspaceProjectReferenceValidator.ts +96 -0
  159. package/Server/Utils/Workspace/WorkspaceReactionNote.ts +620 -0
  160. package/Tests/App/Dashboard/AttributesJSONDashboardSurfaces.test.tsx +496 -0
  161. package/Tests/App/Dashboard/AutoRemediationRulesTableCommandRunners.test.tsx +152 -0
  162. package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +32 -0
  163. package/Tests/App/Dashboard/BulkIncidentLinkActions.test.tsx +869 -0
  164. package/Tests/App/Dashboard/CephMetricTooltips.test.tsx +1777 -0
  165. package/Tests/App/Dashboard/CloudFleetSummary.test.ts +8 -0
  166. package/Tests/App/Dashboard/CloudMetricTooltips.test.tsx +887 -0
  167. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +794 -0
  168. package/Tests/App/Dashboard/ContainerHostMetricTooltips.test.tsx +1309 -0
  169. package/Tests/App/Dashboard/CreateOAuthWorkflowVariableModal.test.tsx +840 -0
  170. package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +653 -0
  171. package/Tests/App/Dashboard/DatabaseMonitorStepForm.test.tsx +197 -0
  172. package/Tests/App/Dashboard/DatabaseMonitorView.test.tsx +376 -0
  173. package/Tests/App/Dashboard/DisabledWarningRobustness.test.tsx +262 -0
  174. package/Tests/App/Dashboard/DiscoveryScanLivePage.test.tsx +39 -0
  175. package/Tests/App/Dashboard/DockerSwarmClustersListTooltips.test.tsx +414 -0
  176. package/Tests/App/Dashboard/DockerSwarmMetricTooltips.test.ts +796 -0
  177. package/Tests/App/Dashboard/DockerSwarmOverviewTooltips.test.tsx +747 -0
  178. package/Tests/App/Dashboard/EventNotes.test.tsx +2080 -0
  179. package/Tests/App/Dashboard/EventNotesPages.test.tsx +486 -0
  180. package/Tests/App/Dashboard/EventNotesUtil.test.ts +933 -0
  181. package/Tests/App/Dashboard/ExceptionMonitorEnvironmentFilter.test.tsx +238 -0
  182. package/Tests/App/Dashboard/HostDetailViewTooltips.test.tsx +725 -0
  183. package/Tests/App/Dashboard/HostListColumnTooltips.test.tsx +472 -0
  184. package/Tests/App/Dashboard/HostMetricTooltips.test.ts +709 -0
  185. package/Tests/App/Dashboard/HostOverviewTooltips.test.tsx +698 -0
  186. package/Tests/App/Dashboard/HostTooltipHarness.ts +124 -0
  187. package/Tests/App/Dashboard/HostsListTooltips.test.tsx +395 -0
  188. package/Tests/App/Dashboard/IncidentAlertLinkDialog.test.tsx +691 -0
  189. package/Tests/App/Dashboard/IncidentAlertLinkHelpers.test.ts +458 -0
  190. package/Tests/App/Dashboard/IncidentAlertLinkPages.test.tsx +828 -0
  191. package/Tests/App/Dashboard/IncidentAlertLinkSideMenus.test.tsx +231 -0
  192. package/Tests/App/Dashboard/IncidentChangeStateNotifyDefault.test.tsx +665 -0
  193. package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +689 -0
  194. package/Tests/App/Dashboard/IncidentEpisodeFeedPublicNoteNotifyDefault.test.tsx +494 -0
  195. package/Tests/App/Dashboard/IncidentEpisodeOverviewNotifyDefault.test.tsx +706 -0
  196. package/Tests/App/Dashboard/IncidentFeedPublicNoteNotifyDefault.test.tsx +472 -0
  197. package/Tests/App/Dashboard/IncidentOverviewNotifyDefault.test.tsx +858 -0
  198. package/Tests/App/Dashboard/IncomingEmailAddressSettings.test.tsx +567 -0
  199. package/Tests/App/Dashboard/InvestigationClusterToolFormat.test.ts +241 -0
  200. package/Tests/App/Dashboard/InvestigationEvidenceKubectl.test.tsx +322 -0
  201. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +12 -0
  202. package/Tests/App/Dashboard/InvestigationPanelClusterAccess.test.tsx +476 -0
  203. package/Tests/App/Dashboard/InvestigationRunDetailsKubectl.test.tsx +383 -0
  204. package/Tests/App/Dashboard/IoTMetricTooltips.test.tsx +1123 -0
  205. package/Tests/App/Dashboard/KubectlActivitySummary.test.tsx +366 -0
  206. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +2886 -0
  207. package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +2688 -0
  208. package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +915 -0
  209. package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +837 -0
  210. package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +699 -0
  211. package/Tests/App/Dashboard/KubernetesContainersTabTooltips.test.tsx +320 -0
  212. package/Tests/App/Dashboard/KubernetesCostTooltips.test.tsx +502 -0
  213. package/Tests/App/Dashboard/KubernetesInsightsTooltips.test.tsx +222 -0
  214. package/Tests/App/Dashboard/KubernetesResourceMetricTooltips.test.ts +561 -0
  215. package/Tests/App/Dashboard/KubernetesResourcePagesTooltips.test.tsx +1168 -0
  216. package/Tests/App/Dashboard/LayerDateTimeFieldTimezoneName.test.tsx +66 -0
  217. package/Tests/App/Dashboard/LinkIncidentAlertModal.test.tsx +154 -0
  218. package/Tests/App/Dashboard/LogMonitorPreview.test.tsx +174 -0
  219. package/Tests/App/Dashboard/MetricDescriptionRules.ts +170 -0
  220. package/Tests/App/Dashboard/MetricDescriptionsCatalog.test.ts +206 -0
  221. package/Tests/App/Dashboard/MetricDescriptionsConsistency.test.ts +275 -0
  222. package/Tests/App/Dashboard/MonitorFeedRefresh.test.tsx +279 -0
  223. package/Tests/App/Dashboard/MonitorMetricQueryConfig.test.ts +244 -0
  224. package/Tests/App/Dashboard/MonitorOpenWorkCard.test.tsx +381 -0
  225. package/Tests/App/Dashboard/MonitorOpenWorkHook.test.tsx +784 -0
  226. package/Tests/App/Dashboard/MonitorOverviewData.test.tsx +2199 -0
  227. package/Tests/App/Dashboard/MonitorOverviewHero.test.tsx +1169 -0
  228. package/Tests/App/Dashboard/MonitorOverviewInput.test.ts +1127 -0
  229. package/Tests/App/Dashboard/MonitorOverviewPage.test.tsx +2136 -0
  230. package/Tests/App/Dashboard/MonitorOverviewSelectReadable.test.ts +368 -0
  231. package/Tests/App/Dashboard/MonitorOverviewStatBar.test.tsx +526 -0
  232. package/Tests/App/Dashboard/MonitorOverviewSupportingCards.test.tsx +542 -0
  233. package/Tests/App/Dashboard/MonitorOwnersCombine.test.ts +299 -0
  234. package/Tests/App/Dashboard/MonitorProbesCard.test.tsx +602 -0
  235. package/Tests/App/Dashboard/MonitorResponseTimeCard.test.tsx +386 -0
  236. package/Tests/App/Dashboard/MonitorSetupAndConnectionCards.test.tsx +612 -0
  237. package/Tests/App/Dashboard/MonitorStatusChangesCard.test.tsx +257 -0
  238. package/Tests/App/Dashboard/MonitorSummaryTestMonitorButton.test.tsx +360 -1
  239. package/Tests/App/Dashboard/MonitorUptimeHistoryCard.test.tsx +835 -0
  240. package/Tests/App/Dashboard/MonitorUptimeSummaryHook.test.tsx +971 -0
  241. package/Tests/App/Dashboard/MonitorViewLayout.test.tsx +580 -0
  242. package/Tests/App/Dashboard/NetworkDeviceTooltips.test.tsx +852 -0
  243. package/Tests/App/Dashboard/NetworkDiagnosticsTooltips.test.tsx +556 -0
  244. package/Tests/App/Dashboard/NetworkMetricTooltips.test.ts +1348 -0
  245. package/Tests/App/Dashboard/NetworkSiteTooltips.test.tsx +679 -0
  246. package/Tests/App/Dashboard/OnCallLayerRestrictionTimesPreserved.test.tsx +441 -0
  247. package/Tests/App/Dashboard/OnCallNavbar.test.tsx +214 -0
  248. package/Tests/App/Dashboard/OnCallSchedulePreviewCalendarDisplay.test.tsx +1389 -0
  249. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +205 -1
  250. package/Tests/App/Dashboard/OnCallScheduleTimeInputsSettingsZone.test.tsx +198 -0
  251. package/Tests/App/Dashboard/ProxmoxMetricTooltips.test.ts +592 -0
  252. package/Tests/App/Dashboard/ProxmoxOverviewTooltips.test.tsx +1002 -0
  253. package/Tests/App/Dashboard/ProxmoxResourcePageTooltips.test.tsx +923 -0
  254. package/Tests/App/Dashboard/PublicNotePagesNotifyDefault.test.tsx +524 -0
  255. package/Tests/App/Dashboard/RemediationSuggestionCardApproval.test.tsx +702 -0
  256. package/Tests/App/Dashboard/RemoveUserFromProject.test.tsx +427 -0
  257. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +4 -0
  258. package/Tests/App/Dashboard/ResourceOverviewTileTooltips.test.tsx +1066 -0
  259. package/Tests/App/Dashboard/RumOverviewPage.test.tsx +1195 -0
  260. package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +3 -1
  261. package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +166 -0
  262. package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +622 -0
  263. package/Tests/App/Dashboard/ScheduledMaintenanceChangeStateNotifyDefault.test.tsx +1491 -0
  264. package/Tests/App/Dashboard/ScheduledMaintenanceFeedPublicNoteNotifyDefault.test.tsx +489 -0
  265. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewNotifyDefault.test.tsx +909 -0
  266. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +14 -0
  267. package/Tests/App/Dashboard/ScheduledMaintenanceWindowStatsTranslation.test.tsx +307 -0
  268. package/Tests/App/Dashboard/SecurityEventAttributeColumnPicker.test.tsx +542 -0
  269. package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +174 -0
  270. package/Tests/App/Dashboard/SecurityEventConnectionsEmptyState.test.tsx +973 -212
  271. package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +491 -52
  272. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +301 -0
  273. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +158 -1
  274. package/Tests/App/Dashboard/SecurityEventProviderTile.test.tsx +869 -0
  275. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +959 -94
  276. package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +2 -0
  277. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +274 -1
  278. package/Tests/App/Dashboard/ServerlessMetricTooltips.test.tsx +474 -0
  279. package/Tests/App/Dashboard/ServiceMetricTooltips.test.tsx +772 -0
  280. package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +56 -1
  281. package/Tests/App/Dashboard/TeamMembershipRemoval.test.ts +900 -0
  282. package/Tests/App/Dashboard/TeamMembershipRemovalPages.test.tsx +460 -0
  283. package/Tests/App/Dashboard/TelemetryMetricsSignals.test.ts +1207 -0
  284. package/Tests/App/Dashboard/TelemetryResourceTabTooltips.test.tsx +437 -0
  285. package/Tests/App/Dashboard/TimezoneElements.test.tsx +321 -0
  286. package/Tests/App/Dashboard/TimezoneSelectButton.test.tsx +634 -0
  287. package/Tests/App/Dashboard/TraceExplorer.test.tsx +260 -0
  288. package/Tests/App/Dashboard/TraceMonitorPreview.test.tsx +182 -0
  289. package/Tests/App/Dashboard/UserTimezoneInit.test.tsx +544 -0
  290. package/Tests/App/Dashboard/VMwareMetricTooltips.test.ts +801 -0
  291. package/Tests/App/Dashboard/VMwareOverviewTooltips.test.tsx +601 -0
  292. package/Tests/App/Dashboard/VMwareResourcePagesTooltips.test.tsx +646 -0
  293. package/Tests/App/Dashboard/VMwareTooltipHarness.ts +145 -0
  294. package/Tests/App/Dashboard/WorkflowVariableModals.test.tsx +1630 -0
  295. package/Tests/App/Dashboard/WorkflowVariableRoutes.test.tsx +603 -0
  296. package/Tests/App/Dashboard/WorkflowVariableTokenStatus.test.tsx +589 -0
  297. package/Tests/App/Dashboard/WorkflowVariableUtil.test.ts +1543 -0
  298. package/Tests/App/Dashboard/WorkflowVariableView.test.tsx +3227 -0
  299. package/Tests/App/Dashboard/WorkflowVariablesTable.test.tsx +1277 -395
  300. package/Tests/App/StatusPage/StatusPageOverviewMonitorGroupUptime.test.tsx +714 -0
  301. package/Tests/App/StatusPage/StatusPageOverviewUptimeBars.NewYork.test.tsx +1009 -0
  302. package/Tests/App/StatusPage/StatusPageOverviewUptimeBars.test.tsx +1092 -0
  303. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +5 -0
  304. package/Tests/Models/DatabaseModels/IncidentAlertModel.test.ts +554 -0
  305. package/Tests/Models/DatabaseModels/KubernetesClusterAiAccessColumns.test.ts +520 -0
  306. package/Tests/Models/DatabaseModels/MonitorSecretKeyColumnAccessControl.test.ts +66 -2
  307. package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +117 -0
  308. package/Tests/Models/DatabaseModels/WorkspaceProjectAuthTokenAccessControl.test.ts +236 -0
  309. package/Tests/Models/IncidentEpisodePublicNoteNotifyColumnContract.test.ts +103 -0
  310. package/Tests/Models/IncidentPublicNoteNotifyColumnContract.test.ts +96 -0
  311. package/Tests/Models/ScheduledMaintenancePublicNoteNotifyColumnContract.test.ts +111 -0
  312. package/Tests/Server/API/AIInvestigationAPI.test.ts +976 -0
  313. package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +836 -0
  314. package/Tests/Server/API/CommonAPIAssertCanCreateTable.test.ts +565 -0
  315. package/Tests/Server/API/CommonAPIAssertCanReadTable.test.ts +282 -0
  316. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +1744 -0
  317. package/Tests/Server/API/LogHistogramAPI.test.ts +371 -0
  318. package/Tests/Server/API/MicrosoftTeamsLegacyWebhookRemoval.test.ts +125 -30
  319. package/Tests/Server/API/MicrosoftTeamsOAuthState.test.ts +1121 -0
  320. package/Tests/Server/API/MonitorUptimeSummaryAPI.test.ts +685 -0
  321. package/Tests/Server/API/SessionReplayAPI.test.ts +602 -1
  322. package/Tests/Server/API/SlackChannelCacheAPI.test.ts +358 -0
  323. package/Tests/Server/API/SlackOAuthState.test.ts +688 -0
  324. package/Tests/Server/API/StatusPageOverviewMonitorGroupUptime.test.ts +527 -0
  325. package/Tests/Server/API/StatusPageTestEmailReportAuth.test.ts +2 -0
  326. package/Tests/Server/API/StatusPageUptimeAPI.test.ts +427 -0
  327. package/Tests/Server/API/UserProjectsAPI.test.ts +4 -0
  328. package/Tests/Server/API/WorkflowVariableAPI.test.ts +404 -0
  329. package/Tests/Server/API/WorkspaceOAuthTestHelpers.ts +289 -0
  330. package/Tests/Server/API/WorkspaceSendTestNotificationRoutes.test.ts +2064 -0
  331. package/Tests/Server/Infrastructure/GlobalCache.test.ts +86 -0
  332. package/Tests/Server/Infrastructure/Postgres/AddIncidentAlertMigration.test.ts +341 -0
  333. package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +589 -0
  334. package/Tests/Server/Infrastructure/Postgres/AddOAuth2WorkflowVariablesMigration.test.ts +254 -0
  335. package/Tests/Server/Infrastructure/Postgres/AddSessionReplaySameOriginTracePropagationMigration.test.ts +247 -0
  336. package/Tests/Server/Middleware/BlockedUserMiddleware.test.ts +403 -0
  337. package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +13 -0
  338. package/Tests/Server/Middleware/PublicRouteUserMiddleware.test.ts +2 -0
  339. package/Tests/Server/Middleware/RemovedProjectMemberAuthorization.test.ts +469 -0
  340. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +77 -1
  341. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +211 -0
  342. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +358 -0
  343. package/Tests/Server/Middleware/UserAuthorization.test.ts +97 -0
  344. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +2 -0
  345. package/Tests/Server/Services/AccessTokenProjectUserGrant.test.ts +14 -2
  346. package/Tests/Server/Services/AccessTokenRemovedMemberAccess.test.ts +1044 -0
  347. package/Tests/Server/Services/AddOwnersIdempotency.test.ts +5 -0
  348. package/Tests/Server/Services/AlertEpisodeMemberCreatePermission.test.ts +139 -0
  349. package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +1361 -0
  350. package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +375 -0
  351. package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +2384 -0
  352. package/Tests/Server/Services/FindOwnersProjectMembership.test.ts +267 -0
  353. package/Tests/Server/Services/InboundEmail/SendGridInboundProviderAddress.test.ts +90 -0
  354. package/Tests/Server/Services/IncidentAlertPostgres.test.ts +903 -0
  355. package/Tests/Server/Services/IncidentAlertRegistration.test.ts +96 -0
  356. package/Tests/Server/Services/IncidentAlertService.test.ts +2225 -0
  357. package/Tests/Server/Services/IncidentAlertStateCascade.test.ts +970 -0
  358. package/Tests/Server/Services/IncidentCreateFromAlerts.test.ts +1284 -0
  359. package/Tests/Server/Services/IncidentEpisodeMemberCreatePermission.test.ts +143 -0
  360. package/Tests/Server/Services/IncidentEpisodePublicNoteNotifyDefault.test.ts +805 -0
  361. package/Tests/Server/Services/IncidentPublicNoteNotifyDefault.test.ts +724 -0
  362. package/Tests/Server/Services/IncidentRoleProjectMembership.test.ts +233 -0
  363. package/Tests/Server/Services/KubernetesClusterAiAccessAgentRunnerAssignments.test.ts +372 -0
  364. package/Tests/Server/Services/KubernetesClusterAiAccessBindingGuard.test.ts +1876 -0
  365. package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +620 -0
  366. package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +421 -0
  367. package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +3662 -0
  368. package/Tests/Server/Services/KubernetesClusterAiAccessSubjectClusters.test.ts +405 -0
  369. package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +975 -0
  370. package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +497 -0
  371. package/Tests/Server/Services/KubernetesClusterServiceDeleteSettlesRemediation.test.ts +328 -0
  372. package/Tests/Server/Services/LogAggregationService.test.ts +99 -0
  373. package/Tests/Server/Services/MonitorServiceIncomingEmailCustomAddress.test.ts +447 -0
  374. package/Tests/Server/Services/MonitorServiceProbeFlagSync.test.ts +1334 -0
  375. package/Tests/Server/Services/MonitorServiceProbeStatusGrouping.test.ts +1640 -0
  376. package/Tests/Server/Services/MonitorServiceRefreshCurrentStatus.test.ts +225 -0
  377. package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +8 -8
  378. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +264 -1
  379. package/Tests/Server/Services/MonitorStatusTimelineMergedDowntime.test.ts +284 -0
  380. package/Tests/Server/Services/MonitorUptimeSummaryService.test.ts +1043 -0
  381. package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +5 -0
  382. package/Tests/Server/Services/OnCallUndeliverablePageOwnerMembership.test.ts +359 -0
  383. package/Tests/Server/Services/ProbeServiceDashboardLink.test.ts +191 -0
  384. package/Tests/Server/Services/ProjectOwnersProjectMembership.test.ts +221 -0
  385. package/Tests/Server/Services/RuleRun/IncidentAlertMaintenanceRuleEnginesRun.test.ts +5 -0
  386. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupARun.test.ts +28 -0
  387. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +9 -1
  388. package/Tests/Server/Services/RunnerJobEnqueueAiCommandAgentRunner.test.ts +230 -0
  389. package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +978 -0
  390. package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +866 -0
  391. package/Tests/Server/Services/RunnerJobSubmitResultRedaction.test.ts +322 -0
  392. package/Tests/Server/Services/RunnerJobSubmitResultUnstorableText.test.ts +357 -0
  393. package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +227 -0
  394. package/Tests/Server/Services/RunnerServiceAgentName.test.ts +581 -0
  395. package/Tests/Server/Services/ScheduledMaintenancePublicNoteNotifyDefault.test.ts +802 -0
  396. package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +53 -0
  397. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +5 -0
  398. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +12 -0
  399. package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +1176 -1
  400. package/Tests/Server/Services/TeamMemberBillingSeatSync.test.ts +9 -0
  401. package/Tests/Server/Services/TeamMemberOnCallCleanup.test.ts +18 -0
  402. package/Tests/Server/Services/TeamMemberProjectMembership.test.ts +255 -0
  403. package/Tests/Server/Services/TeamMemberRemovalRevokesProjectAccess.test.ts +600 -0
  404. package/Tests/Server/Services/TeamMemberResourceCleanup.test.ts +731 -0
  405. package/Tests/Server/Services/TeamMemberWorkspaceAccountCleanup.test.ts +164 -0
  406. package/Tests/Server/Services/TraceAggregationService.test.ts +64 -0
  407. package/Tests/Server/Services/UserServiceBlockedUser.test.ts +293 -0
  408. package/Tests/Server/Services/WorkflowVariableOAuthHooks.test.ts +1016 -0
  409. package/Tests/Server/Services/WorkflowVariableOAuthPostgres.test.ts +543 -0
  410. package/Tests/Server/Services/WorkflowVariableRenameUniqueness.test.ts +16 -5
  411. package/Tests/Server/Services/WorkspaceNotificationRuleNoteDelivery.test.ts +473 -0
  412. package/Tests/Server/Services/WorkspaceNotificationRuleSendTestNotification.test.ts +3690 -0
  413. package/Tests/Server/Services/WorkspaceProjectAuthTokenMiscDataSecrets.test.ts +374 -0
  414. package/Tests/Server/Services/WorkspaceProjectAuthTokenSlackChannelCache.test.ts +143 -0
  415. package/Tests/Server/Types/Database/Permissions/WorkflowVariableOAuthColumnPermission.test.ts +250 -0
  416. package/Tests/Server/Types/Database/QueryHelperJsonContains.test.ts +96 -0
  417. package/Tests/Server/Types/Markdown.test.ts +1033 -0
  418. package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +285 -0
  419. package/Tests/Server/Utils/AI/CodeFix/CodeFixAgentAuth.test.ts +159 -1
  420. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +752 -0
  421. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +1840 -0
  422. package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +1067 -0
  423. package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +355 -0
  424. package/Tests/Server/Utils/AI/PostIncidentStatusUpdateTool.test.ts +496 -0
  425. package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +305 -0
  426. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +1365 -0
  427. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +639 -0
  428. package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +1585 -0
  429. package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +1065 -0
  430. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +2138 -1
  431. package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +1035 -0
  432. package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +517 -0
  433. package/Tests/Server/Utils/AI/ResourceTools.test.ts +27 -1
  434. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +1371 -24
  435. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorRollbackRace.test.ts +962 -0
  436. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +518 -0
  437. package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +939 -2
  438. package/Tests/Server/Utils/Database/ProjectScopedRelationReferences.test.ts +371 -0
  439. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +64 -0
  440. package/Tests/Server/Utils/Monitor/DatabaseMetricObservationRemediation.test.ts +102 -0
  441. package/Tests/Server/Utils/Monitor/MonitorAlertCriteriaReferences.test.ts +362 -0
  442. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +55 -0
  443. package/Tests/Server/Utils/Monitor/MonitorEmailAddressRedaction.test.ts +255 -0
  444. package/Tests/Server/Utils/Monitor/MonitorIncidentCriteriaReferences.test.ts +347 -0
  445. package/Tests/Server/Utils/Monitor/MonitorIncidentMemberRoleMembership.test.ts +203 -0
  446. package/Tests/Server/Utils/Monitor/ProbeMonitorsNotification.test.ts +1147 -0
  447. package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +79 -0
  448. package/Tests/Server/Utils/ResourceFeed/ResourceFeedUtil.test.ts +21 -1
  449. package/Tests/Server/Utils/Rules/OwnerRuleAssignment.test.ts +155 -1
  450. package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +103 -0
  451. package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +288 -0
  452. package/Tests/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.test.ts +304 -0
  453. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +40 -3
  454. package/Tests/Server/Utils/Workflow/OAuth2TokenClient.test.ts +702 -0
  455. package/Tests/Server/Utils/Workflow/OAuth2TokenClientHttpIntegration.test.ts +507 -0
  456. package/Tests/Server/Utils/Workflow/WorkflowVariableOAuthToken.test.ts +831 -0
  457. package/Tests/Server/Utils/Workspace/MicrosoftTeamsActionAuthorization.test.ts +63 -1
  458. package/Tests/Server/Utils/Workspace/MicrosoftTeamsAppAccessToken.test.ts +256 -0
  459. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +60 -0
  460. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChatActionAuthorization.test.ts +442 -0
  461. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +44 -2
  462. package/Tests/Server/Utils/Workspace/MicrosoftTeamsDirectMessage.test.ts +55 -0
  463. package/Tests/Server/Utils/Workspace/MicrosoftTeamsReactionNoteSync.test.ts +1522 -0
  464. package/Tests/Server/Utils/Workspace/MicrosoftTeamsServiceUrl.test.ts +130 -0
  465. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +4 -4
  466. package/Tests/Server/Utils/Workspace/Slack/SlackActionAuthorization.test.ts +691 -0
  467. package/Tests/Server/Utils/Workspace/Slack/SlackMessageByTimestamp.test.ts +253 -0
  468. package/Tests/Server/Utils/Workspace/Slack/SlackReactionNote.test.ts +574 -0
  469. package/Tests/Server/Utils/Workspace/WorkspaceActionAuthorization.test.ts +488 -0
  470. package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +861 -0
  471. package/Tests/Server/Utils/Workspace/WorkspaceMessageAuthor.test.ts +635 -0
  472. package/Tests/Server/Utils/Workspace/WorkspaceOAuthState.test.ts +548 -0
  473. package/Tests/Server/Utils/Workspace/WorkspaceReactionNote.test.ts +839 -0
  474. package/Tests/Server/Utils/Workspace/WorkspaceSendErrorMessage.test.ts +725 -0
  475. package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +283 -9
  476. package/Tests/Types/DateBrowserLocalWallClock.test.ts +280 -0
  477. package/Tests/Types/DateLocalShortMonthNameFallback.test.ts +389 -0
  478. package/Tests/Types/DateUserTimezone.test.ts +177 -4
  479. package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +306 -0
  480. package/Tests/Types/Kubernetes/KubernetesClusterAiAccess.test.ts +283 -0
  481. package/Tests/Types/Kubernetes/KubernetesRunnerPostureWriteScope.test.ts +68 -0
  482. package/Tests/Types/Monitor/DatabaseMonitor/SqlServerPlatform.test.ts +144 -0
  483. package/Tests/Types/Monitor/MonitorStepExceptionMonitor.test.ts +160 -0
  484. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +53 -0
  485. package/Tests/Types/Rum/WebVitals.test.ts +173 -0
  486. package/Tests/Types/Runbook/RunbookStepType.test.ts +91 -16
  487. package/Tests/Types/Runner/RunnerLiveStatus.test.ts +14 -3
  488. package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +15 -0
  489. package/Tests/Types/StatusPage/PublicNoteSubscriberNotificationDefault.test.ts +1868 -0
  490. package/Tests/Types/Timezone.test.ts +5 -0
  491. package/Tests/Types/TimezoneAlias.test.ts +1034 -0
  492. package/Tests/Types/Workflow/JiraTemplateFixtures.ts +833 -0
  493. package/Tests/Types/Workflow/JiraTemplateScripts.test.ts +5414 -0
  494. package/Tests/Types/Workflow/JiraTemplateSimulation.test.ts +4803 -0
  495. package/Tests/Types/Workflow/JiraTemplates.test.ts +5429 -0
  496. package/Tests/Types/Workflow/Templates.test.ts +79 -4
  497. package/Tests/Types/Workflow/WorkflowVariableOAuth.test.ts +520 -0
  498. package/Tests/Types/Workspace/WorkspaceNoteReaction.test.ts +177 -0
  499. package/Tests/UI/Components/AttributesJSON/AttributesJSONView.test.tsx +390 -0
  500. package/Tests/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.test.tsx +566 -0
  501. package/Tests/UI/Components/AttributesJSON/JSONHighlight.test.ts +131 -0
  502. package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +276 -1
  503. package/Tests/UI/Components/Calendar/Calendar.test.tsx +1611 -0
  504. package/Tests/UI/Components/Calendar/CalendarDayLayout.test.ts +1486 -0
  505. package/Tests/UI/Components/Calendar/CalendarDayLayoutDst.test.ts +632 -0
  506. package/Tests/UI/Components/Calendar/CalendarDst.test.tsx +388 -0
  507. package/Tests/UI/Components/Charts/ChartGroupPlotFloor.test.tsx +170 -0
  508. package/Tests/UI/Components/Charts/HistogramSelection.test.ts +282 -0
  509. package/Tests/UI/Components/CustomTimeRangeModal.test.tsx +6 -0
  510. package/Tests/UI/Components/CustomTimeRangeModalTimezoneTranslation.test.tsx +285 -0
  511. package/Tests/UI/Components/Dropdown.test.tsx +999 -2
  512. package/Tests/UI/Components/FieldLabelInfoCardTooltip.test.tsx +413 -0
  513. package/Tests/UI/Components/Forms/FormFieldCheckboxTranslation.test.tsx +216 -0
  514. package/Tests/UI/Components/Forms/FormFieldTimezoneDescriptionTranslation.test.tsx +461 -0
  515. package/Tests/UI/Components/Forms/IncidentEpisodePublicNoteNotifyPayload.test.tsx +641 -0
  516. package/Tests/UI/Components/Forms/IncidentPublicNoteNotifyPayload.test.tsx +346 -0
  517. package/Tests/UI/Components/Forms/ScheduledMaintenancePublicNoteNotifyPayload.test.tsx +493 -0
  518. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +911 -2
  519. package/Tests/UI/Components/Graphs/DayUptimeGraphTimezone.NewYork.test.tsx +730 -0
  520. package/Tests/UI/Components/Graphs/DayUptimeGraphTimezone.Tokyo.test.tsx +506 -0
  521. package/Tests/UI/Components/HistogramClickToZoom.test.tsx +619 -0
  522. package/Tests/UI/Components/InfoTooltip.test.tsx +242 -0
  523. package/Tests/UI/Components/LogDetailsPanelAttributesJSON.test.tsx +248 -0
  524. package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +47 -1
  525. package/Tests/UI/Components/LogsViewerSmallScreens.test.tsx +620 -0
  526. package/Tests/UI/Components/ModelPageModelChange.test.tsx +242 -3
  527. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +207 -3
  528. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDeleteVerb.test.tsx +367 -0
  529. package/Tests/UI/Components/ModelTable/BaseModelTableCreateButtonTitle.test.tsx +275 -0
  530. package/Tests/UI/Components/ModelTable/BaseModelTableDeleteConfirmation.test.tsx +521 -0
  531. package/Tests/UI/Components/MonitorGraphs/Uptime.test.tsx +406 -2
  532. package/Tests/UI/Components/MonitorGraphs/UptimeBarDayModal.test.tsx +169 -2
  533. package/Tests/UI/Components/TableHeaderTooltip.test.tsx +662 -0
  534. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +266 -0
  535. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerSmallScreens.test.tsx +439 -0
  536. package/Tests/UI/Components/TimezoneDropdownLegacyValues.test.tsx +704 -0
  537. package/Tests/UI/Components/UseHistogramZoom.test.tsx +89 -1
  538. package/Tests/UI/Components/UseLogsHistogram.test.tsx +175 -0
  539. package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +5 -5
  540. package/Tests/UI/Rum/PrivacySummaryCard.test.tsx +166 -9
  541. package/Tests/UI/Rum/RecordingHealthTooltips.test.tsx +447 -0
  542. package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +164 -0
  543. package/Tests/UI/Rum/ReplayFrameCapture.test.ts +6750 -0
  544. package/Tests/UI/Rum/ReplayRail.test.tsx +723 -12
  545. package/Tests/UI/Rum/ReplayRailDetail.test.tsx +86 -0
  546. package/Tests/UI/Rum/ReplayScreenshot.test.ts +2124 -0
  547. package/Tests/UI/Rum/ReplayScreenshotActions.test.tsx +3288 -0
  548. package/Tests/UI/Rum/ReplayStage.test.tsx +62 -0
  549. package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +983 -2
  550. package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +149 -0
  551. package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +107 -6
  552. package/Tests/UI/Rum/SessionReplayUsersTableTooltips.test.tsx +330 -0
  553. package/Tests/UI/Rum/UserFlowTooltips.test.tsx +886 -0
  554. package/Tests/UI/Telemetry/TelemetryDetailPanel.test.tsx +28 -0
  555. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  556. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  557. package/Tests/UI/Utils/PermissionGate.test.ts +76 -0
  558. package/Tests/UI/Utils/ProjectUsersModelAPI.test.ts +51 -0
  559. package/Tests/UI/Utils/Timezone.test.ts +747 -33
  560. package/Tests/UI/Workspace/SendTestNotificationButton.test.tsx +1854 -0
  561. package/Tests/UI/Workspace/WorkspaceCardsSendTestNotification.test.tsx +1864 -0
  562. package/Tests/Utils/AI/InvestigationReport.test.ts +435 -7
  563. package/Tests/Utils/AiRemediation/KubectlAllowlistValidatorParity.test.ts +1084 -0
  564. package/Tests/Utils/AiRemediation/KubectlOutputRedactor.test.ts +2531 -0
  565. package/Tests/Utils/AiRemediation/KubectlPolicy.test.ts +1895 -0
  566. package/Tests/Utils/AiRemediation/KubectlPolicyAllowlist.test.ts +428 -0
  567. package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +828 -0
  568. package/Tests/Utils/AiRemediation/KubectlPolicyCustomResourceScope.test.ts +573 -0
  569. package/Tests/Utils/AiRemediation/KubectlPolicyDenials.test.ts +1525 -0
  570. package/Tests/Utils/AiRemediation/KubectlPolicyExposeOverrides.test.ts +275 -0
  571. package/Tests/Utils/AiRemediation/KubectlPolicyNodePatch.test.ts +428 -0
  572. package/Tests/Utils/AiRemediation/KubectlPolicyObjectWords.test.ts +195 -0
  573. package/Tests/Utils/AiRemediation/KubectlPolicyPatchParents.test.ts +637 -0
  574. package/Tests/Utils/AiRemediation/KubectlPolicyPodSecurityBaseline.test.ts +322 -0
  575. package/Tests/Utils/AiRemediation/KubectlPolicySafeWriteScope.test.ts +1026 -0
  576. package/Tests/Utils/AiRemediation/KubectlWaitBudget.test.ts +267 -0
  577. package/Tests/Utils/AiRemediation/KubectlWriteScope.test.ts +390 -0
  578. package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +777 -0
  579. package/Tests/Utils/AiRemediation/KubectlWriteScopeClusterScoped.test.ts +613 -0
  580. package/Tests/Utils/AiRemediation/KubectlWriteScopeEntryPoint.test.ts +576 -0
  581. package/Tests/Utils/AiRemediation/KubectlWriteScopeKubectlSpellings.test.ts +752 -0
  582. package/Tests/Utils/AiRemediation/KubectlWriteScopeObjectWords.test.ts +358 -0
  583. package/Tests/Utils/AiRemediation/KubectlWriteScopeOverrides.test.ts +293 -0
  584. package/Tests/Utils/AiRemediation/KubectlWriteScopeParityCases.ts +598 -0
  585. package/Tests/Utils/AiRemediation/KubectlWriteScopePolicyParity.test.ts +403 -0
  586. package/Tests/Utils/Dashboard/DashboardClockComponent.test.ts +154 -5
  587. package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +696 -0
  588. package/Tests/Utils/Monitor/IncomingEmailMonitorAddress.test.ts +478 -0
  589. package/Tests/Utils/Monitor/MonitorCheckScheduleUtil.test.ts +646 -0
  590. package/Tests/Utils/Monitor/MonitorOverviewCriteriaUtil.test.ts +292 -0
  591. package/Tests/Utils/Monitor/MonitorOverviewFamily.test.ts +274 -0
  592. package/Tests/Utils/Monitor/MonitorOverviewPresentationUtil.test.ts +3100 -0
  593. package/Tests/Utils/Monitor/MonitorOverviewProbeUtil.test.ts +1412 -0
  594. package/Tests/Utils/Monitor/MonitorOverviewTargetUtil.test.ts +374 -0
  595. package/Tests/Utils/Monitor/MonitorStatusHistoryUtil.test.ts +332 -0
  596. package/Tests/Utils/Monitor/MonitorUptimeSummaryUtil.test.ts +946 -0
  597. package/Tests/Utils/Rum/SessionIdentity.test.ts +94 -0
  598. package/Tests/Utils/Rum/SessionReplayWafCompatibility.test.ts +840 -0
  599. package/Tests/Utils/Rum/SessionReplayWireEncoding.test.ts +208 -0
  600. package/Tests/Utils/Rum/SessionTraceState.test.ts +239 -0
  601. package/Tests/Utils/Rum/UserFlow.test.ts +1010 -0
  602. package/Tests/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.test.ts +217 -0
  603. package/Tests/Utils/StatusPage/ResourceUptime.test.ts +1272 -1
  604. package/Tests/Utils/StatusPage/UptimeDailyAggregateTotals.test.ts +298 -0
  605. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +649 -1
  606. package/Tests/Utils/StatusPage/UptimeDailyAggregateWindow.test.ts +314 -0
  607. package/Tests/Utils/Telemetry/AttributesJSON.test.ts +454 -0
  608. package/Tests/Utils/Uptime/DayUptimeGraphUtil.test.ts +418 -2
  609. package/Tests/Utils/Uptime/DayUptimeGraphUtilMidnightDst.test.ts +160 -0
  610. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.Auckland.test.ts +45 -0
  611. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.Kolkata.test.ts +40 -0
  612. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.London.test.ts +147 -0
  613. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.NewYork.test.ts +48 -0
  614. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezone.Tokyo.test.ts +39 -0
  615. package/Tests/Utils/Uptime/DayUptimeGraphUtilTimezoneCases.ts +1015 -0
  616. package/Tests/Utils/Uptime/UptimeUtil.test.ts +75 -0
  617. package/Tests/Utils/Uptime/UptimeUtilChronologicalOrder.test.ts +1279 -0
  618. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +203 -5
  619. package/Types/Date.ts +121 -7
  620. package/Types/Email/EmailMessage.ts +8 -0
  621. package/Types/Email/EmailTemplateType.ts +1 -0
  622. package/Types/Exception/ExceptionMessages.ts +1 -0
  623. package/Types/Incident/IncidentAlertLink.ts +38 -0
  624. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +488 -0
  625. package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +54 -0
  626. package/Types/Kubernetes/KubernetesClusterAiAccessToolNames.ts +17 -0
  627. package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +9 -0
  628. package/Types/Monitor/DatabaseMonitor/SqlServerPlatform.ts +117 -0
  629. package/Types/Monitor/KubernetesAlertTemplates.ts +6 -5
  630. package/Types/Monitor/MonitorStepExceptionMonitor.ts +56 -0
  631. package/Types/Monitor/MonitorUptimeSummary.ts +113 -0
  632. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +11 -0
  633. package/Types/Permission.ts +48 -0
  634. package/Types/Rum/SessionReplay.ts +80 -8
  635. package/Types/Rum/SessionReplayApi.ts +44 -1
  636. package/Types/Rum/UserFlow.ts +187 -0
  637. package/Types/Rum/WebVitals.ts +52 -0
  638. package/Types/Runbook/RunbookStepType.ts +10 -0
  639. package/Types/Runbook/RunnerJobOrigin.ts +15 -0
  640. package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +6 -2
  641. package/Types/StatusPage/MergedDowntimeTotals.ts +17 -0
  642. package/Types/StatusPage/PublicNoteSubscriberNotificationDefault.ts +148 -0
  643. package/Types/StatusPage/UptimeDailyAggregate.ts +15 -0
  644. package/Types/Telemetry/TelemetryIngestSurface.ts +9 -0
  645. package/Types/Timezone.ts +5 -0
  646. package/Types/TimezoneAlias.ts +385 -0
  647. package/Types/Workflow/Templates.ts +3041 -2
  648. package/Types/Workflow/WorkflowVariableOAuth.ts +476 -0
  649. package/Types/Workspace/WorkspaceNoteReaction.ts +132 -0
  650. package/Typings/Index.d.ts +24 -0
  651. package/UI/Components/AttributesJSON/AttributesJSONPreferences.ts +175 -0
  652. package/UI/Components/AttributesJSON/AttributesJSONView.tsx +138 -0
  653. package/UI/Components/AttributesJSON/AttributesViewToggle.tsx +79 -0
  654. package/UI/Components/AttributesJSON/BracesGlyph.tsx +30 -0
  655. package/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.tsx +491 -0
  656. package/UI/Components/AttributesJSON/JSONHighlight.ts +77 -0
  657. package/UI/Components/Calendar/Calendar.css +83 -0
  658. package/UI/Components/Calendar/Calendar.tsx +136 -7
  659. package/UI/Components/Calendar/CalendarDayLayout.ts +236 -0
  660. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +23 -1
  661. package/UI/Components/Charts/Utils/HistogramSelection.ts +117 -0
  662. package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +269 -0
  663. package/UI/Components/Charts/Utils/useHistogramZoom.ts +26 -2
  664. package/UI/Components/Date/CustomTimeRangeModal.tsx +26 -3
  665. package/UI/Components/Detail/FieldLabel.tsx +8 -0
  666. package/UI/Components/Dropdown/Dropdown.tsx +58 -9
  667. package/UI/Components/Forms/Fields/FormField.tsx +49 -14
  668. package/UI/Components/Graphs/DayUptimeGraph.tsx +166 -25
  669. package/UI/Components/Graphs/UptimeBarTooltip.tsx +10 -2
  670. package/UI/Components/Graphs/UptimeDaySummary.tsx +8 -0
  671. package/UI/Components/InfoCard/InfoCard.tsx +47 -1
  672. package/UI/Components/LogsViewer/LogsViewer.tsx +52 -5
  673. package/UI/Components/LogsViewer/components/ColumnSelector.tsx +13 -2
  674. package/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.tsx +13 -1
  675. package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +91 -76
  676. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +15 -1
  677. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +28 -106
  678. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +54 -6
  679. package/UI/Components/LogsViewer/components/SavedViewsDropdown.tsx +8 -2
  680. package/UI/Components/LogsViewer/useLogsHistogram.ts +39 -6
  681. package/UI/Components/ModelTable/BaseModelTable.tsx +161 -31
  682. package/UI/Components/ModelTable/Column.ts +5 -0
  683. package/UI/Components/MonitorGraphs/Uptime.tsx +12 -0
  684. package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +10 -2
  685. package/UI/Components/Page/ModelPage.tsx +59 -3
  686. package/UI/Components/Table/TableHeader.tsx +47 -2
  687. package/UI/Components/Table/Types/Column.ts +7 -0
  688. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +69 -5
  689. package/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.tsx +12 -1
  690. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +15 -1
  691. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +36 -104
  692. package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +9 -1
  693. package/UI/Components/Tooltip/InfoTooltip.tsx +78 -0
  694. package/UI/Utils/ModelAPI/ProjectUsersModelAPI.ts +19 -1
  695. package/UI/Utils/PermissionGate.ts +11 -2
  696. package/UI/Utils/Timezone.ts +69 -28
  697. package/Utils/AI/InvestigationReport.ts +195 -25
  698. package/Utils/AiRemediation/KubectlOutputRedactor.ts +1724 -0
  699. package/Utils/AiRemediation/KubectlPolicy.ts +4136 -0
  700. package/Utils/AiRemediation/KubectlWaitBudget.ts +156 -0
  701. package/Utils/AiRemediation/KubectlWriteScope.ts +1964 -0
  702. package/Utils/Dashboard/Components/DashboardClockComponent.ts +7 -6
  703. package/Utils/Incident/IncidentFromAlerts.ts +516 -0
  704. package/Utils/Monitor/IncomingEmailMonitorAddress.ts +292 -0
  705. package/Utils/Monitor/MonitorCheckScheduleUtil.ts +654 -0
  706. package/Utils/Monitor/MonitorOverviewCriteriaUtil.ts +188 -0
  707. package/Utils/Monitor/MonitorOverviewFamily.ts +263 -0
  708. package/Utils/Monitor/MonitorOverviewPresentationUtil.ts +1958 -0
  709. package/Utils/Monitor/MonitorOverviewProbeUtil.ts +979 -0
  710. package/Utils/Monitor/MonitorOverviewTargetUtil.ts +299 -0
  711. package/Utils/Monitor/MonitorStatusHistoryUtil.ts +201 -0
  712. package/Utils/Monitor/MonitorUptimeSummaryUtil.ts +638 -0
  713. package/Utils/Rum/SessionIdentity.ts +44 -0
  714. package/Utils/Rum/SessionReplayWireEncoding.ts +137 -0
  715. package/Utils/Rum/SessionTraceState.ts +212 -0
  716. package/Utils/Rum/UserFlow.ts +1527 -0
  717. package/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.ts +107 -0
  718. package/Utils/StatusPage/ResourceUptime.ts +99 -0
  719. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +197 -0
  720. package/Utils/Telemetry/AttributesJSON.ts +367 -0
  721. package/Utils/Uptime/DayUptimeGraphUtil.ts +165 -0
  722. package/Utils/Uptime/UptimeUtil.ts +122 -38
  723. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +8 -1
  724. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
  725. package/build/dist/Models/DatabaseModels/AlertFeed.js +2 -0
  726. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  727. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
  728. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
  729. package/build/dist/Models/DatabaseModels/IncidentAlert.js +553 -0
  730. package/build/dist/Models/DatabaseModels/IncidentAlert.js.map +1 -0
  731. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +8 -1
  732. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
  733. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +10 -3
  734. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
  735. package/build/dist/Models/DatabaseModels/IncidentFeed.js +2 -0
  736. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
  737. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +10 -3
  738. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  739. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  740. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  741. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +434 -0
  742. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  743. package/build/dist/Models/DatabaseModels/Monitor.js +49 -0
  744. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  745. package/build/dist/Models/DatabaseModels/Project.js +62 -0
  746. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  747. package/build/dist/Models/DatabaseModels/RumApplication.js +53 -1
  748. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  749. package/build/dist/Models/DatabaseModels/Runner.js +4 -4
  750. package/build/dist/Models/DatabaseModels/Runner.js.map +1 -1
  751. package/build/dist/Models/DatabaseModels/RunnerJob.js +66 -0
  752. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
  753. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +11 -3
  754. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  755. package/build/dist/Models/DatabaseModels/WorkflowVariable.js +487 -3
  756. package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
  757. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js +64 -16
  758. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  759. package/build/dist/Server/API/AIInvestigationAPI.js +205 -0
  760. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  761. package/build/dist/Server/API/AutoRemediationAPI.js +115 -2
  762. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  763. package/build/dist/Server/API/CommonAPI.js +49 -0
  764. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  765. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +564 -0
  766. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -0
  767. package/build/dist/Server/API/MicrosoftTeamsAPI.js +465 -176
  768. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  769. package/build/dist/Server/API/MonitorAPI.js +107 -1
  770. package/build/dist/Server/API/MonitorAPI.js.map +1 -1
  771. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js +5 -16
  772. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js.map +1 -1
  773. package/build/dist/Server/API/SlackAPI.js +322 -78
  774. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  775. package/build/dist/Server/API/StatusPageAPI.js +123 -17
  776. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  777. package/build/dist/Server/API/TelemetryAPI.js +144 -5
  778. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  779. package/build/dist/Server/API/UserTwoFactorBackupCodeAPI.js +1 -0
  780. package/build/dist/Server/API/UserTwoFactorBackupCodeAPI.js.map +1 -1
  781. package/build/dist/Server/API/WorkflowVariableAPI.js +109 -0
  782. package/build/dist/Server/API/WorkflowVariableAPI.js.map +1 -0
  783. package/build/dist/Server/Infrastructure/GlobalCache.js +29 -0
  784. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  785. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794300000000-AddOAuth2WorkflowVariables.js +38 -0
  786. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794300000000-AddOAuth2WorkflowVariables.js.map +1 -0
  787. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794400000000-AddKubernetesClusterAiAccess.js +54 -0
  788. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794400000000-AddKubernetesClusterAiAccess.js.map +1 -0
  789. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794500000000-AddIncomingEmailCustomAddressToMonitor.js +14 -0
  790. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794500000000-AddIncomingEmailCustomAddressToMonitor.js.map +1 -0
  791. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794600000000-AddAuthTokenExpiresAtToWorkspaceProjectAuthToken.js +12 -0
  792. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794600000000-AddAuthTokenExpiresAtToWorkspaceProjectAuthToken.js.map +1 -0
  793. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794700000000-RemoveAppAccessTokenFromWorkspaceProjectAuthTokenMiscData.js +32 -0
  794. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794700000000-RemoveAppAccessTokenFromWorkspaceProjectAuthTokenMiscData.js.map +1 -0
  795. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js +20 -0
  796. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js.map +1 -0
  797. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js +42 -0
  798. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js.map +1 -0
  799. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
  800. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  801. package/build/dist/Server/Middleware/MasterAdminAuthorization.js +21 -0
  802. package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
  803. package/build/dist/Server/Middleware/TelemetryIngest.js +32 -2
  804. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  805. package/build/dist/Server/Middleware/UserAuthorization.js +39 -6
  806. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  807. package/build/dist/Server/Services/AIAgentService.js +1 -0
  808. package/build/dist/Server/Services/AIAgentService.js.map +1 -1
  809. package/build/dist/Server/Services/AccessTokenService.js +87 -42
  810. package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
  811. package/build/dist/Server/Services/AlertEpisodeMemberService.js +4 -0
  812. package/build/dist/Server/Services/AlertEpisodeMemberService.js.map +1 -1
  813. package/build/dist/Server/Services/AlertEpisodeService.js +12 -1
  814. package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
  815. package/build/dist/Server/Services/AlertService.js +110 -23
  816. package/build/dist/Server/Services/AlertService.js.map +1 -1
  817. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +716 -30
  818. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  819. package/build/dist/Server/Services/AutoRemediationRuleService.js +100 -0
  820. package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
  821. package/build/dist/Server/Services/BillingService.js +1 -0
  822. package/build/dist/Server/Services/BillingService.js.map +1 -1
  823. package/build/dist/Server/Services/InboundEmail/Providers/SendGridInboundProvider.js +11 -16
  824. package/build/dist/Server/Services/InboundEmail/Providers/SendGridInboundProvider.js.map +1 -1
  825. package/build/dist/Server/Services/IncidentAlertService.js +1370 -0
  826. package/build/dist/Server/Services/IncidentAlertService.js.map +1 -0
  827. package/build/dist/Server/Services/IncidentEpisodeMemberService.js +4 -0
  828. package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
  829. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +48 -0
  830. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  831. package/build/dist/Server/Services/IncidentEpisodeRoleMemberService.js +21 -0
  832. package/build/dist/Server/Services/IncidentEpisodeRoleMemberService.js.map +1 -1
  833. package/build/dist/Server/Services/IncidentEpisodeService.js +12 -1
  834. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  835. package/build/dist/Server/Services/IncidentGroupingEngineService.js +8 -0
  836. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  837. package/build/dist/Server/Services/IncidentMemberService.js +14 -0
  838. package/build/dist/Server/Services/IncidentMemberService.js.map +1 -1
  839. package/build/dist/Server/Services/IncidentPublicNoteService.js +48 -0
  840. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  841. package/build/dist/Server/Services/IncidentService.js +263 -33
  842. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  843. package/build/dist/Server/Services/IncidentStateTimelineService.js +33 -0
  844. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  845. package/build/dist/Server/Services/IncidentTemplateService.js +68 -4
  846. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  847. package/build/dist/Server/Services/Index.js +2 -0
  848. package/build/dist/Server/Services/Index.js.map +1 -1
  849. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +1470 -0
  850. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -0
  851. package/build/dist/Server/Services/KubernetesClusterService.js +1097 -0
  852. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  853. package/build/dist/Server/Services/LogAggregationService.js +14 -6
  854. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  855. package/build/dist/Server/Services/MonitorService.js +487 -48
  856. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  857. package/build/dist/Server/Services/MonitorStatusTimelineService.js +540 -3
  858. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  859. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +2 -0
  860. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  861. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +2 -0
  862. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  863. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +2 -0
  864. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  865. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +3 -0
  866. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  867. package/build/dist/Server/Services/OnCallNotificationAlertingService.js +29 -7
  868. package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -1
  869. package/build/dist/Server/Services/OnCallSetupReminderService.js +1 -0
  870. package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -1
  871. package/build/dist/Server/Services/ProbeService.js +7 -1
  872. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  873. package/build/dist/Server/Services/ProjectService.js +11 -1
  874. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  875. package/build/dist/Server/Services/RunbookCredentialService.js +24 -0
  876. package/build/dist/Server/Services/RunbookCredentialService.js.map +1 -1
  877. package/build/dist/Server/Services/RunbookSecretService.js +44 -0
  878. package/build/dist/Server/Services/RunbookSecretService.js.map +1 -1
  879. package/build/dist/Server/Services/RunnerJobService.js +641 -21
  880. package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
  881. package/build/dist/Server/Services/RunnerService.js +344 -5
  882. package/build/dist/Server/Services/RunnerService.js.map +1 -1
  883. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +48 -0
  884. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  885. package/build/dist/Server/Services/ScheduledMaintenanceService.js +102 -20
  886. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  887. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +67 -4
  888. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
  889. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +12 -1
  890. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  891. package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -0
  892. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  893. package/build/dist/Server/Services/StatusPageService.js +230 -32
  894. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  895. package/build/dist/Server/Services/StatusPageSubscriberService.js +4 -0
  896. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  897. package/build/dist/Server/Services/TeamMemberService.js +270 -11
  898. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  899. package/build/dist/Server/Services/TraceAggregationService.js +10 -6
  900. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  901. package/build/dist/Server/Services/UserEmailService.js +1 -0
  902. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  903. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1 -0
  904. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -1
  905. package/build/dist/Server/Services/UserNotificationRuleAdminService.js +1 -0
  906. package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -1
  907. package/build/dist/Server/Services/UserNotificationRuleService.js +4 -0
  908. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  909. package/build/dist/Server/Services/UserService.js +107 -1
  910. package/build/dist/Server/Services/UserService.js.map +1 -1
  911. package/build/dist/Server/Services/WorkflowVariableService.js +396 -7
  912. package/build/dist/Server/Services/WorkflowVariableService.js.map +1 -1
  913. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +463 -7
  914. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  915. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +144 -2
  916. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
  917. package/build/dist/Server/Types/Database/QueryHelper.js +20 -0
  918. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  919. package/build/dist/Server/Types/Markdown.js +394 -27
  920. package/build/dist/Server/Types/Markdown.js.map +1 -1
  921. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +123 -0
  922. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -0
  923. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +344 -0
  924. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -0
  925. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +587 -0
  926. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -0
  927. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js +18 -2
  928. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js.map +1 -1
  929. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1380 -239
  930. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  931. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +1099 -68
  932. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  933. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +88 -6
  934. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  935. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +45 -11
  936. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  937. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +41 -11
  938. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  939. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js +11 -4
  940. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -1
  941. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +4 -2
  942. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -1
  943. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +997 -141
  944. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
  945. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +299 -4
  946. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
  947. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js +120 -0
  948. package/build/dist/Server/Utils/Database/AffectedResourceRelations.js.map +1 -0
  949. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +160 -1
  950. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
  951. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +1 -0
  952. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
  953. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +59 -12
  954. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  955. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +5 -1
  956. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  957. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +84 -22
  958. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  959. package/build/dist/Server/Utils/Monitor/MonitorPayloadRedaction.js +70 -5
  960. package/build/dist/Server/Utils/Monitor/MonitorPayloadRedaction.js.map +1 -1
  961. package/build/dist/Server/Utils/Monitor/ProbeMonitorsNotification.js +249 -0
  962. package/build/dist/Server/Utils/Monitor/ProbeMonitorsNotification.js.map +1 -0
  963. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js +1 -0
  964. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js.map +1 -1
  965. package/build/dist/Server/Utils/PushNotificationUtil.js +27 -0
  966. package/build/dist/Server/Utils/PushNotificationUtil.js.map +1 -1
  967. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +26 -3
  968. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -1
  969. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js +38 -3
  970. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js.map +1 -1
  971. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +8 -0
  972. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
  973. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +143 -23
  974. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
  975. package/build/dist/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.js +406 -0
  976. package/build/dist/Server/Utils/SessionReplay/SessionReplayUserFlowReadService.js.map +1 -0
  977. package/build/dist/Server/Utils/StartServer.js +4 -3
  978. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  979. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +382 -0
  980. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -0
  981. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js +1 -0
  982. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js.map +1 -1
  983. package/build/dist/Server/Utils/UserPermission/UserPermission.js +10 -0
  984. package/build/dist/Server/Utils/UserPermission/UserPermission.js.map +1 -1
  985. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js +447 -0
  986. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js.map +1 -0
  987. package/build/dist/Server/Utils/Workflow/WorkflowVariableOAuthToken.js +202 -0
  988. package/build/dist/Server/Utils/Workflow/WorkflowVariableOAuthToken.js.map +1 -0
  989. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +39 -1
  990. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
  991. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +44 -4
  992. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
  993. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +150 -191
  994. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  995. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +44 -4
  996. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  997. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js +39 -17
  998. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js.map +1 -1
  999. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +151 -145
  1000. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
  1001. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +221 -127
  1002. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  1003. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsServiceUrl.js +91 -0
  1004. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsServiceUrl.js.map +1 -0
  1005. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/ReactionNoteSync.js +673 -0
  1006. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/ReactionNoteSync.js.map +1 -0
  1007. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js +3 -9
  1008. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js.map +1 -1
  1009. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +65 -166
  1010. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js.map +1 -1
  1011. package/build/dist/Server/Utils/Workspace/Slack/Actions/AlertEpisode.js +63 -157
  1012. package/build/dist/Server/Utils/Workspace/Slack/Actions/AlertEpisode.js.map +1 -1
  1013. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +23 -3
  1014. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -1
  1015. package/build/dist/Server/Utils/Workspace/Slack/Actions/Authorization.js +92 -0
  1016. package/build/dist/Server/Utils/Workspace/Slack/Actions/Authorization.js.map +1 -0
  1017. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +81 -210
  1018. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js.map +1 -1
  1019. package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js +68 -138
  1020. package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js.map +1 -1
  1021. package/build/dist/Server/Utils/Workspace/Slack/Actions/ReactionNote.js +240 -0
  1022. package/build/dist/Server/Utils/Workspace/Slack/Actions/ReactionNote.js.map +1 -0
  1023. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js +85 -212
  1024. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js.map +1 -1
  1025. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +60 -17
  1026. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  1027. package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +2 -0
  1028. package/build/dist/Server/Utils/Workspace/Workspace.js +134 -41
  1029. package/build/dist/Server/Utils/Workspace/Workspace.js.map +1 -1
  1030. package/build/dist/Server/Utils/Workspace/WorkspaceActionAuthorization.js +197 -0
  1031. package/build/dist/Server/Utils/Workspace/WorkspaceActionAuthorization.js.map +1 -0
  1032. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js +32 -0
  1033. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  1034. package/build/dist/Server/Utils/Workspace/WorkspaceOAuthState.js +199 -0
  1035. package/build/dist/Server/Utils/Workspace/WorkspaceOAuthState.js.map +1 -0
  1036. package/build/dist/Server/Utils/Workspace/WorkspaceProjectReferenceValidator.js +91 -0
  1037. package/build/dist/Server/Utils/Workspace/WorkspaceProjectReferenceValidator.js.map +1 -0
  1038. package/build/dist/Server/Utils/Workspace/WorkspaceReactionNote.js +450 -0
  1039. package/build/dist/Server/Utils/Workspace/WorkspaceReactionNote.js.map +1 -0
  1040. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +103 -5
  1041. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
  1042. package/build/dist/Types/Date.js +97 -7
  1043. package/build/dist/Types/Date.js.map +1 -1
  1044. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  1045. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  1046. package/build/dist/Types/Exception/ExceptionMessages.js +1 -0
  1047. package/build/dist/Types/Exception/ExceptionMessages.js.map +1 -1
  1048. package/build/dist/Types/Incident/IncidentAlertLink.js +34 -0
  1049. package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -0
  1050. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +245 -0
  1051. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -0
  1052. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +49 -0
  1053. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -0
  1054. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessToolNames.js +16 -0
  1055. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessToolNames.js.map +1 -0
  1056. package/build/dist/Types/Monitor/DatabaseMonitor/SqlServerPlatform.js +104 -0
  1057. package/build/dist/Types/Monitor/DatabaseMonitor/SqlServerPlatform.js.map +1 -0
  1058. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +6 -5
  1059. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  1060. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js +32 -0
  1061. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js.map +1 -1
  1062. package/build/dist/Types/Monitor/MonitorUptimeSummary.js +52 -0
  1063. package/build/dist/Types/Monitor/MonitorUptimeSummary.js.map +1 -0
  1064. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +9 -1
  1065. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
  1066. package/build/dist/Types/Permission.js +42 -0
  1067. package/build/dist/Types/Permission.js.map +1 -1
  1068. package/build/dist/Types/Rum/SessionReplay.js +52 -2
  1069. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  1070. package/build/dist/Types/Rum/SessionReplayApi.js +11 -0
  1071. package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
  1072. package/build/dist/Types/Rum/UserFlow.js +115 -0
  1073. package/build/dist/Types/Rum/UserFlow.js.map +1 -0
  1074. package/build/dist/Types/Rum/WebVitals.js +25 -0
  1075. package/build/dist/Types/Rum/WebVitals.js.map +1 -1
  1076. package/build/dist/Types/Runbook/RunbookStepType.js +10 -0
  1077. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  1078. package/build/dist/Types/Runbook/RunnerJobOrigin.js +14 -0
  1079. package/build/dist/Types/Runbook/RunnerJobOrigin.js.map +1 -1
  1080. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +2 -2
  1081. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -1
  1082. package/build/dist/Types/StatusPage/MergedDowntimeTotals.js +2 -0
  1083. package/build/dist/Types/StatusPage/MergedDowntimeTotals.js.map +1 -0
  1084. package/build/dist/Types/StatusPage/PublicNoteSubscriberNotificationDefault.js +65 -0
  1085. package/build/dist/Types/StatusPage/PublicNoteSubscriberNotificationDefault.js.map +1 -0
  1086. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +8 -0
  1087. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
  1088. package/build/dist/Types/Timezone.js +5 -0
  1089. package/build/dist/Types/Timezone.js.map +1 -1
  1090. package/build/dist/Types/TimezoneAlias.js +340 -0
  1091. package/build/dist/Types/TimezoneAlias.js.map +1 -0
  1092. package/build/dist/Types/Workflow/Templates.js +2694 -2
  1093. package/build/dist/Types/Workflow/Templates.js.map +1 -1
  1094. package/build/dist/Types/Workflow/WorkflowVariableOAuth.js +314 -0
  1095. package/build/dist/Types/Workflow/WorkflowVariableOAuth.js.map +1 -0
  1096. package/build/dist/Types/Workspace/WorkspaceNoteReaction.js +98 -0
  1097. package/build/dist/Types/Workspace/WorkspaceNoteReaction.js.map +1 -0
  1098. package/build/dist/UI/Components/AttributesJSON/AttributesJSONPreferences.js +95 -0
  1099. package/build/dist/UI/Components/AttributesJSON/AttributesJSONPreferences.js.map +1 -0
  1100. package/build/dist/UI/Components/AttributesJSON/AttributesJSONView.js +44 -0
  1101. package/build/dist/UI/Components/AttributesJSON/AttributesJSONView.js.map +1 -0
  1102. package/build/dist/UI/Components/AttributesJSON/AttributesViewToggle.js +27 -0
  1103. package/build/dist/UI/Components/AttributesJSON/AttributesViewToggle.js.map +1 -0
  1104. package/build/dist/UI/Components/AttributesJSON/BracesGlyph.js +9 -0
  1105. package/build/dist/UI/Components/AttributesJSON/BracesGlyph.js.map +1 -0
  1106. package/build/dist/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.js +260 -0
  1107. package/build/dist/UI/Components/AttributesJSON/CopyAttributesAsJSONButton.js.map +1 -0
  1108. package/build/dist/UI/Components/AttributesJSON/JSONHighlight.js +56 -0
  1109. package/build/dist/UI/Components/AttributesJSON/JSONHighlight.js.map +1 -0
  1110. package/build/dist/UI/Components/Calendar/Calendar.js +94 -7
  1111. package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
  1112. package/build/dist/UI/Components/Calendar/CalendarDayLayout.js +136 -0
  1113. package/build/dist/UI/Components/Calendar/CalendarDayLayout.js.map +1 -0
  1114. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +1 -1
  1115. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  1116. package/build/dist/UI/Components/Charts/Utils/HistogramSelection.js +72 -0
  1117. package/build/dist/UI/Components/Charts/Utils/HistogramSelection.js.map +1 -0
  1118. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +178 -0
  1119. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -0
  1120. package/build/dist/UI/Components/Charts/Utils/useHistogramZoom.js +13 -1
  1121. package/build/dist/UI/Components/Charts/Utils/useHistogramZoom.js.map +1 -1
  1122. package/build/dist/UI/Components/Date/CustomTimeRangeModal.js +20 -4
  1123. package/build/dist/UI/Components/Date/CustomTimeRangeModal.js.map +1 -1
  1124. package/build/dist/UI/Components/Detail/FieldLabel.js +2 -0
  1125. package/build/dist/UI/Components/Detail/FieldLabel.js.map +1 -1
  1126. package/build/dist/UI/Components/Dropdown/Dropdown.js +33 -9
  1127. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  1128. package/build/dist/UI/Components/Forms/Fields/FormField.js +36 -13
  1129. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  1130. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +117 -11
  1131. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  1132. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +5 -1
  1133. package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
  1134. package/build/dist/UI/Components/Graphs/UptimeDaySummary.js.map +1 -1
  1135. package/build/dist/UI/Components/InfoCard/InfoCard.js +22 -1
  1136. package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
  1137. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +36 -8
  1138. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  1139. package/build/dist/UI/Components/LogsViewer/components/ColumnSelector.js +10 -2
  1140. package/build/dist/UI/Components/LogsViewer/components/ColumnSelector.js.map +1 -1
  1141. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js +9 -1
  1142. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js.map +1 -1
  1143. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +16 -15
  1144. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
  1145. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +1 -1
  1146. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  1147. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +14 -74
  1148. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  1149. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +22 -5
  1150. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  1151. package/build/dist/UI/Components/LogsViewer/components/SavedViewsDropdown.js +9 -2
  1152. package/build/dist/UI/Components/LogsViewer/components/SavedViewsDropdown.js.map +1 -1
  1153. package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js +16 -5
  1154. package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js.map +1 -1
  1155. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +89 -22
  1156. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  1157. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +7 -1
  1158. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  1159. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +5 -1
  1160. package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
  1161. package/build/dist/UI/Components/Page/ModelPage.js +37 -3
  1162. package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
  1163. package/build/dist/UI/Components/Table/TableHeader.js +18 -2
  1164. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  1165. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +27 -6
  1166. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  1167. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js +7 -1
  1168. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js.map +1 -1
  1169. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +1 -1
  1170. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  1171. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +17 -77
  1172. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  1173. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +10 -1
  1174. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
  1175. package/build/dist/UI/Components/Tooltip/InfoTooltip.js +28 -0
  1176. package/build/dist/UI/Components/Tooltip/InfoTooltip.js.map +1 -0
  1177. package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js +15 -1
  1178. package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js.map +1 -1
  1179. package/build/dist/UI/Utils/PermissionGate.js +4 -2
  1180. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  1181. package/build/dist/UI/Utils/Timezone.js +52 -17
  1182. package/build/dist/UI/Utils/Timezone.js.map +1 -1
  1183. package/build/dist/Utils/AI/InvestigationReport.js +116 -21
  1184. package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
  1185. package/build/dist/Utils/AiRemediation/KubectlOutputRedactor.js +1209 -0
  1186. package/build/dist/Utils/AiRemediation/KubectlOutputRedactor.js.map +1 -0
  1187. package/build/dist/Utils/AiRemediation/KubectlPolicy.js +2973 -0
  1188. package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -0
  1189. package/build/dist/Utils/AiRemediation/KubectlWaitBudget.js +99 -0
  1190. package/build/dist/Utils/AiRemediation/KubectlWaitBudget.js.map +1 -0
  1191. package/build/dist/Utils/AiRemediation/KubectlWriteScope.js +1429 -0
  1192. package/build/dist/Utils/AiRemediation/KubectlWriteScope.js.map +1 -0
  1193. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js +7 -6
  1194. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js.map +1 -1
  1195. package/build/dist/Utils/Incident/IncidentFromAlerts.js +306 -0
  1196. package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -0
  1197. package/build/dist/Utils/Monitor/IncomingEmailMonitorAddress.js +214 -0
  1198. package/build/dist/Utils/Monitor/IncomingEmailMonitorAddress.js.map +1 -0
  1199. package/build/dist/Utils/Monitor/MonitorCheckScheduleUtil.js +471 -0
  1200. package/build/dist/Utils/Monitor/MonitorCheckScheduleUtil.js.map +1 -0
  1201. package/build/dist/Utils/Monitor/MonitorOverviewCriteriaUtil.js +107 -0
  1202. package/build/dist/Utils/Monitor/MonitorOverviewCriteriaUtil.js.map +1 -0
  1203. package/build/dist/Utils/Monitor/MonitorOverviewFamily.js +191 -0
  1204. package/build/dist/Utils/Monitor/MonitorOverviewFamily.js.map +1 -0
  1205. package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js +1259 -0
  1206. package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js.map +1 -0
  1207. package/build/dist/Utils/Monitor/MonitorOverviewProbeUtil.js +593 -0
  1208. package/build/dist/Utils/Monitor/MonitorOverviewProbeUtil.js.map +1 -0
  1209. package/build/dist/Utils/Monitor/MonitorOverviewTargetUtil.js +195 -0
  1210. package/build/dist/Utils/Monitor/MonitorOverviewTargetUtil.js.map +1 -0
  1211. package/build/dist/Utils/Monitor/MonitorStatusHistoryUtil.js +127 -0
  1212. package/build/dist/Utils/Monitor/MonitorStatusHistoryUtil.js.map +1 -0
  1213. package/build/dist/Utils/Monitor/MonitorUptimeSummaryUtil.js +464 -0
  1214. package/build/dist/Utils/Monitor/MonitorUptimeSummaryUtil.js.map +1 -0
  1215. package/build/dist/Utils/Rum/SessionIdentity.js +31 -1
  1216. package/build/dist/Utils/Rum/SessionIdentity.js.map +1 -1
  1217. package/build/dist/Utils/Rum/SessionReplayWireEncoding.js +128 -0
  1218. package/build/dist/Utils/Rum/SessionReplayWireEncoding.js.map +1 -0
  1219. package/build/dist/Utils/Rum/SessionTraceState.js +154 -0
  1220. package/build/dist/Utils/Rum/SessionTraceState.js.map +1 -0
  1221. package/build/dist/Utils/Rum/UserFlow.js +941 -0
  1222. package/build/dist/Utils/Rum/UserFlow.js.map +1 -0
  1223. package/build/dist/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.js +82 -0
  1224. package/build/dist/Utils/StatusPage/MonitorGroupMergedDowntimeUtil.js.map +1 -0
  1225. package/build/dist/Utils/StatusPage/ResourceUptime.js +46 -0
  1226. package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
  1227. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  1228. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -1
  1229. package/build/dist/Utils/Telemetry/AttributesJSON.js +245 -0
  1230. package/build/dist/Utils/Telemetry/AttributesJSON.js.map +1 -0
  1231. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js +103 -0
  1232. package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js.map +1 -1
  1233. package/build/dist/Utils/Uptime/UptimeUtil.js +91 -27
  1234. package/build/dist/Utils/Uptime/UptimeUtil.js.map +1 -1
  1235. package/jest.config.json +2 -1
  1236. package/package.json +2 -1
  1237. package/tsconfig.tests.json +36 -0
  1238. package/Tests/UI/Components/EmptyState/EmptyStateGuideLinks.test.tsx +0 -337
  1239. package/UI/Components/EmptyState/EmptyStateGuideLinks.tsx +0 -124
  1240. package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js +0 -47
  1241. package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js.map +0 -1
@@ -45,6 +45,7 @@ export var WorkflowTemplateCategory;
45
45
  WorkflowTemplateCategory["ScheduledMaintenance"] = "Scheduled Maintenance";
46
46
  WorkflowTemplateCategory["OnCall"] = "On-Call";
47
47
  WorkflowTemplateCategory["Scheduled"] = "On a Schedule";
48
+ WorkflowTemplateCategory["Jira"] = "Jira";
48
49
  WorkflowTemplateCategory["Integrations"] = "Integrations";
49
50
  })(WorkflowTemplateCategory || (WorkflowTemplateCategory = {}));
50
51
  /** Display order in the picker. Basics first, because that is where a new builder should start. */
@@ -57,6 +58,7 @@ export const WorkflowTemplateCategories = [
57
58
  WorkflowTemplateCategory.StatusPage,
58
59
  WorkflowTemplateCategory.ScheduledMaintenance,
59
60
  WorkflowTemplateCategory.Scheduled,
61
+ WorkflowTemplateCategory.Jira,
60
62
  WorkflowTemplateCategory.Integrations,
61
63
  ];
62
64
  /*
@@ -161,6 +163,2694 @@ const MONITOR_STATUS_TIMELINE_SELECT = {
161
163
  monitor: { name: true },
162
164
  monitorStatus: { name: true, isOfflineState: true },
163
165
  };
166
+ /* ------------------------------- Jira ------------------------------- */
167
+ /*
168
+ * The Jira templates are small workflows rather than one large one, so a team
169
+ * can take only the directions it wants — for incidents, for alerts, or both.
170
+ * They still have to agree on two things, because each one reads what another
171
+ * wrote.
172
+ *
173
+ * How a record and an issue find each other. Jira holds the link: an issue
174
+ * that belongs to an incident carries the labels `oneuptime` and
175
+ * `oneuptime-incident-<incident id>` (an alert's, `oneuptime-alert-<alert
176
+ * id>`), and every template looks the other side up by that label. Jira is
177
+ * the better home for it: OneUptime's customFields is one JSON value, so
178
+ * writing a key into it from a workflow replaces every other custom field on
179
+ * the record. The one exception is written at create time, when there is
180
+ * nothing to replace: a record created from Jira keeps the issue key in
181
+ * customFields.jiraIssueKey.
182
+ *
183
+ * How they avoid echoing each other. Every write in one direction is an event
184
+ * in the other: a comment copied into Jira arrives back as a comment_created
185
+ * webhook, and a note copied into OneUptime fires the note trigger. Text each
186
+ * side writes starts with a marker, and the template going the other way skips
187
+ * anything that carries it. Issue creation is guarded by the labels and by
188
+ * customFields.jiraIssueKey, and state changes settle on their own because a
189
+ * record only ever moves forward.
190
+ *
191
+ * The incident and alert versions are built from one set of builders, so the
192
+ * two cannot drift apart. JiraRecordKind below is everything that differs.
193
+ * Everything else the templates share lives in the scripts' helper block.
194
+ */
195
+ /** Starts every comment OneUptime writes into Jira. Issues are guarded by their labels instead. */
196
+ export const JIRA_SYNCED_FROM_ONEUPTIME_MARKER = "Synced from OneUptime";
197
+ /** Starts every note, and every state change's cause, that OneUptime writes from a Jira event. */
198
+ export const ONEUPTIME_SYNCED_FROM_JIRA_MARKER = "Synced from Jira";
199
+ /** Carried by every Jira issue linked to a OneUptime incident or alert. */
200
+ export const JIRA_LINK_LABEL = "oneuptime";
201
+ /** Followed by the incident's id; the label is how either side finds the other. */
202
+ export const JIRA_INCIDENT_LABEL_PREFIX = "oneuptime-incident-";
203
+ /** Followed by the alert's id, for the alert versions of the templates. */
204
+ export const JIRA_ALERT_LABEL_PREFIX = "oneuptime-alert-";
205
+ const INCIDENT_KIND = {
206
+ noun: "incident",
207
+ Noun: "Incident",
208
+ plural: "incidents",
209
+ Plural: "Incidents",
210
+ upper: "INCIDENT",
211
+ pluralUpper: "INCIDENTS",
212
+ labelPrefix: JIRA_INCIDENT_LABEL_PREFIX,
213
+ numberField: "incidentNumberWithPrefix",
214
+ severityRelation: "incidentSeverity",
215
+ severityIdColumn: "incidentSeverityId",
216
+ stateRelation: "currentIncidentState",
217
+ stateIdColumn: "currentIncidentStateId",
218
+ idColumn: "incidentId",
219
+ timelineStateColumn: "incidentStateId",
220
+ dashboardPath: "incidents",
221
+ created: "declared",
222
+ Created: "Declared",
223
+ create: "declare",
224
+ Create: "Declare",
225
+ creating: "Declaring",
226
+ quietCreateFields: {
227
+ isVisibleOnStatusPage: false,
228
+ shouldStatusPageSubscribersBeNotifiedOnIncidentCreated: false,
229
+ },
230
+ quietCreateText: ", kept off status pages,",
231
+ editListenOn: {
232
+ title: true,
233
+ description: true,
234
+ incidentSeverityId: true,
235
+ incidentSeverity: true,
236
+ rootCause: true,
237
+ remediationNotes: true,
238
+ },
239
+ editedFieldsText: "title, severity, description, root cause or remediation notes",
240
+ hasPublicNotes: true,
241
+ otherPlural: "alerts",
242
+ };
243
+ const ALERT_KIND = {
244
+ noun: "alert",
245
+ Noun: "Alert",
246
+ plural: "alerts",
247
+ Plural: "Alerts",
248
+ upper: "ALERT",
249
+ pluralUpper: "ALERTS",
250
+ labelPrefix: JIRA_ALERT_LABEL_PREFIX,
251
+ numberField: "alertNumberWithPrefix",
252
+ severityRelation: "alertSeverity",
253
+ severityIdColumn: "alertSeverityId",
254
+ stateRelation: "currentAlertState",
255
+ stateIdColumn: "currentAlertStateId",
256
+ idColumn: "alertId",
257
+ timelineStateColumn: "alertStateId",
258
+ dashboardPath: "alerts",
259
+ created: "created",
260
+ Created: "Created",
261
+ create: "create",
262
+ Create: "Create",
263
+ creating: "Creating",
264
+ quietCreateFields: {},
265
+ quietCreateText: "",
266
+ /*
267
+ * An alert's root cause is written when the alert is created and cannot be
268
+ * edited afterwards, so it is not listened on. The comment still shows it.
269
+ */
270
+ editListenOn: {
271
+ title: true,
272
+ description: true,
273
+ alertSeverityId: true,
274
+ alertSeverity: true,
275
+ remediationNotes: true,
276
+ },
277
+ editedFieldsText: "title, severity, description or remediation notes",
278
+ hasPublicNotes: false,
279
+ otherPlural: "incidents",
280
+ };
281
+ const JIRA_BASE_URL = {
282
+ name: "jiraBaseUrl",
283
+ title: "Jira Site URL",
284
+ description: "Your Jira Cloud site, starting with https:// and with no trailing slash. With a scoped API token, use https://api.atlassian.com/ex/jira/<cloud id> instead.",
285
+ placeholder: "https://your-company.atlassian.net",
286
+ required: true,
287
+ isSecret: false,
288
+ };
289
+ /*
290
+ * Jira Cloud takes an API token as HTTP Basic auth: base64 of
291
+ * "email:api_token". A workflow cannot base64-encode on its own without a
292
+ * script, and a script that did it would return the encoded credential as an
293
+ * ordinary value — which is written to the run log unredacted, because only
294
+ * the literal content of a secret variable is scrubbed. So the variable holds
295
+ * the encoded value itself, and it only ever appears in request headers.
296
+ */
297
+ const JIRA_BASIC_AUTH_TOKEN = {
298
+ name: "jiraBasicAuthToken",
299
+ title: "Jira API Token (base64 of email:token)",
300
+ description: "Create an API token at id.atlassian.com/manage-profile/security/api-tokens for a dedicated Jira user, then encode it with that user's email on one line: printf '%s' 'you@example.com:API_TOKEN' | base64 | tr -d '\\n'",
301
+ placeholder: "eW91QGV4YW1wbGUuY29tOkFUQVRULi4u",
302
+ required: true,
303
+ isSecret: true,
304
+ };
305
+ const JIRA_PROJECT_KEY = {
306
+ name: "jiraProjectKey",
307
+ title: "Jira Project Key",
308
+ description: "The project (space) new issues are filed in — the OPS in OPS-123.",
309
+ placeholder: "OPS",
310
+ required: true,
311
+ isSecret: false,
312
+ };
313
+ const JIRA_ISSUE_TYPE = {
314
+ name: "jiraIssueType",
315
+ title: "Jira Issue Type",
316
+ description: "The issue type to create, spelled exactly as it is in that project — for example Task, Bug or Incident.",
317
+ placeholder: "Task",
318
+ required: true,
319
+ isSecret: false,
320
+ };
321
+ /*
322
+ * Only the wording differs between the two kinds. The name, and with it
323
+ * whether the value is required or secret, is the same everywhere.
324
+ */
325
+ const oneUptimeUrlVariable = (kind) => {
326
+ return {
327
+ name: "oneuptimeUrl",
328
+ title: "OneUptime URL",
329
+ description: `The address you open OneUptime at, used to link the Jira issue back to the ${kind.noun} — https://oneuptime.com, or your own host.`,
330
+ placeholder: "https://oneuptime.com",
331
+ required: true,
332
+ isSecret: false,
333
+ };
334
+ };
335
+ /*
336
+ * Jira Service Management shows a comment to the customer unless it is marked
337
+ * internal, and this comment property is how the platform API marks one. On
338
+ * any other kind of project it is an ordinary property nothing reads.
339
+ */
340
+ const JIRA_INTERNAL_COMMENT_PROPERTY = {
341
+ key: "sd.public.comment",
342
+ value: { internal: true },
343
+ };
344
+ /*
345
+ * An object rather than JSON text: an object-valued argument is substituted
346
+ * with JSON escaping and handed back as an object. The argument is marked
347
+ * sensitive, so the whole header set is kept out of the run log.
348
+ */
349
+ const jiraHeaders = () => {
350
+ return {
351
+ Authorization: "Basic {{local.variables.jiraBasicAuthToken}}",
352
+ };
353
+ };
354
+ /*
355
+ * Request bodies are stored as JSON text, the way the builder saves them.
356
+ * Serializing an object literal keeps every body valid JSON by construction;
357
+ * the {{...}} references inside it all sit within string values.
358
+ */
359
+ const jsonText = (value) => {
360
+ return JSON.stringify(value, null, 2);
361
+ };
362
+ /*
363
+ * Jira Cloud's v3 API takes rich text as an Atlassian Document Format tree,
364
+ * not a string. Each paragraph here holds a single text node, and a text node
365
+ * must not be empty, so every one either starts with fixed words or holds a
366
+ * value the step before it guarantees is non-empty.
367
+ */
368
+ const adfDocument = (paragraphs) => {
369
+ return { type: "doc", version: 1, content: paragraphs };
370
+ };
371
+ const adfParagraph = (text, href) => {
372
+ const node = { type: "text", text: text };
373
+ if (href) {
374
+ node["marks"] = [{ type: "link", attrs: { href: href } }];
375
+ }
376
+ return { type: "paragraph", content: [node] };
377
+ };
378
+ /*
379
+ * Finds the issue linked to a record by its label. POSTed rather than put in
380
+ * a query string, because references are not URL-encoded when they are
381
+ * substituted and JQL is full of spaces, quotes and equals signs. The older
382
+ * /rest/api/3/search endpoint has been removed; /search/jql replaced it, and
383
+ * without `fields` it returns ids only — not even the key.
384
+ */
385
+ const jiraSearchBody = (props) => {
386
+ const body = {
387
+ jql: `labels = "${props.kind.labelPrefix}${props.idReference}" ORDER BY created ASC`,
388
+ fields: props.fields,
389
+ /*
390
+ * Two, not one: the scripts need to see a second match to refuse it. A
391
+ * clone copies labels, and anyone who can edit an issue the token can see
392
+ * can add one, so "the first match" could be an issue that is not the
393
+ * record's — and private notes would be posted to it.
394
+ */
395
+ maxResults: 2,
396
+ };
397
+ if (props.expandTransitions) {
398
+ body["expand"] = "transitions";
399
+ }
400
+ return jsonText(body);
401
+ };
402
+ /*
403
+ * Every Jira script starts with the same helper block, so each one can be read
404
+ * and edited on its own. Two rules hold for all of them:
405
+ *
406
+ * - No double braces anywhere in the source. The script is an argument like
407
+ * any other, so a {{...}} in it would be substituted before it runs. Where
408
+ * the code needs the characters, it builds them ('{' + '{').
409
+ * - Text that came from the other system goes through defuse() before it is
410
+ * returned. A later step quotes these return values into its own
411
+ * arguments, and text that still held a {{...}} would be substituted there
412
+ * — a Jira comment could name a secret variable and have it filled in.
413
+ *
414
+ * isLinked recognises both kinds of link label, so an issue that is already
415
+ * linked when its event arrives — one OneUptime filed for an incident, say —
416
+ * is never also made an alert, or the other way round. It cannot separate the
417
+ * two create-from-Jira templates when both receive the same new issue: each
418
+ * checks before either labels it. Their Jira webhook filters must not overlap,
419
+ * and their descriptions say so.
420
+ */
421
+ const jiraScript = (kind, body) => {
422
+ const helpers = String.raw `// ---- Shared by the Jira templates ----
423
+ const FROM_ONEUPTIME = ${JSON.stringify(JIRA_SYNCED_FROM_ONEUPTIME_MARKER)};
424
+ const FROM_JIRA = ${JSON.stringify(ONEUPTIME_SYNCED_FROM_JIRA_MARKER)};
425
+ const LINK_LABEL = ${JSON.stringify(JIRA_LINK_LABEL)};
426
+ const ${kind.upper}_LABEL_PREFIX = ${JSON.stringify(kind.labelPrefix)};
427
+ // The label prefixes of every kind of record an issue can be linked to.
428
+ const LINKED_LABEL_PREFIXES = ${JSON.stringify([
429
+ JIRA_INCIDENT_LABEL_PREFIX,
430
+ JIRA_ALERT_LABEL_PREFIX,
431
+ ])};
432
+ const ISSUE_KEY = /^[A-Za-z][A-Za-z0-9_]*-[0-9]+$/;
433
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
434
+
435
+ // Another step's output quoted into the arguments arrives as JSON text.
436
+ const readJson = (value) => {
437
+ if (typeof value !== 'string') return value === undefined ? null : value;
438
+ try { return JSON.parse(value); } catch (error) { return null; }
439
+ };
440
+ const asText = (value) => (typeof value === 'string' ? value : typeof value === 'number' ? String(value) : '');
441
+ // OneUptime ids, names and dates are serialized as { _type, value }.
442
+ const valueOf = (value) => (value && typeof value === 'object' ? asText(value.value) : asText(value));
443
+ // Drops the control characters JSON and Jira reject, keeping tabs and line breaks.
444
+ const clean = (value) => Array.from(asText(value)).filter((c) => {
445
+ const code = c.charCodeAt(0);
446
+ return code === 9 || code === 10 || (code >= 32 && code !== 127);
447
+ }).join('');
448
+ const oneLine = (value) => clean(value).replace(/\s+/g, ' ').trim();
449
+ const limit = (value, max) => (value.length > max ? value.slice(0, max - 1) + '…' : value);
450
+ // Breaks up double braces so a later step cannot read the text as a reference.
451
+ const defuse = (value) => {
452
+ let text = value;
453
+ while (text.indexOf('{' + '{') !== -1) text = text.split('{' + '{').join('{ {');
454
+ while (text.indexOf('}' + '}') !== -1) text = text.split('}' + '}').join('} }');
455
+ return text;
456
+ };
457
+ // Atlassian Document Format flattened to text. Wiki-markup strings pass through.
458
+ const plainText = (value) => {
459
+ if (typeof value === 'string') return value;
460
+ if (!value || typeof value !== 'object') return '';
461
+ const children = Array.isArray(value.content) ? value.content.map(plainText) : [];
462
+ return asText(value.text) + (value.type === 'hardBreak' ? '\n' : '') + children.join(value.type === 'doc' ? '\n' : '');
463
+ };
464
+ const displayName = (user) => (user && typeof user === 'object' ? asText(user.displayName) || valueOf(user.name) : '');
465
+ // The ${kind.noun} id in a linked issue's ${kind.labelPrefix}<id> label.
466
+ const ${kind.noun}IdFromLabels = (labels) => {
467
+ for (const label of Array.isArray(labels) ? labels : []) {
468
+ const text = asText(label).toLowerCase();
469
+ const id = text.slice(${kind.upper}_LABEL_PREFIX.length);
470
+ if (text.indexOf(${kind.upper}_LABEL_PREFIX) === 0 && UUID.test(id)) return id;
471
+ }
472
+ return '';
473
+ };
474
+ const isLinked = (labels) => (Array.isArray(labels) ? labels : []).some((label) => {
475
+ const text = asText(label).toLowerCase();
476
+ return text === LINK_LABEL || LINKED_LABEL_PREFIXES.some((prefix) => text.indexOf(prefix) === 0);
477
+ });
478
+ // https://your-company.atlassian.net, read off an issue's own REST URL.
479
+ const siteOf = (self) => {
480
+ const match = asText(self).match(/^https?:\/\/[^/]+/);
481
+ return match ? match[0] : '';
482
+ };
483
+ const issueLink = (self, issueKey) => {
484
+ const site = siteOf(self);
485
+ return site ? '[' + issueKey + '](' + site + '/browse/' + issueKey + ')' : issueKey;
486
+ };
487
+ // A bare "#12" says nothing about what it numbers, so it gets a name: "${kind.Noun} #12".
488
+ const numbered = (value) => {
489
+ const text = asText(value);
490
+ return text.charAt(0) === '#' ? ${JSON.stringify(kind.Noun)} + ' ' + text : text;
491
+ };
492
+ // Reasons can quote the other system's text, so they are defused like everything else.
493
+ const skip = (reason) => ({ proceed: false, reason: defuse(asText(reason)) });
494
+ // The one issue a label search found for an ${kind.noun}. More than one means a clone or
495
+ // a hand-added label is also claiming the ${kind.noun}, and guessing would post to the
496
+ // wrong issue, so the step stops and says which issues to fix.
497
+ const linkedIssue = (search, ${kind.noun}Id) => {
498
+ const label = ${kind.upper}_LABEL_PREFIX + ${kind.noun}Id;
499
+ const issues = (search && Array.isArray(search.issues) ? search.issues : [])
500
+ .filter((issue) => issue && ISSUE_KEY.test(asText(issue.key)));
501
+ if (!issues.length) return { reason: 'No Jira issue is labelled ' + label + ', or the Jira credentials cannot see it.' };
502
+ if (issues.length > 1) {
503
+ return { reason: 'More than one Jira issue is labelled ' + label + ' (' + issues.map((issue) => asText(issue.key)).join(', ') + '). A cloned issue copies the label: remove it from every issue except the one filed for the ${kind.noun}.' };
504
+ }
505
+ return { issue: issues[0], issueKey: asText(issues[0].key) };
506
+ };
507
+ `;
508
+ return `${helpers}\n// ---- What this step does ----\n${body.trim()}\n`;
509
+ };
510
+ /*
511
+ * OneUptime -> Jira: shapes a new record into an issue's summary and
512
+ * description. The issue's fields themselves are in the API step, where they
513
+ * are easiest to extend.
514
+ */
515
+ const jiraPrepareIssueScript = (kind) => {
516
+ const r = kind.noun;
517
+ return jiraScript(kind, String.raw `
518
+ // Turns the new ${r} into the Jira issue's summary and description.
519
+ // Edit the wording here. The issue's other fields are in the "Create Jira issue" step.
520
+ // Private ${kind.plural} stay in OneUptime. Set this to true to file them in Jira anyway.
521
+ const SYNC_PRIVATE_${kind.pluralUpper} = false;
522
+
523
+ const ${r} = readJson(args.${r}) || {};
524
+ const customFields = ${r}.customFields || {};
525
+ const number = numbered(${r}.${kind.numberField}) || 'The ${r}';
526
+
527
+ // The label is the only link between the two, so there is no issue without an id.
528
+ if (!UUID.test(asText(${r}._id))) return skip('The trigger did not hand over an ${r} id.');
529
+
530
+ if (${r}.isPrivate === true && !SYNC_PRIVATE_${kind.pluralUpper}) {
531
+ return skip(number + ' is a private ${r}, so no Jira issue was created.');
532
+ }
533
+
534
+ // ${kind.Created} from a Jira issue: it already has one, and opening another would loop.
535
+ if (asText(customFields.jiraIssueKey)) {
536
+ return skip(number + ' was ${kind.created} from Jira issue ' + asText(customFields.jiraIssueKey) + ', so no new issue was created.');
537
+ }
538
+
539
+ const severity = ${r}.${kind.severityRelation} ? oneLine(${r}.${kind.severityRelation}.name) : '';
540
+ const state = ${r}.${kind.stateRelation} ? oneLine(${r}.${kind.stateRelation}.name) : '';
541
+ const description = clean(${r}.description).trim();
542
+
543
+ const lines = [number + ' was ${kind.created} in OneUptime.'];
544
+ if (severity) lines.push('Severity: ' + severity);
545
+ if (state) lines.push('State: ' + state);
546
+ if (description) lines.push('', description);
547
+ // A monitor fills these in when it raises the ${r}; often they say more than the description.
548
+ const rootCause = clean(${r}.rootCause).trim();
549
+ if (rootCause) lines.push('', 'Root cause:', limit(rootCause, 5000));
550
+ const remediation = clean(${r}.remediationNotes).trim();
551
+ if (remediation) lines.push('', 'Remediation:', limit(remediation, 5000));
552
+
553
+ let oneUptimeUrl = oneLine(args.oneuptimeUrl).replace(/\/+$/, '');
554
+ if (!/^https?:\/\//i.test(oneUptimeUrl)) oneUptimeUrl = 'https://' + oneUptimeUrl;
555
+
556
+ return {
557
+ proceed: true,
558
+ // Jira rejects a summary over 255 characters or with a line break in it.
559
+ summary: limit(defuse(oneLine('[OneUptime] ' + number + ': ' + (oneLine(${r}.title) || 'Untitled ${r}'))), 255),
560
+ description: limit(defuse(lines.join('\n')), 30000),
561
+ ${r}Label: ${kind.upper}_LABEL_PREFIX + asText(${r}._id).toLowerCase(),
562
+ ${r}Url: oneUptimeUrl + '/dashboard/' + valueOf(${r}.projectId) + '/${kind.dashboardPath}/' + asText(${r}._id),
563
+ };
564
+ `);
565
+ };
566
+ /*
567
+ * OneUptime -> Jira: picks the transition for the record's new state out of
568
+ * the transitions the search returned for the linked issue.
569
+ */
570
+ const jiraPlanTransitionScript = (kind) => {
571
+ const r = kind.noun;
572
+ return jiraScript(kind, String.raw `
573
+ // Picks the Jira transition that matches the ${r}'s new state.
574
+ // To map a OneUptime state to one Jira status by name, list it here, for example
575
+ // { Resolved: 'Resolved', Monitoring: 'In Review' }. Everything else goes by meaning:
576
+ // acknowledged moves the issue to an In Progress status, and resolved to a Done one.
577
+ // A workflow with several Done statuses, such as Jira Service Management's Resolved,
578
+ // Canceled and Closed, needs the one to use named here.
579
+ const STATE_TO_JIRA_STATUS = {};
580
+ // Private ${kind.plural} stay in OneUptime. Set this to true to sync them anyway.
581
+ const SYNC_PRIVATE_${kind.pluralUpper} = false;
582
+ // Going by meaning, a status with one of these names wins, and a status matching
583
+ // NEVER_GUESS is only ever used when STATE_TO_JIRA_STATUS names it.
584
+ const PREFERRED_STATUS = { done: /^(done|resolved|closed|complete|completed|fixed)$/i, indeterminate: /^(in progress|work in progress)$/i };
585
+ const NEVER_GUESS = /cancel|declin|reject|won.?t|duplicate|obsolete|waiting|pending|escalat|on hold|blocked/i;
586
+ // Jira's status categories, in the order work moves through them.
587
+ const CATEGORY_RANK = { new: 0, indeterminate: 1, done: 2 };
588
+
589
+ const ${r} = readJson(args.${r}) || {};
590
+ const search = readJson(args.search) || {};
591
+ const state = ${r}.${kind.stateRelation} || {};
592
+ const stateName = oneLine(state.name);
593
+ const number = numbered(${r}.${kind.numberField}) || 'The ${r}';
594
+
595
+ if (${r}.isPrivate === true && !SYNC_PRIVATE_${kind.pluralUpper}) {
596
+ return skip(number + ' is a private ${r}, so its Jira issue was not moved.');
597
+ }
598
+
599
+ const wantedName = oneLine(STATE_TO_JIRA_STATUS[stateName]);
600
+ const wantedCategory = wantedName ? '' : state.isResolvedState === true ? 'done' : state.isAcknowledgedState === true ? 'indeterminate' : '';
601
+ if (!wantedName && !wantedCategory) {
602
+ return skip(number + ' moved to ' + (stateName || 'a new state') + ', which has no Jira status mapped to it.');
603
+ }
604
+ const wanted = wantedName || (wantedCategory === 'done' ? 'a Done status' : 'an In Progress status');
605
+
606
+ const found = linkedIssue(search, asText(${r}._id));
607
+ if (!found.issue) return skip(found.reason);
608
+ const issueKey = found.issueKey;
609
+
610
+ // Match on the status a transition leads to, never on the transition's own name:
611
+ // the two differ, and transition ids differ between Jira workflows.
612
+ const matches = (status) => Boolean(status) && (wantedName
613
+ ? oneLine(status.name).toLowerCase() === wantedName.toLowerCase()
614
+ : Boolean(status.statusCategory) && status.statusCategory.key === wantedCategory);
615
+ const rankOf = (status) => {
616
+ const rank = status && status.statusCategory ? CATEGORY_RANK[asText(status.statusCategory.key)] : undefined;
617
+ return typeof rank === 'number' ? rank : -1;
618
+ };
619
+
620
+ const current = (found.issue.fields && found.issue.fields.status) || {};
621
+ const currentName = oneLine(current.name) || 'its status';
622
+ if (matches(current)) return skip('Jira issue ' + issueKey + ' is already ' + currentName + '.');
623
+
624
+ // Like the ${r}, the issue only moves forward: acknowledging an ${r} whose
625
+ // issue someone already closed leaves the issue closed.
626
+ if (!wantedName && rankOf(current) >= CATEGORY_RANK[wantedCategory]) {
627
+ return skip('Jira issue ' + issueKey + ' is already ' + currentName + ', so it was not moved back to ' + wanted + '.');
628
+ }
629
+
630
+ const score = (transition) => {
631
+ if (wantedName) return 0;
632
+ const name = oneLine(transition.to.name);
633
+ if (PREFERRED_STATUS[wantedCategory].test(name)) return 0;
634
+ return NEVER_GUESS.test(name) ? 2 : 1;
635
+ };
636
+ const reachable = (Array.isArray(found.issue.transitions) ? found.issue.transitions : [])
637
+ .filter((transition) => transition && transition.isAvailable !== false && matches(transition.to));
638
+ const forward = reachable
639
+ .filter((transition) => rankOf(transition.to) < 0 || rankOf(current) < 0 || rankOf(transition.to) >= rankOf(current));
640
+ if (wantedName && !forward.length) {
641
+ return skip(reachable.length
642
+ ? 'Jira issue ' + issueKey + ' is already ' + currentName + ', so it was not moved back to ' + wantedName + '.'
643
+ : 'Jira issue ' + issueKey + ' has no transition from ' + currentName + ' to ' + wantedName + '.');
644
+ }
645
+ const candidates = forward
646
+ .map((transition) => ({ transition: transition, score: score(transition) }))
647
+ .filter((candidate) => candidate.score < 2)
648
+ // Prefer a transition without a screen: those never ask for extra fields.
649
+ .sort((a, b) => a.score - b.score || (a.transition.hasScreen ? 1 : 0) - (b.transition.hasScreen ? 1 : 0));
650
+ if (!candidates.length) {
651
+ return skip('Jira issue ' + issueKey + ' has no transition from ' + currentName + ' to ' + wanted + ' that can be chosen without naming it in STATE_TO_JIRA_STATUS.');
652
+ }
653
+
654
+ // Several different statuses fit equally well. Guessing could, say, cancel a request.
655
+ const best = candidates[0];
656
+ const tied = candidates.filter((candidate) => candidate.score === best.score)
657
+ .map((candidate) => oneLine(candidate.transition.to.name))
658
+ .filter((name, index, names) => names.map((other) => other.toLowerCase()).indexOf(name.toLowerCase()) === index);
659
+ if (tied.length > 1) {
660
+ return skip('Jira issue ' + issueKey + ' could move to ' + tied.join(' or ') + ' for ' + wanted + '. Name the one to use in STATE_TO_JIRA_STATUS.');
661
+ }
662
+
663
+ return {
664
+ proceed: true,
665
+ issueKey: issueKey,
666
+ transitionId: defuse(asText(best.transition.id)),
667
+ jiraStatus: defuse(oneLine(best.transition.to.name)) || wanted,
668
+ reason: number + ' is ' + stateName + ' in OneUptime.',
669
+ };
670
+ `);
671
+ };
672
+ /*
673
+ * OneUptime -> Jira: the comment for a new private or public note. The
674
+ * templates differ only in the trigger and in what they call the note.
675
+ */
676
+ const jiraNoteCommentScript = (kind, noteKind) => {
677
+ const r = kind.noun;
678
+ return jiraScript(kind, String.raw `
679
+ // Writes the Jira comment for a new ${noteKind}.
680
+ const NOTE_KIND = ${JSON.stringify(noteKind)};
681
+ // Notes on private ${kind.plural} stay in OneUptime. Set this to true to post them anyway.
682
+ const SYNC_PRIVATE_${kind.pluralUpper} = false;
683
+
684
+ const note = readJson(args.note) || {};
685
+ const search = readJson(args.search) || {};
686
+ const text = clean(note.note).trim();
687
+ const number = (note.${r} && numbered(note.${r}.${kind.numberField})) || 'the ${r}';
688
+ if (note.${r} && note.${r}.isPrivate === true && !SYNC_PRIVATE_${kind.pluralUpper}) {
689
+ return skip('The note is on ' + number + ', a private ${r}, so it was not posted to Jira.');
690
+ }
691
+ if (!text) return skip('The note is empty, so there is nothing to post.');
692
+
693
+ // Notes copied in from Jira carry this marker. Posting them back would loop.
694
+ if (text.indexOf(FROM_JIRA) !== -1) {
695
+ return skip('This note came from Jira, so it was not posted back.');
696
+ }
697
+
698
+ const found = linkedIssue(search, valueOf(note.${kind.idColumn}));
699
+ if (!found.issue) return skip(found.reason);
700
+ const issueKey = found.issueKey;
701
+
702
+ const author = displayName(note.createdByUser);
703
+ const heading = FROM_ONEUPTIME + ': ' + NOTE_KIND + ' on ' + number + (author ? ' by ' + author : '') + '.';
704
+
705
+ return {
706
+ proceed: true,
707
+ issueKey: issueKey,
708
+ comment: limit(defuse(heading + '\n\n' + text), 30000),
709
+ };
710
+ `);
711
+ };
712
+ /*
713
+ * OneUptime -> Jira: a comment describing the record as it now stands. The
714
+ * update trigger hands over the record's current values, not what changed, so
715
+ * the comment is a snapshot of the fields worth knowing about.
716
+ */
717
+ const jiraUpdateCommentScript = (kind) => {
718
+ const r = kind.noun;
719
+ return jiraScript(kind, String.raw `
720
+ // Writes a Jira comment describing the ${r} as it now stands.
721
+ // Private ${kind.plural} stay in OneUptime. Set this to true to post their changes anyway.
722
+ const SYNC_PRIVATE_${kind.pluralUpper} = false;
723
+
724
+ const ${r} = readJson(args.${r}) || {};
725
+ const search = readJson(args.search) || {};
726
+ const number = numbered(${r}.${kind.numberField}) || 'The ${r}';
727
+
728
+ if (${r}.isPrivate === true && !SYNC_PRIVATE_${kind.pluralUpper}) {
729
+ return skip(number + ' is a private ${r}, so its changes were not posted to Jira.');
730
+ }
731
+
732
+ const found = linkedIssue(search, asText(${r}._id));
733
+ if (!found.issue) return skip(found.reason);
734
+ const issueKey = found.issueKey;
735
+
736
+ const lines = [FROM_ONEUPTIME + ': ' + number + ' was updated.'];
737
+ const add = (label, value, max) => {
738
+ const text = clean(value).trim();
739
+ if (text) lines.push(label + ': ' + limit(text, max));
740
+ };
741
+ add('Title', ${r}.title, 500);
742
+ add('Severity', ${r}.${kind.severityRelation} && ${r}.${kind.severityRelation}.name, 200);
743
+ add('State', ${r}.${kind.stateRelation} && ${r}.${kind.stateRelation}.name, 200);
744
+ add('Root cause', ${r}.rootCause, 5000);
745
+ add('Remediation', ${r}.remediationNotes, 5000);
746
+ add('Description', ${r}.description, 5000);
747
+
748
+ return {
749
+ proceed: true,
750
+ issueKey: issueKey,
751
+ comment: limit(defuse(lines.join('\n')), 30000),
752
+ };
753
+ `);
754
+ };
755
+ /*
756
+ * Jira -> OneUptime: turns a jira:issue_created webhook into the fields of a
757
+ * new record, choosing a severity from the issue's priority.
758
+ */
759
+ const jiraPrepareRecordScript = (kind) => {
760
+ const r = kind.noun;
761
+ return jiraScript(kind, String.raw `
762
+ // Turns a Jira "issue created" event into a OneUptime ${r}.
763
+ // Jira priority to OneUptime severity: 0 is your most severe severity and 2 your
764
+ // least, with the ones in between spread across the range. Priorities that are
765
+ // not listed land in the middle.
766
+ const PRIORITY_RANK = { highest: 0, blocker: 0, critical: 0, high: 0, major: 1, medium: 1, low: 2, minor: 2, lowest: 2, trivial: 2 };
767
+
768
+ const payload = readJson(args.payload) || {};
769
+ const event = asText(payload.webhookEvent);
770
+ const issue = payload.issue || {};
771
+ const fields = issue.fields || {};
772
+ const issueKey = asText(issue.key);
773
+
774
+ if (event !== 'jira:issue_created') {
775
+ return skip(event ? 'Ignored a ' + event + ' event: this workflow only handles jira:issue_created.' : 'The request was not a Jira webhook event, so it was ignored.');
776
+ }
777
+ if (!ISSUE_KEY.test(issueKey)) return skip('The event did not name a Jira issue key.');
778
+
779
+ // Issues OneUptime opened are labelled. ${kind.creating} an ${r} for one would loop.
780
+ if (isLinked(fields.labels)) {
781
+ return skip('Jira issue ' + issueKey + ' is already linked to OneUptime, so no ${r} was ${kind.created}.');
782
+ }
783
+
784
+ const found = readJson(args.severities);
785
+ const severities = (Array.isArray(found) ? found : [])
786
+ .filter((severity) => severity && asText(severity._id))
787
+ .sort((a, b) => Number(a.order) - Number(b.order));
788
+ if (!severities.length) return skip('This project has no ${r} severities to choose from.');
789
+
790
+ const priority = fields.priority ? oneLine(fields.priority.name) : '';
791
+ const rankValue = PRIORITY_RANK[priority.toLowerCase()];
792
+ const rank = typeof rankValue === 'number' ? Math.min(Math.max(rankValue, 0), 2) : 1;
793
+ const severity = severities[Math.round((rank / 2) * (severities.length - 1))];
794
+
795
+ const reporter = displayName(fields.reporter) || displayName(payload.user);
796
+ const lines = ['${kind.Created} from Jira issue ' + issueLink(issue.self, issueKey) + '.'];
797
+ if (priority) lines.push('Priority: ' + priority);
798
+ if (reporter) lines.push('Reported by: ' + reporter);
799
+ const description = clean(plainText(fields.description)).trim();
800
+ if (description) lines.push('', description);
801
+
802
+ return {
803
+ proceed: true,
804
+ issueKey: issueKey,
805
+ severityName: oneLine(severity.name),
806
+ ${kind.severityIdColumn}: asText(severity._id),
807
+ title: limit(defuse(oneLine(fields.summary) || 'Jira issue ' + issueKey), 500),
808
+ description: limit(defuse(lines.join('\n')), 20000),
809
+ };
810
+ `);
811
+ };
812
+ /*
813
+ * Jira -> OneUptime: the create template's second look at the issue, this
814
+ * time as Jira has it rather than as the webhook described it.
815
+ */
816
+ const jiraConfirmUnlinkedScript = (kind) => {
817
+ return jiraScript(kind, String.raw `
818
+ // Checks the issue as Jira has it now, not as the webhook described it: anyone with
819
+ // this workflow's URL can describe any issue, and a delivery Jira retries arrives
820
+ // after the first one has already labelled the issue.
821
+ const issue = readJson(args.issue) || {};
822
+ const issueKey = asText(issue.key);
823
+ if (!ISSUE_KEY.test(issueKey)) return skip('Jira did not return the issue, so no ${kind.noun} was ${kind.created}.');
824
+ if (isLinked(issue.fields && issue.fields.labels)) {
825
+ return skip('Jira issue ' + issueKey + ' is already linked to OneUptime, so no ${kind.noun} was ${kind.created}.');
826
+ }
827
+ return { proceed: true, issueKey: issueKey };
828
+ `);
829
+ };
830
+ /*
831
+ * Jira -> OneUptime: keeps a jira:issue_updated webhook only when the issue's
832
+ * status moved and the issue is linked to a record of this kind.
833
+ */
834
+ const jiraReadStatusChangeScript = (kind) => {
835
+ const r = kind.noun;
836
+ return jiraScript(kind, String.raw `
837
+ // Reads a Jira "issue updated" event and keeps it only if the issue's status moved.
838
+ const payload = readJson(args) || {};
839
+ const event = asText(payload.webhookEvent);
840
+ const issue = payload.issue || {};
841
+ const fields = issue.fields || {};
842
+ const issueKey = asText(issue.key);
843
+
844
+ if (event !== 'jira:issue_updated') {
845
+ return skip(event ? 'Ignored a ' + event + ' event: this workflow only handles jira:issue_updated.' : 'The request was not a Jira webhook event, so it was ignored.');
846
+ }
847
+ if (!ISSUE_KEY.test(issueKey)) return skip('The event did not name a Jira issue key.');
848
+
849
+ // The status item is not always first: resolving an issue lists the resolution before it.
850
+ const items = payload.changelog && Array.isArray(payload.changelog.items) ? payload.changelog.items : [];
851
+ const moved = items.some((item) => item && (asText(item.fieldId) === 'status' || asText(item.field).toLowerCase() === 'status'));
852
+ if (!moved) return skip('Jira issue ' + issueKey + ' changed, but its status did not.');
853
+
854
+ const ${r}Id = ${r}IdFromLabels(fields.labels);
855
+ if (!${r}Id) {
856
+ return skip('Jira issue ' + issueKey + ' is not linked to an ${r}: it has no ' + ${kind.upper}_LABEL_PREFIX + '<id> label.');
857
+ }
858
+
859
+ const status = fields.status || {};
860
+ return {
861
+ proceed: true,
862
+ ${r}Id: ${r}Id,
863
+ issueKey: issueKey,
864
+ // Names are Jira users' text, and the next script receives them quoted into its arguments.
865
+ jiraStatus: defuse(oneLine(status.name)),
866
+ jiraStatusCategory: status.statusCategory ? asText(status.statusCategory.key) : '',
867
+ changedBy: defuse(oneLine(displayName(payload.user))),
868
+ };
869
+ `);
870
+ };
871
+ /*
872
+ * Jira -> OneUptime: maps the issue's new status onto a record state, and
873
+ * only ever moves the record forward.
874
+ */
875
+ const jiraDecideStateScript = (kind) => {
876
+ const r = kind.noun;
877
+ return jiraScript(kind, String.raw `
878
+ // Maps the Jira issue's new status onto a OneUptime ${r} state.
879
+ // To map one Jira status to one state by name, list it here, for example
880
+ // { 'In Review': 'Monitoring' }. Names listed here win over the categories below.
881
+ const JIRA_STATUS_TO_STATE = {};
882
+ // Otherwise the status category decides: In Progress acknowledges the ${r} and
883
+ // Done resolves it. To Do maps to nothing, because an ${r} never moves backwards.
884
+ const CATEGORY_TO_STATE_FLAG = { indeterminate: 'isAcknowledgedState', done: 'isResolvedState' };
885
+
886
+ const event = readJson(args.event) || {};
887
+ const ${r} = readJson(args.${r});
888
+ const states = readJson(args.states);
889
+ if (!${r} || !asText(${r}._id)) {
890
+ return skip('No ${r} with id ' + asText(event.${r}Id) + ' exists in this project.');
891
+ }
892
+
893
+ const number = numbered(${r}.${kind.numberField}) || 'The ${r}';
894
+ const jiraStatus = asText(event.jiraStatus) || 'a new status';
895
+ const list = Array.isArray(states) ? states : [];
896
+ const wantedName = oneLine(JIRA_STATUS_TO_STATE[asText(event.jiraStatus)]).toLowerCase();
897
+ const flag = asText(CATEGORY_TO_STATE_FLAG[asText(event.jiraStatusCategory)]);
898
+ const target = wantedName
899
+ ? list.find((state) => state && oneLine(state.name).toLowerCase() === wantedName)
900
+ : flag ? list.find((state) => state && state[flag] === true) : null;
901
+ if (!target) {
902
+ return skip('Jira issue ' + asText(event.issueKey) + ' moved to ' + jiraStatus + ', which does not map to a OneUptime state.');
903
+ }
904
+
905
+ // An ${r} only moves forward, so an earlier or equal state changes nothing. This
906
+ // is also what settles the echo after the OneUptime-to-Jira template moved the issue.
907
+ const current = ${r}.${kind.stateRelation} || {};
908
+ if (Number(target.order) <= Number(current.order)) {
909
+ return skip(number + ' is already ' + (oneLine(current.name) || 'past that state') + ', so Jira issue ' + asText(event.issueKey) + ' moving to ' + jiraStatus + ' changes nothing.');
910
+ }
911
+
912
+ return {
913
+ proceed: true,
914
+ ${r}Id: asText(${r}._id),
915
+ stateId: asText(target._id),
916
+ stateName: oneLine(target.name),
917
+ rootCause: limit(defuse(FROM_JIRA + ': issue ' + asText(event.issueKey) + ' moved to ' + jiraStatus + (event.changedBy ? ' by ' + oneLine(event.changedBy) : '') + '.'), 1000),
918
+ };
919
+ `);
920
+ };
921
+ /*
922
+ * Jira -> OneUptime: turns a comment_created webhook into the text of a
923
+ * private note.
924
+ */
925
+ const jiraReadCommentScript = (kind) => {
926
+ return jiraScript(kind, String.raw `
927
+ // Reads a Jira comment event and turns it into the text of a OneUptime note.
928
+ // Add 'comment_updated' to also copy edits; each edit then becomes a new note.
929
+ const EVENTS = ['comment_created'];
930
+
931
+ const payload = readJson(args) || {};
932
+ const event = asText(payload.webhookEvent);
933
+ const comment = payload.comment || {};
934
+ const issue = payload.issue || {};
935
+ const issueKey = asText(issue.key);
936
+
937
+ if (EVENTS.indexOf(event) === -1) {
938
+ return skip(event ? 'Ignored a ' + event + ' event: this workflow only handles ' + EVENTS.join(', ') + '.' : 'The request was not a Jira webhook event, so it was ignored.');
939
+ }
940
+ if (!ISSUE_KEY.test(issueKey)) return skip('The event did not name a Jira issue key.');
941
+
942
+ const body = clean(plainText(comment.body)).trim();
943
+ if (!body) return skip('The comment on Jira issue ' + issueKey + ' is empty.');
944
+
945
+ // Comments OneUptime posted carry this marker. Copying them back would loop.
946
+ if (body.indexOf(FROM_ONEUPTIME) !== -1) {
947
+ return skip('This comment was posted by OneUptime, so it was not copied back.');
948
+ }
949
+
950
+ const author = oneLine(displayName(comment.author)) || 'Someone';
951
+ return {
952
+ proceed: true,
953
+ issueKey: issueKey,
954
+ note: limit(defuse(FROM_JIRA + ': ' + author + ' commented on ' + issueLink(issue.self, issueKey) + '.\n\n' + body), 30000),
955
+ };
956
+ `);
957
+ };
958
+ /*
959
+ * Jira -> OneUptime: comment webhooks carry the issue's summary and status but
960
+ * not its labels, so the comment template fetches the issue and reads the
961
+ * link from the response.
962
+ */
963
+ const jiraFindLinkedRecordScript = (kind) => {
964
+ const r = kind.noun;
965
+ return jiraScript(kind, String.raw `
966
+ // Finds the ${r} a Jira issue is linked to, from its ${kind.labelPrefix}<id> label.
967
+ const comment = readJson(args.comment) || {};
968
+ const issue = readJson(args.issue) || {};
969
+ const ${r}Id = ${r}IdFromLabels(issue.fields && issue.fields.labels);
970
+ if (!${r}Id) {
971
+ return skip('Jira issue ' + asText(comment.issueKey) + ' is not linked to an ${r}: it has no ' + ${kind.upper}_LABEL_PREFIX + '<id> label.');
972
+ }
973
+ return { proceed: true, ${r}Id: ${r}Id };
974
+ `);
975
+ };
976
+ /*
977
+ * Jira -> OneUptime: lists what changed on a linked issue, for a private
978
+ * note. Status is left to the status template.
979
+ */
980
+ const jiraReadIssueChangesScript = (kind) => {
981
+ const r = kind.noun;
982
+ return jiraScript(kind, String.raw `
983
+ // Reads a Jira "issue updated" event and lists what changed, for a OneUptime note.
984
+ // Fields whose changes are not worth a note. Status is left to the status template.
985
+ const IGNORED_FIELDS = ['status', 'resolution', 'resolutiondate', 'rank', 'timespent', 'timeestimate', 'aggregatetimespent', 'aggregatetimeestimate', 'worklogid', 'lastviewed'];
986
+
987
+ const payload = readJson(args) || {};
988
+ const event = asText(payload.webhookEvent);
989
+ const issue = payload.issue || {};
990
+ const fields = issue.fields || {};
991
+ const issueKey = asText(issue.key);
992
+
993
+ if (event !== 'jira:issue_updated') {
994
+ return skip(event ? 'Ignored a ' + event + ' event: this workflow only handles jira:issue_updated.' : 'The request was not a Jira webhook event, so it was ignored.');
995
+ }
996
+ if (!ISSUE_KEY.test(issueKey)) return skip('The event did not name a Jira issue key.');
997
+
998
+ const ${r}Id = ${r}IdFromLabels(fields.labels);
999
+ if (!${r}Id) {
1000
+ return skip('Jira issue ' + issueKey + ' is not linked to an ${r}: it has no ' + ${kind.upper}_LABEL_PREFIX + '<id> label.');
1001
+ }
1002
+
1003
+ // Adding the oneuptime labels is how an issue gets linked, not a change worth a note.
1004
+ const labelsIn = (value) => asText(value).split(' ').filter(Boolean);
1005
+ const onlyLinkLabels = (item) => {
1006
+ const before = labelsIn(item.fromString);
1007
+ const after = labelsIn(item.toString);
1008
+ const changed = after.filter((label) => before.indexOf(label) === -1)
1009
+ .concat(before.filter((label) => after.indexOf(label) === -1));
1010
+ return changed.length > 0 && changed.every((label) => isLinked([label]));
1011
+ };
1012
+
1013
+ const items = payload.changelog && Array.isArray(payload.changelog.items) ? payload.changelog.items : [];
1014
+ // Custom fields such as Rank arrive with a customfield_ id, so check the display name too.
1015
+ const changes = items.filter((item) => {
1016
+ if (!item) return false;
1017
+ const names = [asText(item.fieldId), asText(item.field)].map((name) => name.toLowerCase());
1018
+ if (names.some((name) => IGNORED_FIELDS.indexOf(name) !== -1)) return false;
1019
+ return !(names.indexOf('labels') !== -1 && onlyLinkLabels(item));
1020
+ });
1021
+ if (!changes.length) return skip('Nothing that changed on Jira issue ' + issueKey + ' is worth a note.');
1022
+
1023
+ const show = (value) => {
1024
+ const text = oneLine(value);
1025
+ return text ? limit(text, 300) : '(empty)';
1026
+ };
1027
+ const lines = changes.map((item) => '- ' + (oneLine(item.field) || oneLine(item.fieldId)) + ': ' + show(item.fromString) + ' → ' + show(item.toString));
1028
+ const who = oneLine(displayName(payload.user)) || 'Someone';
1029
+
1030
+ return {
1031
+ proceed: true,
1032
+ ${r}Id: ${r}Id,
1033
+ issueKey: issueKey,
1034
+ note: limit(defuse(FROM_JIRA + ': ' + who + ' updated ' + issueLink(issue.self, issueKey) + '.\n\n' + lines.join('\n')), 30000),
1035
+ };
1036
+ `);
1037
+ };
1038
+ /** The If / Else every Jira template uses to act on a script's decision. */
1039
+ const proceedCondition = (componentId) => {
1040
+ return {
1041
+ "input-1-type": ConditionValueType.Boolean,
1042
+ "input-1": `{{local.components.${componentId}.returnValues.returnValue.proceed}}`,
1043
+ operator: ConditionOperator.EqualTo,
1044
+ "input-2-type": ConditionValueType.Boolean,
1045
+ "input-2": true,
1046
+ };
1047
+ };
1048
+ /* ----------------------- OneUptime -> Jira ----------------------- */
1049
+ const jiraCreateIssueTemplate = (kind) => {
1050
+ const r = kind.noun;
1051
+ const trigger = `${r}-on-create-1`;
1052
+ return {
1053
+ id: `jira-create-issue-for-${r}`,
1054
+ name: `Create a Jira issue when an ${r} is ${kind.created}`,
1055
+ description: `Files a Jira issue for every new ${r}, labelled so the other Jira templates can find it again.`,
1056
+ teaches: `How to call a REST API with Basic auth, and how a label on the issue becomes the link back to the ${r}.`,
1057
+ category: WorkflowTemplateCategory.Jira,
1058
+ icon: IconProp.Ticket,
1059
+ workflowName: `Create Jira issue for new ${r}`,
1060
+ workflowDescription: `Creates a Jira issue whenever an ${r} is ${kind.created}, labelled ${kind.labelPrefix}<id>. ${kind.Plural} that were ${kind.created} from Jira are skipped.`,
1061
+ variables: [
1062
+ JIRA_BASE_URL,
1063
+ JIRA_BASIC_AUTH_TOKEN,
1064
+ JIRA_PROJECT_KEY,
1065
+ JIRA_ISSUE_TYPE,
1066
+ oneUptimeUrlVariable(kind),
1067
+ ],
1068
+ graph: {
1069
+ nodes: [
1070
+ {
1071
+ componentId: trigger,
1072
+ metadataId: `${r}-on-create`,
1073
+ componentType: ComponentType.Trigger,
1074
+ position: { x: 100, y: 100 },
1075
+ args: {
1076
+ select: {
1077
+ _id: true,
1078
+ projectId: true,
1079
+ title: true,
1080
+ description: true,
1081
+ [kind.numberField]: true,
1082
+ isPrivate: true,
1083
+ customFields: true,
1084
+ rootCause: true,
1085
+ remediationNotes: true,
1086
+ [kind.severityRelation]: { name: true },
1087
+ [kind.stateRelation]: { name: true },
1088
+ },
1089
+ },
1090
+ },
1091
+ {
1092
+ componentId: "prepare-issue-1",
1093
+ metadataId: ComponentID.JavaScriptCode,
1094
+ componentType: ComponentType.Component,
1095
+ position: { x: 100, y: 300 },
1096
+ args: {
1097
+ code: jiraPrepareIssueScript(kind),
1098
+ arguments: jsonText({
1099
+ oneuptimeUrl: "{{local.variables.oneuptimeUrl}}",
1100
+ [r]: `{{local.components.${trigger}.returnValues.model}}`,
1101
+ }),
1102
+ },
1103
+ },
1104
+ {
1105
+ componentId: "log-prepare-failed",
1106
+ metadataId: ComponentID.Log,
1107
+ componentType: ComponentType.Component,
1108
+ position: { x: 600, y: 300 },
1109
+ args: {
1110
+ value: "❌ Could not prepare the Jira issue: {{local.components.prepare-issue-1.returnValues.error}}",
1111
+ },
1112
+ },
1113
+ {
1114
+ componentId: "if-create-1",
1115
+ metadataId: ComponentID.IfElse,
1116
+ componentType: ComponentType.Component,
1117
+ position: { x: 100, y: 500 },
1118
+ args: proceedCondition("prepare-issue-1"),
1119
+ },
1120
+ {
1121
+ componentId: "log-skipped",
1122
+ metadataId: ComponentID.Log,
1123
+ componentType: ComponentType.Component,
1124
+ position: { x: 350, y: 700 },
1125
+ args: {
1126
+ value: "ℹ️ {{local.components.prepare-issue-1.returnValues.returnValue.reason}}",
1127
+ },
1128
+ },
1129
+ {
1130
+ componentId: "create-issue-1",
1131
+ metadataId: ComponentID.ApiPost,
1132
+ componentType: ComponentType.Component,
1133
+ position: { x: -150, y: 700 },
1134
+ args: {
1135
+ url: "{{local.variables.jiraBaseUrl}}/rest/api/3/issue",
1136
+ "request-headers": jiraHeaders(),
1137
+ "request-body": jsonText({
1138
+ fields: {
1139
+ project: { key: "{{local.variables.jiraProjectKey}}" },
1140
+ issuetype: { name: "{{local.variables.jiraIssueType}}" },
1141
+ summary: "{{local.components.prepare-issue-1.returnValues.returnValue.summary}}",
1142
+ labels: [
1143
+ JIRA_LINK_LABEL,
1144
+ `{{local.components.prepare-issue-1.returnValues.returnValue.${r}Label}}`,
1145
+ ],
1146
+ description: adfDocument([
1147
+ adfParagraph("{{local.components.prepare-issue-1.returnValues.returnValue.description}}"),
1148
+ adfParagraph(`Open this ${r} in OneUptime`, `{{local.components.prepare-issue-1.returnValues.returnValue.${r}Url}}`),
1149
+ ]),
1150
+ },
1151
+ }),
1152
+ },
1153
+ },
1154
+ {
1155
+ componentId: "log-created",
1156
+ metadataId: ComponentID.Log,
1157
+ componentType: ComponentType.Component,
1158
+ position: { x: -150, y: 900 },
1159
+ args: {
1160
+ value: `✅ Created Jira issue {{local.components.create-issue-1.returnValues.response-body.key}} for {{local.components.${trigger}.returnValues.model.${kind.numberField}}}.`,
1161
+ },
1162
+ },
1163
+ {
1164
+ componentId: "log-create-failed",
1165
+ metadataId: ComponentID.Log,
1166
+ componentType: ComponentType.Component,
1167
+ position: { x: 100, y: 900 },
1168
+ args: {
1169
+ value: "❌ Jira did not create the issue: {{local.components.create-issue-1.returnValues.error}}\nJira said: {{local.components.create-issue-1.returnValues.response-body}}",
1170
+ },
1171
+ },
1172
+ ],
1173
+ edges: [
1174
+ {
1175
+ fromComponentId: trigger,
1176
+ toComponentId: "prepare-issue-1",
1177
+ fromPort: "success",
1178
+ },
1179
+ {
1180
+ fromComponentId: "prepare-issue-1",
1181
+ toComponentId: "if-create-1",
1182
+ fromPort: "success",
1183
+ },
1184
+ {
1185
+ fromComponentId: "prepare-issue-1",
1186
+ toComponentId: "log-prepare-failed",
1187
+ fromPort: "error",
1188
+ },
1189
+ {
1190
+ fromComponentId: "if-create-1",
1191
+ toComponentId: "create-issue-1",
1192
+ fromPort: "yes",
1193
+ },
1194
+ {
1195
+ fromComponentId: "if-create-1",
1196
+ toComponentId: "log-skipped",
1197
+ fromPort: "no",
1198
+ },
1199
+ {
1200
+ fromComponentId: "create-issue-1",
1201
+ toComponentId: "log-created",
1202
+ fromPort: "success",
1203
+ },
1204
+ {
1205
+ fromComponentId: "create-issue-1",
1206
+ toComponentId: "log-create-failed",
1207
+ fromPort: "error",
1208
+ },
1209
+ ],
1210
+ },
1211
+ };
1212
+ };
1213
+ const jiraTransitionIssueTemplate = (kind) => {
1214
+ const r = kind.noun;
1215
+ const trigger = `${r}-on-update-1`;
1216
+ return {
1217
+ id: `jira-transition-issue-on-${r}-state`,
1218
+ name: `Move the Jira issue when the ${r} is acknowledged or resolved`,
1219
+ description: `Keeps the linked Jira issue's status in step with the ${r}: acknowledged moves it to In Progress, resolved moves it to Done.`,
1220
+ teaches: "How to look a record up in another system, then choose what to do from what comes back.",
1221
+ category: WorkflowTemplateCategory.Jira,
1222
+ icon: IconProp.Refresh,
1223
+ workflowName: `Sync ${r} state to Jira`,
1224
+ workflowDescription: `Transitions the linked Jira issue when the ${r}'s state changes. Edit the script to map custom states to Jira statuses.`,
1225
+ variables: [JIRA_BASE_URL, JIRA_BASIC_AUTH_TOKEN],
1226
+ graph: {
1227
+ nodes: [
1228
+ {
1229
+ componentId: trigger,
1230
+ metadataId: `${r}-on-update`,
1231
+ componentType: ComponentType.Trigger,
1232
+ position: { x: 100, y: 100 },
1233
+ args: {
1234
+ "listen-on": { [kind.stateIdColumn]: true },
1235
+ select: {
1236
+ _id: true,
1237
+ [kind.numberField]: true,
1238
+ isPrivate: true,
1239
+ [kind.stateRelation]: {
1240
+ name: true,
1241
+ isAcknowledgedState: true,
1242
+ isResolvedState: true,
1243
+ },
1244
+ },
1245
+ },
1246
+ },
1247
+ {
1248
+ componentId: "find-issue-1",
1249
+ metadataId: ComponentID.ApiPost,
1250
+ componentType: ComponentType.Component,
1251
+ position: { x: 100, y: 300 },
1252
+ args: {
1253
+ url: "{{local.variables.jiraBaseUrl}}/rest/api/3/search/jql",
1254
+ "request-headers": jiraHeaders(),
1255
+ /*
1256
+ * Asking for the transitions here saves a call: the search
1257
+ * returns the ones available from the issue's current status.
1258
+ */
1259
+ "request-body": jiraSearchBody({
1260
+ kind: kind,
1261
+ idReference: `{{local.components.${trigger}.returnValues.model._id}}`,
1262
+ fields: ["key", "status"],
1263
+ expandTransitions: true,
1264
+ }),
1265
+ },
1266
+ },
1267
+ {
1268
+ componentId: "log-find-failed",
1269
+ metadataId: ComponentID.Log,
1270
+ componentType: ComponentType.Component,
1271
+ position: { x: 600, y: 300 },
1272
+ args: {
1273
+ value: `❌ Could not search Jira for the ${r}'s issue: {{local.components.find-issue-1.returnValues.error}}\nJira said: {{local.components.find-issue-1.returnValues.response-body}}`,
1274
+ },
1275
+ },
1276
+ {
1277
+ componentId: "plan-transition-1",
1278
+ metadataId: ComponentID.JavaScriptCode,
1279
+ componentType: ComponentType.Component,
1280
+ position: { x: 100, y: 500 },
1281
+ args: {
1282
+ code: jiraPlanTransitionScript(kind),
1283
+ arguments: jsonText({
1284
+ [r]: `{{local.components.${trigger}.returnValues.model}}`,
1285
+ search: "{{local.components.find-issue-1.returnValues.response-body}}",
1286
+ }),
1287
+ },
1288
+ },
1289
+ {
1290
+ componentId: "log-plan-failed",
1291
+ metadataId: ComponentID.Log,
1292
+ componentType: ComponentType.Component,
1293
+ position: { x: 600, y: 500 },
1294
+ args: {
1295
+ value: "❌ Could not choose a Jira transition: {{local.components.plan-transition-1.returnValues.error}}",
1296
+ },
1297
+ },
1298
+ {
1299
+ componentId: "if-transition-1",
1300
+ metadataId: ComponentID.IfElse,
1301
+ componentType: ComponentType.Component,
1302
+ position: { x: 100, y: 700 },
1303
+ args: proceedCondition("plan-transition-1"),
1304
+ },
1305
+ {
1306
+ componentId: "log-skipped",
1307
+ metadataId: ComponentID.Log,
1308
+ componentType: ComponentType.Component,
1309
+ position: { x: 350, y: 900 },
1310
+ args: {
1311
+ value: "ℹ️ {{local.components.plan-transition-1.returnValues.returnValue.reason}}",
1312
+ },
1313
+ },
1314
+ {
1315
+ componentId: "transition-issue-1",
1316
+ metadataId: ComponentID.ApiPost,
1317
+ componentType: ComponentType.Component,
1318
+ position: { x: -150, y: 900 },
1319
+ args: {
1320
+ url: "{{local.variables.jiraBaseUrl}}/rest/api/3/issue/{{local.components.plan-transition-1.returnValues.returnValue.issueKey}}/transitions",
1321
+ "request-headers": jiraHeaders(),
1322
+ "request-body": jsonText({
1323
+ transition: {
1324
+ id: "{{local.components.plan-transition-1.returnValues.returnValue.transitionId}}",
1325
+ },
1326
+ }),
1327
+ },
1328
+ },
1329
+ {
1330
+ componentId: "log-transitioned",
1331
+ metadataId: ComponentID.Log,
1332
+ componentType: ComponentType.Component,
1333
+ position: { x: -150, y: 1100 },
1334
+ args: {
1335
+ value: "✅ Moved Jira issue {{local.components.plan-transition-1.returnValues.returnValue.issueKey}} to {{local.components.plan-transition-1.returnValues.returnValue.jiraStatus}}. {{local.components.plan-transition-1.returnValues.returnValue.reason}}",
1336
+ },
1337
+ },
1338
+ {
1339
+ componentId: "log-transition-failed",
1340
+ metadataId: ComponentID.Log,
1341
+ componentType: ComponentType.Component,
1342
+ position: { x: 100, y: 1100 },
1343
+ args: {
1344
+ value: "❌ Jira did not move the issue: {{local.components.transition-issue-1.returnValues.error}}\nJira said: {{local.components.transition-issue-1.returnValues.response-body}}",
1345
+ },
1346
+ },
1347
+ ],
1348
+ edges: [
1349
+ {
1350
+ fromComponentId: trigger,
1351
+ toComponentId: "find-issue-1",
1352
+ fromPort: "success",
1353
+ },
1354
+ {
1355
+ fromComponentId: "find-issue-1",
1356
+ toComponentId: "plan-transition-1",
1357
+ fromPort: "success",
1358
+ },
1359
+ {
1360
+ fromComponentId: "find-issue-1",
1361
+ toComponentId: "log-find-failed",
1362
+ fromPort: "error",
1363
+ },
1364
+ {
1365
+ fromComponentId: "plan-transition-1",
1366
+ toComponentId: "if-transition-1",
1367
+ fromPort: "success",
1368
+ },
1369
+ {
1370
+ fromComponentId: "plan-transition-1",
1371
+ toComponentId: "log-plan-failed",
1372
+ fromPort: "error",
1373
+ },
1374
+ {
1375
+ fromComponentId: "if-transition-1",
1376
+ toComponentId: "transition-issue-1",
1377
+ fromPort: "yes",
1378
+ },
1379
+ {
1380
+ fromComponentId: "if-transition-1",
1381
+ toComponentId: "log-skipped",
1382
+ fromPort: "no",
1383
+ },
1384
+ {
1385
+ fromComponentId: "transition-issue-1",
1386
+ toComponentId: "log-transitioned",
1387
+ fromPort: "success",
1388
+ },
1389
+ {
1390
+ fromComponentId: "transition-issue-1",
1391
+ toComponentId: "log-transition-failed",
1392
+ fromPort: "error",
1393
+ },
1394
+ ],
1395
+ },
1396
+ };
1397
+ };
1398
+ /*
1399
+ * Private and public notes go to Jira the same way; only the trigger, the
1400
+ * wording and the comment's visibility differ.
1401
+ */
1402
+ const jiraNoteToCommentTemplate = (props) => {
1403
+ const kind = props.kind;
1404
+ const r = kind.noun;
1405
+ const noteKind = `${props.visibility} note`;
1406
+ const commentBody = {
1407
+ body: adfDocument([
1408
+ adfParagraph("{{local.components.build-comment-1.returnValues.returnValue.comment}}"),
1409
+ ]),
1410
+ };
1411
+ if (props.commentProperties) {
1412
+ commentBody["properties"] = props.commentProperties;
1413
+ }
1414
+ return {
1415
+ id: `jira-comment-from-${r}-${props.visibility}-note`,
1416
+ name: `Copy ${r} ${props.visibility} notes to the Jira issue`,
1417
+ description: props.description,
1418
+ teaches: "How to find a record in another system by a label, and how a marker in the text stops two systems echoing each other.",
1419
+ category: WorkflowTemplateCategory.Jira,
1420
+ icon: props.icon,
1421
+ workflowName: `Copy ${r} ${props.visibility} notes to Jira`,
1422
+ workflowDescription: props.workflowDescription,
1423
+ variables: [JIRA_BASE_URL, JIRA_BASIC_AUTH_TOKEN],
1424
+ graph: {
1425
+ nodes: [
1426
+ {
1427
+ componentId: "note-on-create-1",
1428
+ metadataId: props.triggerMetadataId,
1429
+ componentType: ComponentType.Trigger,
1430
+ position: { x: 100, y: 100 },
1431
+ args: {
1432
+ select: {
1433
+ _id: true,
1434
+ note: true,
1435
+ [kind.idColumn]: true,
1436
+ [r]: { [kind.numberField]: true, isPrivate: true },
1437
+ createdByUser: { name: true },
1438
+ },
1439
+ },
1440
+ },
1441
+ {
1442
+ componentId: "find-issue-1",
1443
+ metadataId: ComponentID.ApiPost,
1444
+ componentType: ComponentType.Component,
1445
+ position: { x: 100, y: 300 },
1446
+ args: {
1447
+ url: "{{local.variables.jiraBaseUrl}}/rest/api/3/search/jql",
1448
+ "request-headers": jiraHeaders(),
1449
+ "request-body": jiraSearchBody({
1450
+ kind: kind,
1451
+ idReference: `{{local.components.note-on-create-1.returnValues.model.${kind.idColumn}.value}}`,
1452
+ fields: ["key", "summary"],
1453
+ }),
1454
+ },
1455
+ },
1456
+ {
1457
+ componentId: "log-find-failed",
1458
+ metadataId: ComponentID.Log,
1459
+ componentType: ComponentType.Component,
1460
+ position: { x: 600, y: 300 },
1461
+ args: {
1462
+ value: `❌ Could not search Jira for the ${r}'s issue: {{local.components.find-issue-1.returnValues.error}}\nJira said: {{local.components.find-issue-1.returnValues.response-body}}`,
1463
+ },
1464
+ },
1465
+ {
1466
+ componentId: "build-comment-1",
1467
+ metadataId: ComponentID.JavaScriptCode,
1468
+ componentType: ComponentType.Component,
1469
+ position: { x: 100, y: 500 },
1470
+ args: {
1471
+ code: jiraNoteCommentScript(kind, noteKind),
1472
+ arguments: jsonText({
1473
+ note: "{{local.components.note-on-create-1.returnValues.model}}",
1474
+ search: "{{local.components.find-issue-1.returnValues.response-body}}",
1475
+ }),
1476
+ },
1477
+ },
1478
+ {
1479
+ componentId: "log-build-failed",
1480
+ metadataId: ComponentID.Log,
1481
+ componentType: ComponentType.Component,
1482
+ position: { x: 600, y: 500 },
1483
+ args: {
1484
+ value: "❌ Could not write the Jira comment: {{local.components.build-comment-1.returnValues.error}}",
1485
+ },
1486
+ },
1487
+ {
1488
+ componentId: "if-post-1",
1489
+ metadataId: ComponentID.IfElse,
1490
+ componentType: ComponentType.Component,
1491
+ position: { x: 100, y: 700 },
1492
+ args: proceedCondition("build-comment-1"),
1493
+ },
1494
+ {
1495
+ componentId: "log-skipped",
1496
+ metadataId: ComponentID.Log,
1497
+ componentType: ComponentType.Component,
1498
+ position: { x: 350, y: 900 },
1499
+ args: {
1500
+ value: "ℹ️ {{local.components.build-comment-1.returnValues.returnValue.reason}}",
1501
+ },
1502
+ },
1503
+ {
1504
+ componentId: "post-comment-1",
1505
+ metadataId: ComponentID.ApiPost,
1506
+ componentType: ComponentType.Component,
1507
+ position: { x: -150, y: 900 },
1508
+ args: {
1509
+ url: "{{local.variables.jiraBaseUrl}}/rest/api/3/issue/{{local.components.build-comment-1.returnValues.returnValue.issueKey}}/comment",
1510
+ "request-headers": jiraHeaders(),
1511
+ "request-body": jsonText(commentBody),
1512
+ },
1513
+ },
1514
+ {
1515
+ componentId: "log-posted",
1516
+ metadataId: ComponentID.Log,
1517
+ componentType: ComponentType.Component,
1518
+ position: { x: -150, y: 1100 },
1519
+ args: {
1520
+ value: "✅ Posted the note to Jira issue {{local.components.build-comment-1.returnValues.returnValue.issueKey}}.",
1521
+ },
1522
+ },
1523
+ {
1524
+ componentId: "log-post-failed",
1525
+ metadataId: ComponentID.Log,
1526
+ componentType: ComponentType.Component,
1527
+ position: { x: 100, y: 1100 },
1528
+ args: {
1529
+ value: "❌ Jira did not accept the comment: {{local.components.post-comment-1.returnValues.error}}\nJira said: {{local.components.post-comment-1.returnValues.response-body}}",
1530
+ },
1531
+ },
1532
+ ],
1533
+ edges: [
1534
+ {
1535
+ fromComponentId: "note-on-create-1",
1536
+ toComponentId: "find-issue-1",
1537
+ fromPort: "success",
1538
+ },
1539
+ {
1540
+ fromComponentId: "find-issue-1",
1541
+ toComponentId: "build-comment-1",
1542
+ fromPort: "success",
1543
+ },
1544
+ {
1545
+ fromComponentId: "find-issue-1",
1546
+ toComponentId: "log-find-failed",
1547
+ fromPort: "error",
1548
+ },
1549
+ {
1550
+ fromComponentId: "build-comment-1",
1551
+ toComponentId: "if-post-1",
1552
+ fromPort: "success",
1553
+ },
1554
+ {
1555
+ fromComponentId: "build-comment-1",
1556
+ toComponentId: "log-build-failed",
1557
+ fromPort: "error",
1558
+ },
1559
+ {
1560
+ fromComponentId: "if-post-1",
1561
+ toComponentId: "post-comment-1",
1562
+ fromPort: "yes",
1563
+ },
1564
+ {
1565
+ fromComponentId: "if-post-1",
1566
+ toComponentId: "log-skipped",
1567
+ fromPort: "no",
1568
+ },
1569
+ {
1570
+ fromComponentId: "post-comment-1",
1571
+ toComponentId: "log-posted",
1572
+ fromPort: "success",
1573
+ },
1574
+ {
1575
+ fromComponentId: "post-comment-1",
1576
+ toComponentId: "log-post-failed",
1577
+ fromPort: "error",
1578
+ },
1579
+ ],
1580
+ },
1581
+ };
1582
+ };
1583
+ const jiraPrivateNoteToCommentTemplate = (kind) => {
1584
+ return jiraNoteToCommentTemplate({
1585
+ kind: kind,
1586
+ visibility: "private",
1587
+ description: `Posts every new private note on an ${kind.noun} as a comment on its Jira issue — an internal one in Jira Service Management.`,
1588
+ icon: IconProp.ChatBubbleLeftRight,
1589
+ workflowDescription: `Posts each new private note as a comment on the ${kind.noun}'s linked Jira issue. Notes that came from Jira are not sent back.`,
1590
+ triggerMetadataId: `${kind.noun}-internal-note-on-create`,
1591
+ // A private note stays private in Jira Service Management too.
1592
+ commentProperties: [JIRA_INTERNAL_COMMENT_PROPERTY],
1593
+ });
1594
+ };
1595
+ const jiraPublicNoteToCommentTemplate = (kind) => {
1596
+ return jiraNoteToCommentTemplate({
1597
+ kind: kind,
1598
+ visibility: "public",
1599
+ description: `Posts every new public note on an ${kind.noun} as a comment on its Jira issue, so the ticket carries the same updates as the status page.`,
1600
+ icon: IconProp.ChatBubbleLeft,
1601
+ workflowDescription: `Posts each new public note as a comment on the ${kind.noun}'s linked Jira issue.`,
1602
+ triggerMetadataId: `${kind.noun}-public-note-on-create`,
1603
+ });
1604
+ };
1605
+ const jiraUpdateCommentTemplate = (kind) => {
1606
+ const r = kind.noun;
1607
+ const trigger = `${r}-on-update-1`;
1608
+ return {
1609
+ id: `jira-comment-on-${r}-update`,
1610
+ name: `Comment on the Jira issue when the ${r} is edited`,
1611
+ description: `Posts a comment on the linked Jira issue when the ${r}'s ${kind.editedFieldsText} are edited.`,
1612
+ teaches: "How Listen On picks the edits that matter, and how to turn a record into a readable summary.",
1613
+ category: WorkflowTemplateCategory.Jira,
1614
+ icon: IconProp.PencilSquare,
1615
+ workflowName: `Comment on Jira when ${r} changes`,
1616
+ workflowDescription: `When the ${r}'s ${kind.editedFieldsText} are edited, posts how the ${r} now stands to its linked Jira issue. Saving the ${r}'s details form counts, even when it only changed labels or the Private setting. State changes are left to the transition template.`,
1617
+ variables: [JIRA_BASE_URL, JIRA_BASIC_AUTH_TOKEN],
1618
+ graph: {
1619
+ nodes: [
1620
+ {
1621
+ componentId: trigger,
1622
+ metadataId: `${r}-on-update`,
1623
+ componentType: ComponentType.Trigger,
1624
+ position: { x: 100, y: 100 },
1625
+ args: {
1626
+ /*
1627
+ * State changes are left out on purpose: the transition
1628
+ * template handles those, and a comment for each would
1629
+ * double up.
1630
+ */
1631
+ "listen-on": kind.editListenOn,
1632
+ select: {
1633
+ _id: true,
1634
+ title: true,
1635
+ description: true,
1636
+ [kind.numberField]: true,
1637
+ isPrivate: true,
1638
+ rootCause: true,
1639
+ remediationNotes: true,
1640
+ [kind.severityRelation]: { name: true },
1641
+ [kind.stateRelation]: { name: true },
1642
+ },
1643
+ },
1644
+ },
1645
+ {
1646
+ componentId: "find-issue-1",
1647
+ metadataId: ComponentID.ApiPost,
1648
+ componentType: ComponentType.Component,
1649
+ position: { x: 100, y: 300 },
1650
+ args: {
1651
+ url: "{{local.variables.jiraBaseUrl}}/rest/api/3/search/jql",
1652
+ "request-headers": jiraHeaders(),
1653
+ "request-body": jiraSearchBody({
1654
+ kind: kind,
1655
+ idReference: `{{local.components.${trigger}.returnValues.model._id}}`,
1656
+ fields: ["key", "summary"],
1657
+ }),
1658
+ },
1659
+ },
1660
+ {
1661
+ componentId: "log-find-failed",
1662
+ metadataId: ComponentID.Log,
1663
+ componentType: ComponentType.Component,
1664
+ position: { x: 600, y: 300 },
1665
+ args: {
1666
+ value: `❌ Could not search Jira for the ${r}'s issue: {{local.components.find-issue-1.returnValues.error}}\nJira said: {{local.components.find-issue-1.returnValues.response-body}}`,
1667
+ },
1668
+ },
1669
+ {
1670
+ componentId: "build-comment-1",
1671
+ metadataId: ComponentID.JavaScriptCode,
1672
+ componentType: ComponentType.Component,
1673
+ position: { x: 100, y: 500 },
1674
+ args: {
1675
+ code: jiraUpdateCommentScript(kind),
1676
+ arguments: jsonText({
1677
+ [r]: `{{local.components.${trigger}.returnValues.model}}`,
1678
+ search: "{{local.components.find-issue-1.returnValues.response-body}}",
1679
+ }),
1680
+ },
1681
+ },
1682
+ {
1683
+ componentId: "log-build-failed",
1684
+ metadataId: ComponentID.Log,
1685
+ componentType: ComponentType.Component,
1686
+ position: { x: 600, y: 500 },
1687
+ args: {
1688
+ value: "❌ Could not write the Jira comment: {{local.components.build-comment-1.returnValues.error}}",
1689
+ },
1690
+ },
1691
+ {
1692
+ componentId: "if-post-1",
1693
+ metadataId: ComponentID.IfElse,
1694
+ componentType: ComponentType.Component,
1695
+ position: { x: 100, y: 700 },
1696
+ args: proceedCondition("build-comment-1"),
1697
+ },
1698
+ {
1699
+ componentId: "log-skipped",
1700
+ metadataId: ComponentID.Log,
1701
+ componentType: ComponentType.Component,
1702
+ position: { x: 350, y: 900 },
1703
+ args: {
1704
+ value: "ℹ️ {{local.components.build-comment-1.returnValues.returnValue.reason}}",
1705
+ },
1706
+ },
1707
+ {
1708
+ componentId: "post-comment-1",
1709
+ metadataId: ComponentID.ApiPost,
1710
+ componentType: ComponentType.Component,
1711
+ position: { x: -150, y: 900 },
1712
+ args: {
1713
+ url: "{{local.variables.jiraBaseUrl}}/rest/api/3/issue/{{local.components.build-comment-1.returnValues.returnValue.issueKey}}/comment",
1714
+ "request-headers": jiraHeaders(),
1715
+ "request-body": jsonText({
1716
+ body: adfDocument([
1717
+ adfParagraph("{{local.components.build-comment-1.returnValues.returnValue.comment}}"),
1718
+ ]),
1719
+ // Root causes and remediation are for the team, not the customer.
1720
+ properties: [JIRA_INTERNAL_COMMENT_PROPERTY],
1721
+ }),
1722
+ },
1723
+ },
1724
+ {
1725
+ componentId: "log-posted",
1726
+ metadataId: ComponentID.Log,
1727
+ componentType: ComponentType.Component,
1728
+ position: { x: -150, y: 1100 },
1729
+ args: {
1730
+ value: `✅ Posted the ${r}'s changes to Jira issue {{local.components.build-comment-1.returnValues.returnValue.issueKey}}.`,
1731
+ },
1732
+ },
1733
+ {
1734
+ componentId: "log-post-failed",
1735
+ metadataId: ComponentID.Log,
1736
+ componentType: ComponentType.Component,
1737
+ position: { x: 100, y: 1100 },
1738
+ args: {
1739
+ value: "❌ Jira did not accept the comment: {{local.components.post-comment-1.returnValues.error}}\nJira said: {{local.components.post-comment-1.returnValues.response-body}}",
1740
+ },
1741
+ },
1742
+ ],
1743
+ edges: [
1744
+ {
1745
+ fromComponentId: trigger,
1746
+ toComponentId: "find-issue-1",
1747
+ fromPort: "success",
1748
+ },
1749
+ {
1750
+ fromComponentId: "find-issue-1",
1751
+ toComponentId: "build-comment-1",
1752
+ fromPort: "success",
1753
+ },
1754
+ {
1755
+ fromComponentId: "find-issue-1",
1756
+ toComponentId: "log-find-failed",
1757
+ fromPort: "error",
1758
+ },
1759
+ {
1760
+ fromComponentId: "build-comment-1",
1761
+ toComponentId: "if-post-1",
1762
+ fromPort: "success",
1763
+ },
1764
+ {
1765
+ fromComponentId: "build-comment-1",
1766
+ toComponentId: "log-build-failed",
1767
+ fromPort: "error",
1768
+ },
1769
+ {
1770
+ fromComponentId: "if-post-1",
1771
+ toComponentId: "post-comment-1",
1772
+ fromPort: "yes",
1773
+ },
1774
+ {
1775
+ fromComponentId: "if-post-1",
1776
+ toComponentId: "log-skipped",
1777
+ fromPort: "no",
1778
+ },
1779
+ {
1780
+ fromComponentId: "post-comment-1",
1781
+ toComponentId: "log-posted",
1782
+ fromPort: "success",
1783
+ },
1784
+ {
1785
+ fromComponentId: "post-comment-1",
1786
+ toComponentId: "log-post-failed",
1787
+ fromPort: "error",
1788
+ },
1789
+ ],
1790
+ },
1791
+ };
1792
+ };
1793
+ /* ----------------------- Jira -> OneUptime ----------------------- */
1794
+ const jiraCreateRecordTemplate = (kind) => {
1795
+ const r = kind.noun;
1796
+ const prepare = `prepare-${r}-1`;
1797
+ const create = `create-${r}-1`;
1798
+ const createJson = Object.assign(Object.assign({ [kind.severityIdColumn]: `{{local.components.${prepare}.returnValues.returnValue.${kind.severityIdColumn}}}`, customFields: {
1799
+ jiraIssueKey: `{{local.components.${prepare}.returnValues.returnValue.issueKey}}`,
1800
+ } }, kind.quietCreateFields), { title: `{{local.components.${prepare}.returnValues.returnValue.title}}`, description: `{{local.components.${prepare}.returnValues.returnValue.description}}` });
1801
+ return {
1802
+ id: `jira-${kind.create}-${r}-from-issue`,
1803
+ name: `${kind.Create} an ${r} when a Jira issue is created`,
1804
+ description: `Point a Jira webhook at this workflow and each new issue becomes an ${r}, with its severity chosen from the issue's priority.`,
1805
+ teaches: "How to receive another system's webhook, map its fields, and write back to it once you have an id.",
1806
+ category: WorkflowTemplateCategory.Jira,
1807
+ icon: IconProp.Bug,
1808
+ workflowName: `${kind.Create} ${r} from Jira issue`,
1809
+ workflowDescription: `${kind.Create}s an ${r}${kind.quietCreateText} for each Jira issue created. Enable it, copy the URL from the Webhook trigger, and register it in Jira under Settings > System > WebHooks for the Issue created event. If you also create ${kind.otherPlural} from Jira, give the two webhooks JQL filters that never match the same issue, or each issue becomes both.`,
1810
+ variables: [JIRA_BASE_URL, JIRA_BASIC_AUTH_TOKEN],
1811
+ graph: {
1812
+ nodes: [
1813
+ {
1814
+ componentId: "webhook-1",
1815
+ metadataId: ComponentID.Webhook,
1816
+ componentType: ComponentType.Trigger,
1817
+ position: { x: 100, y: 100 },
1818
+ },
1819
+ {
1820
+ componentId: "find-severities-1",
1821
+ metadataId: `${r}-severity-find-many`,
1822
+ componentType: ComponentType.Component,
1823
+ position: { x: 100, y: 300 },
1824
+ args: {
1825
+ // Every row. Query cannot be left empty, so it asks for any id.
1826
+ query: { _id: { _type: "NotNull", value: null } },
1827
+ select: { _id: true, name: true, order: true },
1828
+ limit: 50,
1829
+ },
1830
+ },
1831
+ {
1832
+ componentId: "log-severities-failed",
1833
+ metadataId: ComponentID.Log,
1834
+ componentType: ComponentType.Component,
1835
+ position: { x: 600, y: 300 },
1836
+ args: {
1837
+ value: `❌ Could not read this project's ${r} severities. The database error is in the run log above.`,
1838
+ },
1839
+ },
1840
+ {
1841
+ componentId: prepare,
1842
+ metadataId: ComponentID.JavaScriptCode,
1843
+ componentType: ComponentType.Component,
1844
+ position: { x: 100, y: 500 },
1845
+ args: {
1846
+ code: jiraPrepareRecordScript(kind),
1847
+ /*
1848
+ * The Jira payload goes last. Text Jira users wrote is only
1849
+ * ever substituted after everything else in an argument.
1850
+ */
1851
+ arguments: jsonText({
1852
+ severities: "{{local.components.find-severities-1.returnValues.models}}",
1853
+ payload: "{{local.components.webhook-1.returnValues.request-body}}",
1854
+ }),
1855
+ },
1856
+ },
1857
+ {
1858
+ componentId: "log-prepare-failed",
1859
+ metadataId: ComponentID.Log,
1860
+ componentType: ComponentType.Component,
1861
+ position: { x: 600, y: 500 },
1862
+ args: {
1863
+ value: `❌ Could not read the Jira event: {{local.components.${prepare}.returnValues.error}}`,
1864
+ },
1865
+ },
1866
+ {
1867
+ componentId: `if-${kind.create}-1`,
1868
+ metadataId: ComponentID.IfElse,
1869
+ componentType: ComponentType.Component,
1870
+ position: { x: 100, y: 700 },
1871
+ args: proceedCondition(prepare),
1872
+ },
1873
+ {
1874
+ componentId: "log-skipped",
1875
+ metadataId: ComponentID.Log,
1876
+ componentType: ComponentType.Component,
1877
+ position: { x: 350, y: 900 },
1878
+ args: {
1879
+ value: `ℹ️ {{local.components.${prepare}.returnValues.returnValue.reason}}`,
1880
+ },
1881
+ },
1882
+ {
1883
+ /*
1884
+ * The webhook's word is not taken for whether the issue is already
1885
+ * linked. Anyone holding this workflow's URL can describe any issue,
1886
+ * and a delivery Jira retries arrives after the first one labelled
1887
+ * the issue — so ask Jira what the labels are now.
1888
+ */
1889
+ componentId: "get-issue-1",
1890
+ metadataId: ComponentID.ApiGet,
1891
+ componentType: ComponentType.Component,
1892
+ position: { x: -150, y: 900 },
1893
+ args: {
1894
+ url: `{{local.variables.jiraBaseUrl}}/rest/api/3/issue/{{local.components.${prepare}.returnValues.returnValue.issueKey}}?fields=labels`,
1895
+ "request-headers": jiraHeaders(),
1896
+ },
1897
+ },
1898
+ {
1899
+ componentId: "log-get-issue-failed",
1900
+ metadataId: ComponentID.Log,
1901
+ componentType: ComponentType.Component,
1902
+ position: { x: 100, y: 1100 },
1903
+ args: {
1904
+ value: `❌ Could not read Jira issue {{local.components.${prepare}.returnValues.returnValue.issueKey}}, so no ${r} was ${kind.created}: {{local.components.get-issue-1.returnValues.error}}\nJira said: {{local.components.get-issue-1.returnValues.response-body}}`,
1905
+ },
1906
+ },
1907
+ {
1908
+ componentId: "confirm-unlinked-1",
1909
+ metadataId: ComponentID.JavaScriptCode,
1910
+ componentType: ComponentType.Component,
1911
+ position: { x: -150, y: 1100 },
1912
+ args: {
1913
+ code: jiraConfirmUnlinkedScript(kind),
1914
+ arguments: jsonText({
1915
+ issue: "{{local.components.get-issue-1.returnValues.response-body}}",
1916
+ }),
1917
+ },
1918
+ },
1919
+ {
1920
+ componentId: "log-confirm-failed",
1921
+ metadataId: ComponentID.Log,
1922
+ componentType: ComponentType.Component,
1923
+ position: { x: 100, y: 1300 },
1924
+ args: {
1925
+ value: "❌ Could not read the issue's labels: {{local.components.confirm-unlinked-1.returnValues.error}}",
1926
+ },
1927
+ },
1928
+ {
1929
+ componentId: "if-unlinked-1",
1930
+ metadataId: ComponentID.IfElse,
1931
+ componentType: ComponentType.Component,
1932
+ position: { x: -150, y: 1300 },
1933
+ args: proceedCondition("confirm-unlinked-1"),
1934
+ },
1935
+ {
1936
+ componentId: "log-already-linked",
1937
+ metadataId: ComponentID.Log,
1938
+ componentType: ComponentType.Component,
1939
+ position: { x: 100, y: 1500 },
1940
+ args: {
1941
+ value: "ℹ️ {{local.components.confirm-unlinked-1.returnValues.returnValue.reason}}",
1942
+ },
1943
+ },
1944
+ {
1945
+ componentId: create,
1946
+ metadataId: `${r}-create-one`,
1947
+ componentType: ComponentType.Component,
1948
+ position: { x: -400, y: 1500 },
1949
+ args: {
1950
+ /*
1951
+ * customFields.jiraIssueKey is what stops the create-issue
1952
+ * template filing this record back into Jira as a second issue.
1953
+ */
1954
+ json: jsonText(createJson),
1955
+ },
1956
+ },
1957
+ {
1958
+ componentId: "log-create-failed",
1959
+ metadataId: ComponentID.Log,
1960
+ componentType: ComponentType.Component,
1961
+ position: { x: -150, y: 1700 },
1962
+ args: {
1963
+ value: `❌ Could not ${kind.create} the ${r} for Jira issue {{local.components.${prepare}.returnValues.returnValue.issueKey}}. The database error is in the run log above.`,
1964
+ },
1965
+ },
1966
+ {
1967
+ componentId: "link-issue-1",
1968
+ metadataId: ComponentID.ApiPut,
1969
+ componentType: ComponentType.Component,
1970
+ position: { x: -400, y: 1700 },
1971
+ args: {
1972
+ url: `{{local.variables.jiraBaseUrl}}/rest/api/3/issue/{{local.components.${prepare}.returnValues.returnValue.issueKey}}`,
1973
+ "request-headers": jiraHeaders(),
1974
+ "request-body": jsonText({
1975
+ update: {
1976
+ labels: [
1977
+ { add: JIRA_LINK_LABEL },
1978
+ {
1979
+ add: `${kind.labelPrefix}{{local.components.${create}.returnValues.model._id}}`,
1980
+ },
1981
+ ],
1982
+ },
1983
+ }),
1984
+ },
1985
+ },
1986
+ {
1987
+ componentId: "log-linked",
1988
+ metadataId: ComponentID.Log,
1989
+ componentType: ComponentType.Component,
1990
+ position: { x: -400, y: 1900 },
1991
+ args: {
1992
+ value: `✅ ${kind.Created} an ${r} with severity {{local.components.${prepare}.returnValues.returnValue.severityName}} for Jira issue {{local.components.${prepare}.returnValues.returnValue.issueKey}}, and labelled the issue to link them.`,
1993
+ },
1994
+ },
1995
+ {
1996
+ componentId: "log-link-failed",
1997
+ metadataId: ComponentID.Log,
1998
+ componentType: ComponentType.Component,
1999
+ position: { x: -150, y: 1900 },
2000
+ args: {
2001
+ value: `⚠️ The ${r} was ${kind.created}, but Jira did not accept the link labels, so the other Jira templates cannot find it: {{local.components.link-issue-1.returnValues.error}}\nJira said: {{local.components.link-issue-1.returnValues.response-body}}`,
2002
+ },
2003
+ },
2004
+ ],
2005
+ edges: [
2006
+ {
2007
+ fromComponentId: "webhook-1",
2008
+ toComponentId: "find-severities-1",
2009
+ fromPort: "out",
2010
+ },
2011
+ {
2012
+ fromComponentId: "find-severities-1",
2013
+ toComponentId: prepare,
2014
+ fromPort: "success",
2015
+ },
2016
+ {
2017
+ fromComponentId: "find-severities-1",
2018
+ toComponentId: "log-severities-failed",
2019
+ fromPort: "error",
2020
+ },
2021
+ {
2022
+ fromComponentId: prepare,
2023
+ toComponentId: `if-${kind.create}-1`,
2024
+ fromPort: "success",
2025
+ },
2026
+ {
2027
+ fromComponentId: prepare,
2028
+ toComponentId: "log-prepare-failed",
2029
+ fromPort: "error",
2030
+ },
2031
+ {
2032
+ fromComponentId: `if-${kind.create}-1`,
2033
+ toComponentId: "get-issue-1",
2034
+ fromPort: "yes",
2035
+ },
2036
+ {
2037
+ fromComponentId: "get-issue-1",
2038
+ toComponentId: "confirm-unlinked-1",
2039
+ fromPort: "success",
2040
+ },
2041
+ {
2042
+ fromComponentId: "get-issue-1",
2043
+ toComponentId: "log-get-issue-failed",
2044
+ fromPort: "error",
2045
+ },
2046
+ {
2047
+ fromComponentId: "confirm-unlinked-1",
2048
+ toComponentId: "if-unlinked-1",
2049
+ fromPort: "success",
2050
+ },
2051
+ {
2052
+ fromComponentId: "confirm-unlinked-1",
2053
+ toComponentId: "log-confirm-failed",
2054
+ fromPort: "error",
2055
+ },
2056
+ {
2057
+ fromComponentId: "if-unlinked-1",
2058
+ toComponentId: create,
2059
+ fromPort: "yes",
2060
+ },
2061
+ {
2062
+ fromComponentId: "if-unlinked-1",
2063
+ toComponentId: "log-already-linked",
2064
+ fromPort: "no",
2065
+ },
2066
+ {
2067
+ fromComponentId: `if-${kind.create}-1`,
2068
+ toComponentId: "log-skipped",
2069
+ fromPort: "no",
2070
+ },
2071
+ {
2072
+ fromComponentId: create,
2073
+ toComponentId: "link-issue-1",
2074
+ fromPort: "success",
2075
+ },
2076
+ {
2077
+ fromComponentId: create,
2078
+ toComponentId: "log-create-failed",
2079
+ fromPort: "error",
2080
+ },
2081
+ {
2082
+ fromComponentId: "link-issue-1",
2083
+ toComponentId: "log-linked",
2084
+ fromPort: "success",
2085
+ },
2086
+ {
2087
+ fromComponentId: "link-issue-1",
2088
+ toComponentId: "log-link-failed",
2089
+ fromPort: "error",
2090
+ },
2091
+ ],
2092
+ },
2093
+ };
2094
+ };
2095
+ const jiraStatusToStateTemplate = (kind) => {
2096
+ const r = kind.noun;
2097
+ const find = `find-${r}-1`;
2098
+ return {
2099
+ id: `jira-status-to-${r}-state`,
2100
+ name: `Acknowledge or resolve the ${r} when its Jira issue moves`,
2101
+ description: `When the linked Jira issue moves to In Progress the ${r} is acknowledged, and when it moves to Done the ${r} is resolved.`,
2102
+ teaches: `How to read a Jira changelog, and why an ${r}'s state only ever moves forward.`,
2103
+ category: WorkflowTemplateCategory.Jira,
2104
+ icon: IconProp.ClipboardDocumentCheck,
2105
+ workflowName: `Sync Jira status to ${r}`,
2106
+ workflowDescription: `Changes the ${r}'s state when its linked Jira issue changes status. Enable it, copy the URL from the Webhook trigger, and register it in Jira under Settings > System > WebHooks for the Issue updated event.`,
2107
+ variables: [],
2108
+ graph: {
2109
+ nodes: [
2110
+ {
2111
+ componentId: "webhook-1",
2112
+ metadataId: ComponentID.Webhook,
2113
+ componentType: ComponentType.Trigger,
2114
+ position: { x: 100, y: 100 },
2115
+ },
2116
+ {
2117
+ componentId: "read-event-1",
2118
+ metadataId: ComponentID.JavaScriptCode,
2119
+ componentType: ComponentType.Component,
2120
+ position: { x: 100, y: 300 },
2121
+ args: {
2122
+ code: jiraReadStatusChangeScript(kind),
2123
+ arguments: "{{local.components.webhook-1.returnValues.request-body}}",
2124
+ },
2125
+ },
2126
+ {
2127
+ componentId: "log-read-failed",
2128
+ metadataId: ComponentID.Log,
2129
+ componentType: ComponentType.Component,
2130
+ position: { x: 600, y: 300 },
2131
+ args: {
2132
+ value: "❌ Could not read the Jira event: {{local.components.read-event-1.returnValues.error}}",
2133
+ },
2134
+ },
2135
+ {
2136
+ componentId: "if-status-changed-1",
2137
+ metadataId: ComponentID.IfElse,
2138
+ componentType: ComponentType.Component,
2139
+ position: { x: 100, y: 500 },
2140
+ args: proceedCondition("read-event-1"),
2141
+ },
2142
+ {
2143
+ componentId: "log-ignored",
2144
+ metadataId: ComponentID.Log,
2145
+ componentType: ComponentType.Component,
2146
+ position: { x: 350, y: 700 },
2147
+ args: {
2148
+ value: "ℹ️ {{local.components.read-event-1.returnValues.returnValue.reason}}",
2149
+ },
2150
+ },
2151
+ {
2152
+ componentId: find,
2153
+ metadataId: `${r}-find-one`,
2154
+ componentType: ComponentType.Component,
2155
+ position: { x: -150, y: 700 },
2156
+ args: {
2157
+ query: {
2158
+ _id: `{{local.components.read-event-1.returnValues.returnValue.${r}Id}}`,
2159
+ },
2160
+ select: {
2161
+ _id: true,
2162
+ [kind.numberField]: true,
2163
+ [kind.stateRelation]: { _id: true, name: true, order: true },
2164
+ },
2165
+ },
2166
+ },
2167
+ {
2168
+ componentId: `log-find-${r}-failed`,
2169
+ metadataId: ComponentID.Log,
2170
+ componentType: ComponentType.Component,
2171
+ position: { x: 100, y: 900 },
2172
+ args: {
2173
+ value: `❌ Could not look up the ${r}. The database error is in the run log above.`,
2174
+ },
2175
+ },
2176
+ {
2177
+ componentId: "find-states-1",
2178
+ metadataId: `${r}-state-find-many`,
2179
+ componentType: ComponentType.Component,
2180
+ position: { x: -150, y: 900 },
2181
+ args: {
2182
+ // Every row. Query cannot be left empty, so it asks for any id.
2183
+ query: { _id: { _type: "NotNull", value: null } },
2184
+ select: {
2185
+ _id: true,
2186
+ name: true,
2187
+ order: true,
2188
+ isAcknowledgedState: true,
2189
+ isResolvedState: true,
2190
+ },
2191
+ limit: 50,
2192
+ },
2193
+ },
2194
+ {
2195
+ componentId: "log-find-states-failed",
2196
+ metadataId: ComponentID.Log,
2197
+ componentType: ComponentType.Component,
2198
+ position: { x: 100, y: 1100 },
2199
+ args: {
2200
+ value: `❌ Could not read this project's ${r} states. The database error is in the run log above.`,
2201
+ },
2202
+ },
2203
+ {
2204
+ componentId: "decide-state-1",
2205
+ metadataId: ComponentID.JavaScriptCode,
2206
+ componentType: ComponentType.Component,
2207
+ position: { x: -150, y: 1100 },
2208
+ args: {
2209
+ code: jiraDecideStateScript(kind),
2210
+ /*
2211
+ * The event goes last: its status and user names are Jira users'
2212
+ * text, and text from the other system is only ever substituted
2213
+ * after everything else in an argument.
2214
+ */
2215
+ arguments: jsonText({
2216
+ [r]: `{{local.components.${find}.returnValues.model}}`,
2217
+ states: "{{local.components.find-states-1.returnValues.models}}",
2218
+ event: "{{local.components.read-event-1.returnValues.returnValue}}",
2219
+ }),
2220
+ },
2221
+ },
2222
+ {
2223
+ componentId: "log-decide-failed",
2224
+ metadataId: ComponentID.Log,
2225
+ componentType: ComponentType.Component,
2226
+ position: { x: 100, y: 1300 },
2227
+ args: {
2228
+ value: `❌ Could not map the Jira status to an ${r} state: {{local.components.decide-state-1.returnValues.error}}`,
2229
+ },
2230
+ },
2231
+ {
2232
+ componentId: "if-change-1",
2233
+ metadataId: ComponentID.IfElse,
2234
+ componentType: ComponentType.Component,
2235
+ position: { x: -150, y: 1300 },
2236
+ args: proceedCondition("decide-state-1"),
2237
+ },
2238
+ {
2239
+ componentId: "log-unchanged",
2240
+ metadataId: ComponentID.Log,
2241
+ componentType: ComponentType.Component,
2242
+ position: { x: 100, y: 1500 },
2243
+ args: {
2244
+ value: "ℹ️ {{local.components.decide-state-1.returnValues.returnValue.reason}}",
2245
+ },
2246
+ },
2247
+ {
2248
+ /*
2249
+ * A state change is a new timeline row, not an edit to the
2250
+ * record: the timeline is what records it, notifies, and refuses
2251
+ * to move a record backwards.
2252
+ */
2253
+ componentId: "change-state-1",
2254
+ metadataId: `${r}-state-timeline-create-one`,
2255
+ componentType: ComponentType.Component,
2256
+ position: { x: -400, y: 1500 },
2257
+ args: {
2258
+ json: jsonText({
2259
+ [kind.idColumn]: `{{local.components.decide-state-1.returnValues.returnValue.${r}Id}}`,
2260
+ [kind.timelineStateColumn]: "{{local.components.decide-state-1.returnValues.returnValue.stateId}}",
2261
+ rootCause: "{{local.components.decide-state-1.returnValues.returnValue.rootCause}}",
2262
+ }),
2263
+ },
2264
+ },
2265
+ {
2266
+ componentId: "log-changed",
2267
+ metadataId: ComponentID.Log,
2268
+ componentType: ComponentType.Component,
2269
+ position: { x: -400, y: 1700 },
2270
+ args: {
2271
+ value: `✅ Moved {{local.components.${find}.returnValues.model.${kind.numberField}}} to {{local.components.decide-state-1.returnValues.returnValue.stateName}} because Jira issue {{local.components.read-event-1.returnValues.returnValue.issueKey}} is now {{local.components.read-event-1.returnValues.returnValue.jiraStatus}}.`,
2272
+ },
2273
+ },
2274
+ {
2275
+ componentId: "log-change-failed",
2276
+ metadataId: ComponentID.Log,
2277
+ componentType: ComponentType.Component,
2278
+ position: { x: -150, y: 1700 },
2279
+ args: {
2280
+ value: `❌ Could not change the ${r}'s state. The reason is in the run log above — an ${r} cannot move back to an earlier state.`,
2281
+ },
2282
+ },
2283
+ ],
2284
+ edges: [
2285
+ {
2286
+ fromComponentId: "webhook-1",
2287
+ toComponentId: "read-event-1",
2288
+ fromPort: "out",
2289
+ },
2290
+ {
2291
+ fromComponentId: "read-event-1",
2292
+ toComponentId: "if-status-changed-1",
2293
+ fromPort: "success",
2294
+ },
2295
+ {
2296
+ fromComponentId: "read-event-1",
2297
+ toComponentId: "log-read-failed",
2298
+ fromPort: "error",
2299
+ },
2300
+ {
2301
+ fromComponentId: "if-status-changed-1",
2302
+ toComponentId: find,
2303
+ fromPort: "yes",
2304
+ },
2305
+ {
2306
+ fromComponentId: "if-status-changed-1",
2307
+ toComponentId: "log-ignored",
2308
+ fromPort: "no",
2309
+ },
2310
+ {
2311
+ fromComponentId: find,
2312
+ toComponentId: "find-states-1",
2313
+ fromPort: "success",
2314
+ },
2315
+ {
2316
+ fromComponentId: find,
2317
+ toComponentId: `log-find-${r}-failed`,
2318
+ fromPort: "error",
2319
+ },
2320
+ {
2321
+ fromComponentId: "find-states-1",
2322
+ toComponentId: "decide-state-1",
2323
+ fromPort: "success",
2324
+ },
2325
+ {
2326
+ fromComponentId: "find-states-1",
2327
+ toComponentId: "log-find-states-failed",
2328
+ fromPort: "error",
2329
+ },
2330
+ {
2331
+ fromComponentId: "decide-state-1",
2332
+ toComponentId: "if-change-1",
2333
+ fromPort: "success",
2334
+ },
2335
+ {
2336
+ fromComponentId: "decide-state-1",
2337
+ toComponentId: "log-decide-failed",
2338
+ fromPort: "error",
2339
+ },
2340
+ {
2341
+ fromComponentId: "if-change-1",
2342
+ toComponentId: "change-state-1",
2343
+ fromPort: "yes",
2344
+ },
2345
+ {
2346
+ fromComponentId: "if-change-1",
2347
+ toComponentId: "log-unchanged",
2348
+ fromPort: "no",
2349
+ },
2350
+ {
2351
+ fromComponentId: "change-state-1",
2352
+ toComponentId: "log-changed",
2353
+ fromPort: "success",
2354
+ },
2355
+ {
2356
+ fromComponentId: "change-state-1",
2357
+ toComponentId: "log-change-failed",
2358
+ fromPort: "error",
2359
+ },
2360
+ ],
2361
+ },
2362
+ };
2363
+ };
2364
+ const jiraCommentToNoteTemplate = (kind) => {
2365
+ const r = kind.noun;
2366
+ const find = `find-${r}-1`;
2367
+ return {
2368
+ id: `jira-comment-to-${r}-private-note`,
2369
+ name: `Add Jira comments to the ${r} as private notes`,
2370
+ description: `Copies each comment on the linked Jira issue onto the ${r} as a private note, so responders see the whole conversation in one place.`,
2371
+ teaches: "How to follow a webhook with a lookup call when the payload does not carry everything you need.",
2372
+ category: WorkflowTemplateCategory.Jira,
2373
+ icon: IconProp.ChatBubbleOvalLeftEllipsis,
2374
+ workflowName: `Copy Jira comments to ${r}`,
2375
+ workflowDescription: `Adds each comment on a linked Jira issue to the ${r} as a private note. Enable it, copy the URL from the Webhook trigger, and register it in Jira under Settings > System > WebHooks for the Comment created event.`,
2376
+ variables: [JIRA_BASE_URL, JIRA_BASIC_AUTH_TOKEN],
2377
+ graph: {
2378
+ nodes: [
2379
+ {
2380
+ componentId: "webhook-1",
2381
+ metadataId: ComponentID.Webhook,
2382
+ componentType: ComponentType.Trigger,
2383
+ position: { x: 100, y: 100 },
2384
+ },
2385
+ {
2386
+ componentId: "read-comment-1",
2387
+ metadataId: ComponentID.JavaScriptCode,
2388
+ componentType: ComponentType.Component,
2389
+ position: { x: 100, y: 300 },
2390
+ args: {
2391
+ code: jiraReadCommentScript(kind),
2392
+ arguments: "{{local.components.webhook-1.returnValues.request-body}}",
2393
+ },
2394
+ },
2395
+ {
2396
+ componentId: "log-read-failed",
2397
+ metadataId: ComponentID.Log,
2398
+ componentType: ComponentType.Component,
2399
+ position: { x: 600, y: 300 },
2400
+ args: {
2401
+ value: "❌ Could not read the Jira event: {{local.components.read-comment-1.returnValues.error}}",
2402
+ },
2403
+ },
2404
+ {
2405
+ componentId: "if-comment-1",
2406
+ metadataId: ComponentID.IfElse,
2407
+ componentType: ComponentType.Component,
2408
+ position: { x: 100, y: 500 },
2409
+ args: proceedCondition("read-comment-1"),
2410
+ },
2411
+ {
2412
+ componentId: "log-ignored",
2413
+ metadataId: ComponentID.Log,
2414
+ componentType: ComponentType.Component,
2415
+ position: { x: 350, y: 700 },
2416
+ args: {
2417
+ value: "ℹ️ {{local.components.read-comment-1.returnValues.returnValue.reason}}",
2418
+ },
2419
+ },
2420
+ {
2421
+ componentId: "get-issue-1",
2422
+ metadataId: ComponentID.ApiGet,
2423
+ componentType: ComponentType.Component,
2424
+ position: { x: -150, y: 700 },
2425
+ args: {
2426
+ url: "{{local.variables.jiraBaseUrl}}/rest/api/3/issue/{{local.components.read-comment-1.returnValues.returnValue.issueKey}}?fields=labels",
2427
+ "request-headers": jiraHeaders(),
2428
+ },
2429
+ },
2430
+ {
2431
+ componentId: "log-get-issue-failed",
2432
+ metadataId: ComponentID.Log,
2433
+ componentType: ComponentType.Component,
2434
+ position: { x: 100, y: 900 },
2435
+ args: {
2436
+ value: "❌ Could not read Jira issue {{local.components.read-comment-1.returnValues.returnValue.issueKey}}: {{local.components.get-issue-1.returnValues.error}}\nJira said: {{local.components.get-issue-1.returnValues.response-body}}",
2437
+ },
2438
+ },
2439
+ {
2440
+ componentId: "find-link-1",
2441
+ metadataId: ComponentID.JavaScriptCode,
2442
+ componentType: ComponentType.Component,
2443
+ position: { x: -150, y: 900 },
2444
+ args: {
2445
+ code: jiraFindLinkedRecordScript(kind),
2446
+ arguments: jsonText({
2447
+ comment: "{{local.components.read-comment-1.returnValues.returnValue}}",
2448
+ issue: "{{local.components.get-issue-1.returnValues.response-body}}",
2449
+ }),
2450
+ },
2451
+ },
2452
+ {
2453
+ componentId: "log-find-link-failed",
2454
+ metadataId: ComponentID.Log,
2455
+ componentType: ComponentType.Component,
2456
+ position: { x: 100, y: 1100 },
2457
+ args: {
2458
+ value: "❌ Could not read the issue's labels: {{local.components.find-link-1.returnValues.error}}",
2459
+ },
2460
+ },
2461
+ {
2462
+ componentId: "if-linked-1",
2463
+ metadataId: ComponentID.IfElse,
2464
+ componentType: ComponentType.Component,
2465
+ position: { x: -150, y: 1100 },
2466
+ args: proceedCondition("find-link-1"),
2467
+ },
2468
+ {
2469
+ componentId: "log-not-linked",
2470
+ metadataId: ComponentID.Log,
2471
+ componentType: ComponentType.Component,
2472
+ position: { x: 100, y: 1300 },
2473
+ args: {
2474
+ value: "ℹ️ {{local.components.find-link-1.returnValues.returnValue.reason}}",
2475
+ },
2476
+ },
2477
+ {
2478
+ componentId: find,
2479
+ metadataId: `${r}-find-one`,
2480
+ componentType: ComponentType.Component,
2481
+ position: { x: -400, y: 1300 },
2482
+ args: {
2483
+ query: {
2484
+ _id: `{{local.components.find-link-1.returnValues.returnValue.${r}Id}}`,
2485
+ },
2486
+ select: { _id: true, [kind.numberField]: true },
2487
+ },
2488
+ },
2489
+ {
2490
+ componentId: `log-find-${r}-failed`,
2491
+ metadataId: ComponentID.Log,
2492
+ componentType: ComponentType.Component,
2493
+ position: { x: -150, y: 1500 },
2494
+ args: {
2495
+ value: `❌ Could not look up the ${r}. The database error is in the run log above.`,
2496
+ },
2497
+ },
2498
+ {
2499
+ /*
2500
+ * Find One answers "nothing matched" on its Success port, so this
2501
+ * is what stops a label naming a record in another project — the
2502
+ * lookup is scoped to this one — from being written to.
2503
+ */
2504
+ componentId: "if-found-1",
2505
+ metadataId: ComponentID.IfElse,
2506
+ componentType: ComponentType.Component,
2507
+ position: { x: -400, y: 1500 },
2508
+ args: {
2509
+ "input-1-type": ConditionValueType.Text,
2510
+ "input-1": `{{local.components.${find}.returnValues.model._id}}`,
2511
+ operator: ConditionOperator.EqualTo,
2512
+ "input-2-type": ConditionValueType.Text,
2513
+ "input-2": `{{local.components.find-link-1.returnValues.returnValue.${r}Id}}`,
2514
+ },
2515
+ },
2516
+ {
2517
+ componentId: "log-not-found",
2518
+ metadataId: ComponentID.Log,
2519
+ componentType: ComponentType.Component,
2520
+ position: { x: -150, y: 1700 },
2521
+ args: {
2522
+ value: `ℹ️ Jira issue {{local.components.read-comment-1.returnValues.returnValue.issueKey}} names ${r} {{local.components.find-link-1.returnValues.returnValue.${r}Id}}, which is not in this project.`,
2523
+ },
2524
+ },
2525
+ {
2526
+ componentId: "create-note-1",
2527
+ metadataId: `${r}-internal-note-create-one`,
2528
+ componentType: ComponentType.Component,
2529
+ position: { x: -650, y: 1700 },
2530
+ args: {
2531
+ json: jsonText({
2532
+ [kind.idColumn]: `{{local.components.${find}.returnValues.model._id}}`,
2533
+ note: "{{local.components.read-comment-1.returnValues.returnValue.note}}",
2534
+ }),
2535
+ },
2536
+ },
2537
+ {
2538
+ componentId: "log-noted",
2539
+ metadataId: ComponentID.Log,
2540
+ componentType: ComponentType.Component,
2541
+ position: { x: -650, y: 1900 },
2542
+ args: {
2543
+ value: `✅ Added the Jira comment on {{local.components.read-comment-1.returnValues.returnValue.issueKey}} to {{local.components.${find}.returnValues.model.${kind.numberField}}} as a private note.`,
2544
+ },
2545
+ },
2546
+ {
2547
+ componentId: "log-note-failed",
2548
+ metadataId: ComponentID.Log,
2549
+ componentType: ComponentType.Component,
2550
+ position: { x: -400, y: 1900 },
2551
+ args: {
2552
+ value: "❌ Could not add the private note. The database error is in the run log above.",
2553
+ },
2554
+ },
2555
+ ],
2556
+ edges: [
2557
+ {
2558
+ fromComponentId: "webhook-1",
2559
+ toComponentId: "read-comment-1",
2560
+ fromPort: "out",
2561
+ },
2562
+ {
2563
+ fromComponentId: "read-comment-1",
2564
+ toComponentId: "if-comment-1",
2565
+ fromPort: "success",
2566
+ },
2567
+ {
2568
+ fromComponentId: "read-comment-1",
2569
+ toComponentId: "log-read-failed",
2570
+ fromPort: "error",
2571
+ },
2572
+ {
2573
+ fromComponentId: "if-comment-1",
2574
+ toComponentId: "get-issue-1",
2575
+ fromPort: "yes",
2576
+ },
2577
+ {
2578
+ fromComponentId: "if-comment-1",
2579
+ toComponentId: "log-ignored",
2580
+ fromPort: "no",
2581
+ },
2582
+ {
2583
+ fromComponentId: "get-issue-1",
2584
+ toComponentId: "find-link-1",
2585
+ fromPort: "success",
2586
+ },
2587
+ {
2588
+ fromComponentId: "get-issue-1",
2589
+ toComponentId: "log-get-issue-failed",
2590
+ fromPort: "error",
2591
+ },
2592
+ {
2593
+ fromComponentId: "find-link-1",
2594
+ toComponentId: "if-linked-1",
2595
+ fromPort: "success",
2596
+ },
2597
+ {
2598
+ fromComponentId: "find-link-1",
2599
+ toComponentId: "log-find-link-failed",
2600
+ fromPort: "error",
2601
+ },
2602
+ {
2603
+ fromComponentId: "if-linked-1",
2604
+ toComponentId: find,
2605
+ fromPort: "yes",
2606
+ },
2607
+ {
2608
+ fromComponentId: "if-linked-1",
2609
+ toComponentId: "log-not-linked",
2610
+ fromPort: "no",
2611
+ },
2612
+ {
2613
+ fromComponentId: find,
2614
+ toComponentId: "if-found-1",
2615
+ fromPort: "success",
2616
+ },
2617
+ {
2618
+ fromComponentId: find,
2619
+ toComponentId: `log-find-${r}-failed`,
2620
+ fromPort: "error",
2621
+ },
2622
+ {
2623
+ fromComponentId: "if-found-1",
2624
+ toComponentId: "create-note-1",
2625
+ fromPort: "yes",
2626
+ },
2627
+ {
2628
+ fromComponentId: "if-found-1",
2629
+ toComponentId: "log-not-found",
2630
+ fromPort: "no",
2631
+ },
2632
+ {
2633
+ fromComponentId: "create-note-1",
2634
+ toComponentId: "log-noted",
2635
+ fromPort: "success",
2636
+ },
2637
+ {
2638
+ fromComponentId: "create-note-1",
2639
+ toComponentId: "log-note-failed",
2640
+ fromPort: "error",
2641
+ },
2642
+ ],
2643
+ },
2644
+ };
2645
+ };
2646
+ const jiraIssueChangesToNoteTemplate = (kind) => {
2647
+ const r = kind.noun;
2648
+ const find = `find-${r}-1`;
2649
+ return {
2650
+ id: `jira-issue-changes-to-${r}-private-note`,
2651
+ name: `Add Jira issue changes to the ${r} as private notes`,
2652
+ description: `When someone edits the linked Jira issue — its priority, assignee, summary and so on — the change is noted on the ${r}.`,
2653
+ teaches: "How to turn a list of changes in a webhook into one readable note.",
2654
+ category: WorkflowTemplateCategory.Jira,
2655
+ icon: IconProp.DocumentText,
2656
+ workflowName: `Copy Jira issue changes to ${r}`,
2657
+ workflowDescription: `Notes each change to a linked Jira issue on the ${r} as a private note. Enable it, copy the URL from the Webhook trigger, and register it in Jira under Settings > System > WebHooks for the Issue updated event.`,
2658
+ variables: [],
2659
+ graph: {
2660
+ nodes: [
2661
+ {
2662
+ componentId: "webhook-1",
2663
+ metadataId: ComponentID.Webhook,
2664
+ componentType: ComponentType.Trigger,
2665
+ position: { x: 100, y: 100 },
2666
+ },
2667
+ {
2668
+ componentId: "read-changes-1",
2669
+ metadataId: ComponentID.JavaScriptCode,
2670
+ componentType: ComponentType.Component,
2671
+ position: { x: 100, y: 300 },
2672
+ args: {
2673
+ code: jiraReadIssueChangesScript(kind),
2674
+ arguments: "{{local.components.webhook-1.returnValues.request-body}}",
2675
+ },
2676
+ },
2677
+ {
2678
+ componentId: "log-read-failed",
2679
+ metadataId: ComponentID.Log,
2680
+ componentType: ComponentType.Component,
2681
+ position: { x: 600, y: 300 },
2682
+ args: {
2683
+ value: "❌ Could not read the Jira event: {{local.components.read-changes-1.returnValues.error}}",
2684
+ },
2685
+ },
2686
+ {
2687
+ componentId: "if-changed-1",
2688
+ metadataId: ComponentID.IfElse,
2689
+ componentType: ComponentType.Component,
2690
+ position: { x: 100, y: 500 },
2691
+ args: proceedCondition("read-changes-1"),
2692
+ },
2693
+ {
2694
+ componentId: "log-ignored",
2695
+ metadataId: ComponentID.Log,
2696
+ componentType: ComponentType.Component,
2697
+ position: { x: 350, y: 700 },
2698
+ args: {
2699
+ value: "ℹ️ {{local.components.read-changes-1.returnValues.returnValue.reason}}",
2700
+ },
2701
+ },
2702
+ {
2703
+ componentId: find,
2704
+ metadataId: `${r}-find-one`,
2705
+ componentType: ComponentType.Component,
2706
+ position: { x: -150, y: 700 },
2707
+ args: {
2708
+ query: {
2709
+ _id: `{{local.components.read-changes-1.returnValues.returnValue.${r}Id}}`,
2710
+ },
2711
+ select: { _id: true, [kind.numberField]: true },
2712
+ },
2713
+ },
2714
+ {
2715
+ componentId: `log-find-${r}-failed`,
2716
+ metadataId: ComponentID.Log,
2717
+ componentType: ComponentType.Component,
2718
+ position: { x: 100, y: 900 },
2719
+ args: {
2720
+ value: `❌ Could not look up the ${r}. The database error is in the run log above.`,
2721
+ },
2722
+ },
2723
+ {
2724
+ componentId: "if-found-1",
2725
+ metadataId: ComponentID.IfElse,
2726
+ componentType: ComponentType.Component,
2727
+ position: { x: -150, y: 900 },
2728
+ args: {
2729
+ "input-1-type": ConditionValueType.Text,
2730
+ "input-1": `{{local.components.${find}.returnValues.model._id}}`,
2731
+ operator: ConditionOperator.EqualTo,
2732
+ "input-2-type": ConditionValueType.Text,
2733
+ "input-2": `{{local.components.read-changes-1.returnValues.returnValue.${r}Id}}`,
2734
+ },
2735
+ },
2736
+ {
2737
+ componentId: "log-not-found",
2738
+ metadataId: ComponentID.Log,
2739
+ componentType: ComponentType.Component,
2740
+ position: { x: 100, y: 1100 },
2741
+ args: {
2742
+ value: `ℹ️ Jira issue {{local.components.read-changes-1.returnValues.returnValue.issueKey}} names ${r} {{local.components.read-changes-1.returnValues.returnValue.${r}Id}}, which is not in this project.`,
2743
+ },
2744
+ },
2745
+ {
2746
+ componentId: "create-note-1",
2747
+ metadataId: `${r}-internal-note-create-one`,
2748
+ componentType: ComponentType.Component,
2749
+ position: { x: -400, y: 1100 },
2750
+ args: {
2751
+ json: jsonText({
2752
+ [kind.idColumn]: `{{local.components.${find}.returnValues.model._id}}`,
2753
+ note: "{{local.components.read-changes-1.returnValues.returnValue.note}}",
2754
+ }),
2755
+ },
2756
+ },
2757
+ {
2758
+ componentId: "log-noted",
2759
+ metadataId: ComponentID.Log,
2760
+ componentType: ComponentType.Component,
2761
+ position: { x: -400, y: 1300 },
2762
+ args: {
2763
+ value: `✅ Noted the changes to Jira issue {{local.components.read-changes-1.returnValues.returnValue.issueKey}} on {{local.components.${find}.returnValues.model.${kind.numberField}}}.`,
2764
+ },
2765
+ },
2766
+ {
2767
+ componentId: "log-note-failed",
2768
+ metadataId: ComponentID.Log,
2769
+ componentType: ComponentType.Component,
2770
+ position: { x: -150, y: 1300 },
2771
+ args: {
2772
+ value: "❌ Could not add the private note. The database error is in the run log above.",
2773
+ },
2774
+ },
2775
+ ],
2776
+ edges: [
2777
+ {
2778
+ fromComponentId: "webhook-1",
2779
+ toComponentId: "read-changes-1",
2780
+ fromPort: "out",
2781
+ },
2782
+ {
2783
+ fromComponentId: "read-changes-1",
2784
+ toComponentId: "if-changed-1",
2785
+ fromPort: "success",
2786
+ },
2787
+ {
2788
+ fromComponentId: "read-changes-1",
2789
+ toComponentId: "log-read-failed",
2790
+ fromPort: "error",
2791
+ },
2792
+ {
2793
+ fromComponentId: "if-changed-1",
2794
+ toComponentId: find,
2795
+ fromPort: "yes",
2796
+ },
2797
+ {
2798
+ fromComponentId: "if-changed-1",
2799
+ toComponentId: "log-ignored",
2800
+ fromPort: "no",
2801
+ },
2802
+ {
2803
+ fromComponentId: find,
2804
+ toComponentId: "if-found-1",
2805
+ fromPort: "success",
2806
+ },
2807
+ {
2808
+ fromComponentId: find,
2809
+ toComponentId: `log-find-${r}-failed`,
2810
+ fromPort: "error",
2811
+ },
2812
+ {
2813
+ fromComponentId: "if-found-1",
2814
+ toComponentId: "create-note-1",
2815
+ fromPort: "yes",
2816
+ },
2817
+ {
2818
+ fromComponentId: "if-found-1",
2819
+ toComponentId: "log-not-found",
2820
+ fromPort: "no",
2821
+ },
2822
+ {
2823
+ fromComponentId: "create-note-1",
2824
+ toComponentId: "log-noted",
2825
+ fromPort: "success",
2826
+ },
2827
+ {
2828
+ fromComponentId: "create-note-1",
2829
+ toComponentId: "log-note-failed",
2830
+ fromPort: "error",
2831
+ },
2832
+ ],
2833
+ },
2834
+ };
2835
+ };
2836
+ /** One kind's set, OneUptime -> Jira first. Public notes exist only on incidents. */
2837
+ const jiraTemplatesForKind = (kind) => {
2838
+ return [
2839
+ jiraCreateIssueTemplate(kind),
2840
+ jiraTransitionIssueTemplate(kind),
2841
+ jiraPrivateNoteToCommentTemplate(kind),
2842
+ ...(kind.hasPublicNotes ? [jiraPublicNoteToCommentTemplate(kind)] : []),
2843
+ jiraUpdateCommentTemplate(kind),
2844
+ jiraCreateRecordTemplate(kind),
2845
+ jiraStatusToStateTemplate(kind),
2846
+ jiraCommentToNoteTemplate(kind),
2847
+ jiraIssueChangesToNoteTemplate(kind),
2848
+ ];
2849
+ };
2850
+ const JIRA_TEMPLATE_DEFINITIONS = [
2851
+ ...jiraTemplatesForKind(INCIDENT_KIND),
2852
+ ...jiraTemplatesForKind(ALERT_KIND),
2853
+ ];
164
2854
  const TEMPLATE_DEFINITIONS = [
165
2855
  /* ----------------------------- Basics ----------------------------- */
166
2856
  {
@@ -657,7 +3347,7 @@ const TEMPLATE_DEFINITIONS = [
657
3347
  url: "{{local.variables.forwardUrl}}",
658
3348
  "request-body": [
659
3349
  "{",
660
- ' "id": "{{local.components.incident-on-create-1.returnValues.model._id.value}}",',
3350
+ ' "id": "{{local.components.incident-on-create-1.returnValues.model._id}}",',
661
3351
  ' "number": "{{local.components.incident-on-create-1.returnValues.model.incidentNumber}}",',
662
3352
  ' "title": "{{local.components.incident-on-create-1.returnValues.model.title}}",',
663
3353
  ' "severity": "{{local.components.incident-on-create-1.returnValues.model.incidentSeverity.name}}",',
@@ -1097,7 +3787,7 @@ const TEMPLATE_DEFINITIONS = [
1097
3787
  url: "{{local.variables.forwardUrl}}",
1098
3788
  "request-body": [
1099
3789
  "{",
1100
- ' "eventId": "{{local.components.monitor-status-timeline-on-create-1.returnValues.model._id.value}}",',
3790
+ ' "eventId": "{{local.components.monitor-status-timeline-on-create-1.returnValues.model._id}}",',
1101
3791
  ' "monitor": "{{local.components.monitor-status-timeline-on-create-1.returnValues.model.monitor.name}}",',
1102
3792
  ' "status": "{{local.components.monitor-status-timeline-on-create-1.returnValues.model.monitorStatus.name}}",',
1103
3793
  ' "isOffline": {{local.components.monitor-status-timeline-on-create-1.returnValues.model.monitorStatus.isOfflineState}}',
@@ -1900,6 +4590,8 @@ const TEMPLATE_DEFINITIONS = [
1900
4590
  ],
1901
4591
  },
1902
4592
  },
4593
+ /* ------------------------------- Jira ------------------------------- */
4594
+ ...JIRA_TEMPLATE_DEFINITIONS,
1903
4595
  /* --------------------------- Integrations --------------------------- */
1904
4596
  {
1905
4597
  id: "webhook-to-slack",