@oneuptime/common 12.0.8 → 12.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (769) hide show
  1. package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +1 -1
  2. package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +1 -1
  3. package/Models/DatabaseModels/AIConversation.ts +32 -0
  4. package/Models/DatabaseModels/AIConversationMessage.ts +41 -0
  5. package/Models/DatabaseModels/AlertEpisodeMember.ts +27 -0
  6. package/Models/DatabaseModels/IncidentEpisodeMember.ts +28 -0
  7. package/Models/DatabaseModels/Index.ts +12 -4
  8. package/Models/DatabaseModels/{TelemetryEntity.ts → InventoryItem.ts} +139 -9
  9. package/Models/DatabaseModels/InventoryItemCustomField.ts +434 -0
  10. package/Models/DatabaseModels/{TelemetryEntityRelationship.ts → InventoryItemRelationship.ts} +8 -8
  11. package/Models/DatabaseModels/NetworkDevice.ts +141 -0
  12. package/Models/DatabaseModels/NetworkDeviceLink.ts +699 -0
  13. package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +467 -0
  14. package/Models/DatabaseModels/NetworkTopologySuppression.ts +429 -0
  15. package/Models/DatabaseModels/OnCallDutyPolicyFeed.ts +9 -0
  16. package/Models/DatabaseModels/Project.ts +78 -0
  17. package/Models/DatabaseModels/UserCall.ts +42 -0
  18. package/Models/DatabaseModels/UserEmail.ts +44 -0
  19. package/Models/DatabaseModels/UserNotificationRule.ts +425 -55
  20. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +24 -2
  21. package/Models/DatabaseModels/UserPush.ts +49 -0
  22. package/Models/DatabaseModels/UserSMS.ts +43 -0
  23. package/Models/DatabaseModels/UserTelegram.ts +59 -0
  24. package/Models/DatabaseModels/UserWebhook.ts +52 -0
  25. package/Models/DatabaseModels/UserWhatsApp.ts +41 -0
  26. package/Models/DatabaseModels/WorkflowVariable.ts +12 -0
  27. package/Server/API/AIChatAPI.ts +315 -1
  28. package/Server/API/DashboardAPI.ts +217 -1
  29. package/Server/API/OnCallReadinessAPI.ts +841 -0
  30. package/Server/API/TeamComplianceAPI.ts +69 -17
  31. package/Server/API/TelemetryAPI.ts +220 -12
  32. package/Server/EnvironmentConfig.ts +52 -0
  33. package/Server/Infrastructure/Postgres/DataSourceOptions.ts +22 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +4 -4
  35. package/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.ts +5 -5
  36. package/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.ts +35 -0
  37. package/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.ts +82 -0
  38. package/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.ts +91 -0
  39. package/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.ts +47 -0
  40. package/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.ts +255 -0
  41. package/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.ts +107 -0
  42. package/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.ts +90 -0
  43. package/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.ts +39 -0
  44. package/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.ts +33 -0
  45. package/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.ts +59 -0
  46. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +20 -0
  47. package/Server/Infrastructure/Queue.ts +78 -13
  48. package/Server/Middleware/PublicDashboardRateLimit.ts +593 -0
  49. package/Server/Services/AIService.ts +7 -0
  50. package/Server/Services/AlertEpisodeStateTimelineService.ts +29 -0
  51. package/Server/Services/AlertSeverityService.ts +63 -0
  52. package/Server/Services/DashboardService.ts +9 -10
  53. package/Server/Services/DatabaseService.ts +32 -2
  54. package/Server/Services/IncidentEpisodeStateTimelineService.ts +29 -0
  55. package/Server/Services/IncidentSeverityService.ts +76 -0
  56. package/Server/Services/Index.ts +12 -4
  57. package/Server/Services/InventoryItemCustomFieldService.ts +9 -0
  58. package/Server/Services/{TelemetryEntityRelationshipService.ts → InventoryItemRelationshipService.ts} +4 -4
  59. package/Server/Services/{TelemetryEntityService.ts → InventoryItemService.ts} +89 -20
  60. package/Server/Services/LogAggregationService.ts +45 -8
  61. package/Server/Services/MetricAggregationService.ts +121 -0
  62. package/Server/Services/MetricService.ts +7 -7
  63. package/Server/Services/NetworkDeviceLinkRuleService.ts +10 -0
  64. package/Server/Services/NetworkDeviceLinkService.ts +84 -0
  65. package/Server/Services/NetworkDeviceService.ts +140 -0
  66. package/Server/Services/NetworkSiteService.ts +77 -25
  67. package/Server/Services/NetworkTopologySuppressionService.ts +84 -0
  68. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +41 -29
  69. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +8 -0
  70. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +62 -13
  71. package/Server/Services/OnCallDutyPolicyScheduleService.ts +61 -1
  72. package/Server/Services/OnCallNotificationAlertingService.ts +742 -0
  73. package/Server/Services/OnCallReadinessService.ts +2803 -0
  74. package/Server/Services/OnCallSetupReminderService.ts +955 -0
  75. package/Server/Services/ProfileAggregationService.ts +123 -0
  76. package/Server/Services/StatusPageService.ts +9 -10
  77. package/Server/Services/TeamComplianceService.ts +429 -252
  78. package/Server/Services/UserCallService.ts +26 -1
  79. package/Server/Services/UserEmailService.ts +26 -1
  80. package/Server/Services/UserNotificationRuleAdminService.ts +1183 -0
  81. package/Server/Services/UserNotificationRuleService.ts +3812 -333
  82. package/Server/Services/UserOnCallLogService.ts +561 -48
  83. package/Server/Services/UserPushService.ts +29 -0
  84. package/Server/Services/UserService.ts +11 -0
  85. package/Server/Services/UserSmsService.ts +26 -1
  86. package/Server/Services/UserTelegramService.ts +24 -1
  87. package/Server/Services/UserWebhookService.ts +28 -1
  88. package/Server/Services/UserWhatsAppService.ts +24 -1
  89. package/Server/Types/Database/Permissions/BasePermission.ts +19 -0
  90. package/Server/Types/Database/Permissions/CreatePermission.ts +164 -0
  91. package/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.ts +340 -0
  92. package/Server/Types/Database/Permissions/QueryPermission.ts +48 -0
  93. package/Server/Types/Database/Permissions/TenantPermission.ts +8 -1
  94. package/Server/Types/Workflow/Components/API/Delete.ts +1 -1
  95. package/Server/Types/Workflow/Components/API/Get.ts +1 -1
  96. package/Server/Types/Workflow/Components/API/Patch.ts +1 -1
  97. package/Server/Types/Workflow/Components/API/Post.ts +1 -1
  98. package/Server/Types/Workflow/Components/API/Put.ts +1 -1
  99. package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +29 -5
  100. package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +18 -10
  101. package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +55 -0
  102. package/Server/Types/Workflow/Components/Conditions/IfElse.ts +3 -17
  103. package/Server/Types/Workflow/Components/Email.ts +25 -7
  104. package/Server/Types/Workflow/Components/JavaScript.ts +10 -3
  105. package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +1 -1
  106. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +643 -48
  107. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +32 -3
  108. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +20 -6
  109. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +7 -0
  110. package/Server/Utils/AI/Toolbox/AIActionTools.ts +2 -2
  111. package/Server/Utils/AI/Toolbox/AIMetaTools.ts +863 -0
  112. package/Server/Utils/AI/Toolbox/AlertTools.ts +177 -15
  113. package/Server/Utils/AI/Toolbox/IncidentTools.ts +191 -10
  114. package/Server/Utils/AI/Toolbox/Index.ts +48 -0
  115. package/Server/Utils/AI/Toolbox/MonitorTools.ts +298 -11
  116. package/Server/Utils/AI/Toolbox/NoteWriteTools.ts +295 -0
  117. package/Server/Utils/AI/Toolbox/OnCallTools.ts +1246 -0
  118. package/Server/Utils/AI/Toolbox/RunbookTools.ts +424 -0
  119. package/Server/Utils/AI/Toolbox/SloTools.ts +456 -0
  120. package/Server/Utils/AI/Toolbox/StatusPageTools.ts +559 -0
  121. package/Server/Utils/AI/Toolbox/TeamTools.ts +327 -0
  122. package/Server/Utils/AI/Toolbox/TimelineTools.ts +615 -0
  123. package/Server/Utils/AI/Toolbox/WorkflowProbeTools.ts +664 -0
  124. package/Server/Utils/ClientIp.ts +221 -0
  125. package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +47 -0
  126. package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +163 -0
  127. package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +147 -0
  128. package/Server/Utils/Express.ts +12 -17
  129. package/Server/Utils/LLM/LLMService.ts +85 -8
  130. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +204 -10
  131. package/Server/Utils/SSRFProtection.ts +98 -23
  132. package/Server/Utils/StartServer.ts +12 -3
  133. package/Server/Utils/Telemetry/EntityRegistry.ts +205 -18
  134. package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +25 -25
  135. package/Server/Utils/Telemetry/TelemetryEntity.ts +160 -52
  136. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +7 -3
  137. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +2146 -0
  138. package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +561 -0
  139. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +2470 -0
  140. package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +1897 -0
  141. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3606 -0
  142. package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +784 -0
  143. package/Tests/App/Dashboard/OnCallRulesTable.test.tsx +1119 -0
  144. package/Tests/App/Dashboard/SloWidgetFetching.test.tsx +531 -0
  145. package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +1312 -0
  146. package/Tests/App/Dashboard/UserSettingsSetupChecklistPage.test.tsx +1390 -0
  147. package/Tests/Models/InventoryItemModel.test.ts +174 -0
  148. package/Tests/Models/InventoryItemNaming.test.ts +302 -0
  149. package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +437 -0
  150. package/Tests/Server/API/DashboardPublicRateLimit.test.ts +659 -0
  151. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +18 -0
  152. package/Tests/Server/API/DashboardPublicSloAPI.test.ts +880 -0
  153. package/Tests/Server/API/Helpers.ts +24 -15
  154. package/Tests/Server/API/OnCallReadinessAPI.test.ts +2680 -0
  155. package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +915 -0
  156. package/Tests/Server/Infrastructure/Postgres/EpisodeMemberNotifyIndexesMigration.test.ts +533 -0
  157. package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +213 -0
  158. package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +432 -0
  159. package/Tests/Server/Infrastructure/Queue.test.ts +293 -0
  160. package/Tests/Server/Middleware/PublicDashboardRateLimit.test.ts +1645 -0
  161. package/Tests/Server/Services/AdminRuleEditGuards.test.ts +2848 -0
  162. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1393 -0
  163. package/Tests/Server/Services/EpisodeRuleSeverityRepair.test.ts +1802 -0
  164. package/Tests/Server/Services/EpisodeStateTimelineNote.test.ts +304 -0
  165. package/Tests/Server/Services/InventoryItemDisplayName.test.ts +339 -0
  166. package/Tests/Server/Services/{TelemetryEntityManualCreate.test.ts → InventoryItemManualCreate.test.ts} +27 -27
  167. package/Tests/Server/Services/IpAllowlistSpoofing.test.ts +450 -0
  168. package/Tests/Server/Services/LogAggregationService.test.ts +235 -1
  169. package/Tests/Server/Services/MetricAggregationService.test.ts +231 -0
  170. package/Tests/Server/Services/MetricEntityMVKeyParity.test.ts +80 -29
  171. package/Tests/Server/Services/MetricServiceAggregate.test.ts +30 -30
  172. package/Tests/Server/Services/NetworkSiteService.test.ts +18 -3
  173. package/Tests/Server/Services/NotificationChannelEventCoverage.test.ts +1728 -0
  174. package/Tests/Server/Services/NotificationDeletionImpact.test.ts +2402 -0
  175. package/Tests/Server/Services/OnCallDutyPolicyExecutionLogTimelineGapFeed.test.ts +394 -0
  176. package/Tests/Server/Services/OnCallNotificationFallback.test.ts +1744 -0
  177. package/Tests/Server/Services/OnCallReadinessService.test.ts +4295 -0
  178. package/Tests/Server/Services/OnCallSetupReminder.test.ts +1272 -0
  179. package/Tests/Server/Services/OnCallWeeklyReadinessDigest.test.ts +1021 -0
  180. package/Tests/Server/Services/ProfileAggregationService.test.ts +296 -0
  181. package/Tests/Server/Services/SeverityCreationRuleBackfill.test.ts +1536 -0
  182. package/Tests/Server/Services/SeverityRuleBackfill.test.ts +1818 -0
  183. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +1845 -0
  184. package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +1394 -0
  185. package/Tests/Server/Services/UserNotificationRuleDefaultCreation.test.ts +1166 -0
  186. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1468 -0
  187. package/Tests/Server/Services/UserOnCallLogNoNotificationRules.test.ts +1457 -0
  188. package/Tests/Server/Types/Database/Permissions/AdminNotificationRuleAccess.test.ts +1546 -0
  189. package/Tests/Server/Types/Database/Permissions/CreateOwnershipScoping.test.ts +529 -0
  190. package/Tests/Server/Types/Database/Permissions/OwnerOnlyColumns.test.ts +1219 -0
  191. package/Tests/Server/Types/Database/Permissions/UserNotificationRuleScoping.test.ts +1089 -0
  192. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +2 -1
  193. package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +190 -0
  194. package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +44 -14
  195. package/Tests/Server/Types/Workflow/Components/Email.test.ts +151 -0
  196. package/Tests/Server/Types/Workflow/Components/IfElse.test.ts +98 -0
  197. package/Tests/Server/Types/Workflow/Components/JavaScript.test.ts +51 -0
  198. package/Tests/Server/Utils/AI/AIMetaTools.test.ts +586 -0
  199. package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +582 -0
  200. package/Tests/Server/Utils/AI/ChatAgentRunner.test.ts +726 -0
  201. package/Tests/Server/Utils/AI/IncidentToolsFilters.test.ts +315 -0
  202. package/Tests/Server/Utils/AI/LLMServiceStopReason.test.ts +314 -0
  203. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +26 -3
  204. package/Tests/Server/Utils/AI/NoteWriteTools.test.ts +268 -0
  205. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +169 -0
  206. package/Tests/Server/Utils/AI/OnCallTools.test.ts +664 -0
  207. package/Tests/Server/Utils/AI/RunbookTools.test.ts +325 -0
  208. package/Tests/Server/Utils/AI/SloTools.test.ts +306 -0
  209. package/Tests/Server/Utils/AI/StatusPageTools.test.ts +391 -0
  210. package/Tests/Server/Utils/AI/TeamTools.test.ts +257 -0
  211. package/Tests/Server/Utils/AI/TimelineTools.test.ts +472 -0
  212. package/Tests/Server/Utils/AI/WorkflowProbeTools.test.ts +428 -0
  213. package/Tests/Server/Utils/ClientIp.test.ts +438 -0
  214. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +171 -0
  215. package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +383 -0
  216. package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +23 -25
  217. package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +6 -0
  218. package/Tests/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.test.ts +307 -0
  219. package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +468 -0
  220. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorTelemetryDeepLinks.test.ts +460 -0
  221. package/Tests/Server/Utils/ResponseRateLimitStatusCodes.test.ts +137 -0
  222. package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +40 -8
  223. package/Tests/Server/Utils/SSRFProtectionUserInfo.test.ts +351 -0
  224. package/Tests/Server/Utils/Telemetry/EntityRegistryRetirement.test.ts +531 -0
  225. package/Tests/Server/Utils/Telemetry/InventoryEntityRegistry.test.ts +15 -15
  226. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +356 -39
  227. package/Tests/Types/IP/IP.test.ts +263 -0
  228. package/Tests/Types/IP/IPWhitelist.test.ts +197 -0
  229. package/Tests/Types/IP/IPv6.test.ts +12 -1
  230. package/Tests/Types/Monitor/SnmpOid.test.ts +64 -0
  231. package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +110 -0
  232. package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeAudit.test.ts +106 -0
  233. package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeDifferential.test.ts +511 -0
  234. package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageEndToEnd.test.ts +489 -0
  235. package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageGapTolerance.test.ts +479 -0
  236. package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageState.test.ts +822 -0
  237. package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +6 -6
  238. package/Tests/Types/Workflow/BaseModelComponents.test.ts +429 -0
  239. package/Tests/Types/Workflow/Components/BaseModel.test.ts +225 -0
  240. package/Tests/Types/Workflow/IntegrationCredentialMetadata.test.ts +100 -0
  241. package/Tests/Types/Workflow/TemplateSyntax.test.ts +112 -0
  242. package/Tests/Types/Workflow/Templates.test.ts +916 -101
  243. package/Tests/UI/Components/ActiveFilterChipsOpenRoute.test.tsx +82 -0
  244. package/Tests/UI/Components/ComponentsModal.test.tsx +564 -7
  245. package/Tests/UI/Components/KeyboardShortcut.test.tsx +95 -0
  246. package/Tests/UI/Components/LogDetailsPanelCrossSignal.test.tsx +448 -0
  247. package/Tests/UI/Components/LogsTableCrossLinks.test.tsx +263 -0
  248. package/Tests/UI/Components/PendingProjectInvitations.test.tsx +913 -0
  249. package/Tests/UI/Components/SimpleLogViewer.test.tsx +228 -0
  250. package/Tests/UI/Components/TableRowSelectability.test.tsx +312 -0
  251. package/Tests/UI/Components/Workflow/GraphLint.test.ts +72 -0
  252. package/Tests/UI/Components/Workflow/GraphLintSummary.test.ts +755 -0
  253. package/Tests/UI/Components/Workflow/ModelColumnEditor.test.ts +242 -7
  254. package/Tests/UI/Components/Workflow/ModelColumnEditorServerContract.test.ts +15 -7
  255. package/Tests/UI/Components/Workflow/ModelSchema.test.ts +242 -28
  256. package/Tests/UI/Components/Workflow/RunStatusWatcher.test.ts +59 -1
  257. package/Tests/UI/Components/Workflow/StepTraceViewer.test.tsx +256 -0
  258. package/Tests/UI/Components/Workflow/UseRunWatch.test.tsx +665 -0
  259. package/Tests/UI/Components/Workflow/WorkflowIssuesModal.test.tsx +485 -0
  260. package/Tests/UI/Components/Workflow/WorkflowLogModal.test.tsx +478 -0
  261. package/Tests/UI/Components/Workflow/WorkflowStatusBar.test.tsx +379 -0
  262. package/Tests/UI/EsbuildConfig.test.ts +607 -0
  263. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +5 -0
  264. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +11 -4
  265. package/Tests/UI/Utils/ModelAPICreateMiscData.test.ts +94 -0
  266. package/Tests/UI/Utils/Platform.test.ts +147 -0
  267. package/Tests/UI/Utils/ProjectInvitationDisplay.test.ts +357 -0
  268. package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +198 -0
  269. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +487 -0
  270. package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +698 -0
  271. package/Tests/__mocks__/bullmq.js +55 -0
  272. package/Types/AI/AIChatMessageStatus.ts +8 -1
  273. package/Types/AI/AIChatTypes.ts +12 -0
  274. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +88 -0
  275. package/Types/Exception/ExceptionCode.ts +2 -0
  276. package/Types/Exception/ServiceUnavailableException.ts +8 -0
  277. package/Types/Exception/TooManyRequestsException.ts +8 -0
  278. package/Types/IP/IP.ts +93 -47
  279. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +49 -3
  280. package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +55 -0
  281. package/Types/OnCallDutyPolicy/Layer.ts +203 -149
  282. package/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.ts +13 -0
  283. package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +155 -10
  284. package/Types/Permission.ts +193 -0
  285. package/Types/Telemetry/EntityRelationshipType.ts +1 -1
  286. package/Types/Telemetry/EntitySource.ts +1 -1
  287. package/Types/Telemetry/EntityType.ts +1 -1
  288. package/Types/Telemetry/EntityTypeGroups.ts +1 -1
  289. package/Types/Workflow/Components/BaseModel.ts +75 -29
  290. package/Types/Workflow/Components/Discord.ts +1 -0
  291. package/Types/Workflow/Components/Email.ts +12 -3
  292. package/Types/Workflow/Components/JavaScript.ts +7 -0
  293. package/Types/Workflow/Components/MicrosoftTeams.ts +3 -2
  294. package/Types/Workflow/Components/Slack.ts +1 -0
  295. package/Types/Workflow/Components/Telegram.ts +1 -0
  296. package/Types/Workflow/TemplateSyntax.ts +44 -0
  297. package/Types/Workflow/Templates.ts +2097 -45
  298. package/UI/Components/Calendar/Calendar.css +43 -0
  299. package/UI/Components/Calendar/Calendar.tsx +8 -0
  300. package/UI/Components/Card/Card.tsx +2 -2
  301. package/UI/Components/Checkbox/Checkbox.tsx +16 -0
  302. package/UI/Components/Dictionary/Dictionary.tsx +48 -9
  303. package/UI/Components/FormModal/BasicFormModal.tsx +2 -1
  304. package/UI/Components/Header/HeaderIconDropdownButton.tsx +53 -3
  305. package/UI/Components/Input/Input.tsx +1 -0
  306. package/UI/Components/KeyboardShortcut/KeyboardKey.ts +185 -0
  307. package/UI/Components/KeyboardShortcut/KeyboardShortcut.tsx +87 -0
  308. package/UI/Components/LogsViewer/LogsViewer.tsx +28 -0
  309. package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +31 -0
  310. package/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.tsx +18 -18
  311. package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +363 -14
  312. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +11 -0
  313. package/UI/Components/LogsViewer/components/LogsTable.tsx +155 -12
  314. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +29 -0
  315. package/UI/Components/LogsViewer/types.ts +23 -0
  316. package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +9 -2
  317. package/UI/Components/Navbar/NavBarMenuModal.tsx +15 -30
  318. package/UI/Components/ProjectInvitations/PendingProjectInvitations.tsx +442 -0
  319. package/UI/Components/SimpleLogViewer/SimpleLogViewer.tsx +23 -1
  320. package/UI/Components/Table/Table.tsx +49 -16
  321. package/UI/Components/Table/TableBody.tsx +53 -28
  322. package/UI/Components/Table/TableHeader.tsx +13 -0
  323. package/UI/Components/Table/TableRow.tsx +58 -26
  324. package/UI/Components/Workflow/ArgumentsForm.tsx +155 -9
  325. package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +26 -0
  326. package/UI/Components/Workflow/ComponentSettingsModal.tsx +10 -1
  327. package/UI/Components/Workflow/ComponentValuePickerModal.tsx +135 -7
  328. package/UI/Components/Workflow/ComponentsModal.tsx +116 -22
  329. package/UI/Components/Workflow/DocumentationViewer.tsx +59 -9
  330. package/UI/Components/Workflow/GraphLint.ts +42 -5
  331. package/UI/Components/Workflow/GraphLintSummary.ts +390 -0
  332. package/UI/Components/Workflow/ModelColumnEditor.tsx +154 -22
  333. package/UI/Components/Workflow/ModelSchema.ts +115 -33
  334. package/UI/Components/Workflow/RunStatusWatcher.ts +1 -1
  335. package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
  336. package/UI/Components/Workflow/UseRunWatch.ts +212 -0
  337. package/UI/Components/Workflow/VariableModal.tsx +6 -2
  338. package/UI/Components/Workflow/Workflow.tsx +49 -3
  339. package/UI/Components/Workflow/WorkflowIssuesModal.tsx +255 -0
  340. package/UI/Components/Workflow/WorkflowLogModal.tsx +128 -0
  341. package/UI/Components/Workflow/WorkflowStatusBar.tsx +224 -0
  342. package/UI/Utils/AIChatExport/ConversationMarkdown.ts +10 -0
  343. package/UI/Utils/ModelAPI/ModelAPI.ts +7 -1
  344. package/UI/Utils/Platform.ts +149 -0
  345. package/UI/Utils/ProjectInvitationDisplay.ts +118 -0
  346. package/UI/esbuild-config.js +22 -1
  347. package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +187 -0
  348. package/Utils/Monitor/NetworkTopologyUtil.ts +888 -164
  349. package/Utils/Telemetry/CrossSignalScope.ts +502 -0
  350. package/Utils/Telemetry/EntityKey.ts +5 -5
  351. package/Utils/Telemetry/EntityRelationship.ts +1 -1
  352. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +1 -1
  353. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +1 -1
  354. package/build/dist/Models/DatabaseModels/AIConversation.js +32 -0
  355. package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
  356. package/build/dist/Models/DatabaseModels/AIConversationMessage.js +42 -0
  357. package/build/dist/Models/DatabaseModels/AIConversationMessage.js.map +1 -1
  358. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +28 -0
  359. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
  360. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +29 -0
  361. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
  362. package/build/dist/Models/DatabaseModels/Index.js +12 -4
  363. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  364. package/build/dist/Models/DatabaseModels/{TelemetryEntity.js → InventoryItem.js} +167 -31
  365. package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -0
  366. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +454 -0
  367. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js.map +1 -0
  368. package/build/dist/Models/DatabaseModels/{TelemetryEntityRelationship.js → InventoryItemRelationship.js} +27 -27
  369. package/build/dist/Models/DatabaseModels/InventoryItemRelationship.js.map +1 -0
  370. package/build/dist/Models/DatabaseModels/NetworkDevice.js +141 -0
  371. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  372. package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js +719 -0
  373. package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js.map +1 -0
  374. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +475 -0
  375. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -0
  376. package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js +446 -0
  377. package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js.map +1 -0
  378. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js +9 -0
  379. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js.map +1 -1
  380. package/build/dist/Models/DatabaseModels/Project.js +80 -0
  381. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  382. package/build/dist/Models/DatabaseModels/UserCall.js +46 -2
  383. package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
  384. package/build/dist/Models/DatabaseModels/UserEmail.js +48 -2
  385. package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
  386. package/build/dist/Models/DatabaseModels/UserNotificationRule.js +424 -55
  387. package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
  388. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +24 -2
  389. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  390. package/build/dist/Models/DatabaseModels/UserPush.js +51 -1
  391. package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
  392. package/build/dist/Models/DatabaseModels/UserSMS.js +47 -2
  393. package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
  394. package/build/dist/Models/DatabaseModels/UserTelegram.js +65 -3
  395. package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
  396. package/build/dist/Models/DatabaseModels/UserWebhook.js +56 -2
  397. package/build/dist/Models/DatabaseModels/UserWebhook.js.map +1 -1
  398. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +45 -2
  399. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
  400. package/build/dist/Models/DatabaseModels/WorkflowVariable.js +12 -0
  401. package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
  402. package/build/dist/Server/API/AIChatAPI.js +237 -1
  403. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  404. package/build/dist/Server/API/DashboardAPI.js +165 -13
  405. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  406. package/build/dist/Server/API/OnCallReadinessAPI.js +599 -0
  407. package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -0
  408. package/build/dist/Server/API/TeamComplianceAPI.js +68 -9
  409. package/build/dist/Server/API/TeamComplianceAPI.js.map +1 -1
  410. package/build/dist/Server/API/TelemetryAPI.js +129 -18
  411. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  412. package/build/dist/Server/EnvironmentConfig.js +45 -0
  413. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  414. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +22 -0
  415. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
  416. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js +4 -4
  417. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js +18 -0
  418. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js.map +1 -0
  419. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js +39 -0
  420. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js.map +1 -0
  421. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js +38 -0
  422. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js.map +1 -0
  423. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js +22 -0
  424. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js.map +1 -0
  425. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js +150 -0
  426. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js.map +1 -0
  427. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js +57 -0
  428. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js.map +1 -0
  429. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js +69 -0
  430. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js.map +1 -0
  431. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js +32 -0
  432. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js.map +1 -0
  433. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js +26 -0
  434. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js.map +1 -0
  435. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js +48 -0
  436. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js.map +1 -0
  437. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +20 -0
  438. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  439. package/build/dist/Server/Infrastructure/Queue.js +72 -13
  440. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  441. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js +399 -0
  442. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js.map +1 -0
  443. package/build/dist/Server/Services/AIService.js +1 -0
  444. package/build/dist/Server/Services/AIService.js.map +1 -1
  445. package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js +24 -3
  446. package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js.map +1 -1
  447. package/build/dist/Server/Services/AlertSeverityService.js +54 -0
  448. package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
  449. package/build/dist/Server/Services/DashboardService.js +10 -9
  450. package/build/dist/Server/Services/DashboardService.js.map +1 -1
  451. package/build/dist/Server/Services/DatabaseService.js +24 -2
  452. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  453. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +24 -3
  454. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
  455. package/build/dist/Server/Services/IncidentSeverityService.js +67 -0
  456. package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
  457. package/build/dist/Server/Services/Index.js +12 -4
  458. package/build/dist/Server/Services/Index.js.map +1 -1
  459. package/build/dist/Server/Services/InventoryItemCustomFieldService.js +9 -0
  460. package/build/dist/Server/Services/InventoryItemCustomFieldService.js.map +1 -0
  461. package/build/dist/Server/Services/{TelemetryEntityRelationshipService.js → InventoryItemRelationshipService.js} +6 -6
  462. package/build/dist/Server/Services/InventoryItemRelationshipService.js.map +1 -0
  463. package/build/dist/Server/Services/{TelemetryEntityService.js → InventoryItemService.js} +68 -23
  464. package/build/dist/Server/Services/InventoryItemService.js.map +1 -0
  465. package/build/dist/Server/Services/LogAggregationService.js +27 -8
  466. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  467. package/build/dist/Server/Services/MetricAggregationService.js +80 -0
  468. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  469. package/build/dist/Server/Services/MetricService.js +6 -6
  470. package/build/dist/Server/Services/MetricService.js.map +1 -1
  471. package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js +9 -0
  472. package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js.map +1 -0
  473. package/build/dist/Server/Services/NetworkDeviceLinkService.js +71 -0
  474. package/build/dist/Server/Services/NetworkDeviceLinkService.js.map +1 -0
  475. package/build/dist/Server/Services/NetworkDeviceService.js +113 -0
  476. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  477. package/build/dist/Server/Services/NetworkSiteService.js +53 -13
  478. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  479. package/build/dist/Server/Services/NetworkTopologySuppressionService.js +85 -0
  480. package/build/dist/Server/Services/NetworkTopologySuppressionService.js.map +1 -0
  481. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +48 -32
  482. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  483. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +8 -0
  484. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  485. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +51 -12
  486. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  487. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +57 -13
  488. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  489. package/build/dist/Server/Services/OnCallNotificationAlertingService.js +548 -0
  490. package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -0
  491. package/build/dist/Server/Services/OnCallReadinessService.js +1961 -0
  492. package/build/dist/Server/Services/OnCallReadinessService.js.map +1 -0
  493. package/build/dist/Server/Services/OnCallSetupReminderService.js +738 -0
  494. package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -0
  495. package/build/dist/Server/Services/ProfileAggregationService.js +68 -4
  496. package/build/dist/Server/Services/ProfileAggregationService.js.map +1 -1
  497. package/build/dist/Server/Services/StatusPageService.js +11 -10
  498. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  499. package/build/dist/Server/Services/TeamComplianceService.js +312 -160
  500. package/build/dist/Server/Services/TeamComplianceService.js.map +1 -1
  501. package/build/dist/Server/Services/UserCallService.js +24 -1
  502. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  503. package/build/dist/Server/Services/UserEmailService.js +24 -1
  504. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  505. package/build/dist/Server/Services/UserNotificationRuleAdminService.js +858 -0
  506. package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -0
  507. package/build/dist/Server/Services/UserNotificationRuleService.js +2830 -175
  508. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  509. package/build/dist/Server/Services/UserOnCallLogService.js +488 -43
  510. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  511. package/build/dist/Server/Services/UserPushService.js +26 -0
  512. package/build/dist/Server/Services/UserPushService.js.map +1 -1
  513. package/build/dist/Server/Services/UserService.js +10 -0
  514. package/build/dist/Server/Services/UserService.js.map +1 -1
  515. package/build/dist/Server/Services/UserSmsService.js +24 -1
  516. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  517. package/build/dist/Server/Services/UserTelegramService.js +22 -1
  518. package/build/dist/Server/Services/UserTelegramService.js.map +1 -1
  519. package/build/dist/Server/Services/UserWebhookService.js +25 -1
  520. package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
  521. package/build/dist/Server/Services/UserWhatsAppService.js +22 -1
  522. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
  523. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +12 -1
  524. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  525. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +126 -0
  526. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  527. package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js +254 -0
  528. package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js.map +1 -0
  529. package/build/dist/Server/Types/Database/Permissions/QueryPermission.js +47 -2
  530. package/build/dist/Server/Types/Database/Permissions/QueryPermission.js.map +1 -1
  531. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +7 -0
  532. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
  533. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +1 -1
  534. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  535. package/build/dist/Server/Types/Workflow/Components/API/Get.js +1 -1
  536. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  537. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +1 -1
  538. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  539. package/build/dist/Server/Types/Workflow/Components/API/Post.js +1 -1
  540. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  541. package/build/dist/Server/Types/Workflow/Components/API/Put.js +1 -1
  542. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  543. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +21 -5
  544. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
  545. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +14 -10
  546. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
  547. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +31 -0
  548. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -1
  549. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +3 -9
  550. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
  551. package/build/dist/Server/Types/Workflow/Components/Email.js +15 -4
  552. package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
  553. package/build/dist/Server/Types/Workflow/Components/JavaScript.js +7 -2
  554. package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
  555. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +1 -1
  556. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
  557. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +514 -56
  558. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  559. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +20 -3
  560. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  561. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +19 -6
  562. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  563. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +7 -0
  564. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  565. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js +2 -2
  566. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -1
  567. package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js +692 -0
  568. package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js.map +1 -0
  569. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +148 -12
  570. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
  571. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +157 -10
  572. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
  573. package/build/dist/Server/Utils/AI/Toolbox/Index.js +37 -0
  574. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  575. package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js +259 -14
  576. package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js.map +1 -1
  577. package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js +235 -0
  578. package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js.map +1 -0
  579. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +1000 -0
  580. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -0
  581. package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js +356 -0
  582. package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js.map +1 -0
  583. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +394 -0
  584. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -0
  585. package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js +465 -0
  586. package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js.map +1 -0
  587. package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js +280 -0
  588. package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js.map +1 -0
  589. package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +527 -0
  590. package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -0
  591. package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js +548 -0
  592. package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js.map +1 -0
  593. package/build/dist/Server/Utils/ClientIp.js +137 -0
  594. package/build/dist/Server/Utils/ClientIp.js.map +1 -0
  595. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +38 -0
  596. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
  597. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +89 -0
  598. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -0
  599. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +77 -0
  600. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -0
  601. package/build/dist/Server/Utils/Express.js +12 -12
  602. package/build/dist/Server/Utils/Express.js.map +1 -1
  603. package/build/dist/Server/Utils/LLM/LLMService.js +70 -7
  604. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  605. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +121 -11
  606. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  607. package/build/dist/Server/Utils/SSRFProtection.js +82 -21
  608. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  609. package/build/dist/Server/Utils/StartServer.js +12 -4
  610. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  611. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +165 -18
  612. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  613. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +11 -11
  614. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
  615. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +122 -47
  616. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  617. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +7 -3
  618. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  619. package/build/dist/Types/AI/AIChatMessageStatus.js +8 -1
  620. package/build/dist/Types/AI/AIChatMessageStatus.js.map +1 -1
  621. package/build/dist/Types/AI/AIChatTypes.js +12 -0
  622. package/build/dist/Types/AI/AIChatTypes.js.map +1 -1
  623. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +60 -0
  624. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -0
  625. package/build/dist/Types/Exception/ExceptionCode.js +2 -0
  626. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  627. package/build/dist/Types/Exception/ServiceUnavailableException.js +8 -0
  628. package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -0
  629. package/build/dist/Types/Exception/TooManyRequestsException.js +8 -0
  630. package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -0
  631. package/build/dist/Types/IP/IP.js +87 -43
  632. package/build/dist/Types/IP/IP.js.map +1 -1
  633. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +50 -0
  634. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -0
  635. package/build/dist/Types/OnCallDutyPolicy/Layer.js +186 -123
  636. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  637. package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js +13 -0
  638. package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js.map +1 -1
  639. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +105 -11
  640. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
  641. package/build/dist/Types/Permission.js +174 -0
  642. package/build/dist/Types/Permission.js.map +1 -1
  643. package/build/dist/Types/Telemetry/EntityRelationshipType.js +1 -1
  644. package/build/dist/Types/Telemetry/EntitySource.js +1 -1
  645. package/build/dist/Types/Telemetry/EntityType.js +1 -1
  646. package/build/dist/Types/Telemetry/EntityTypeGroups.js +1 -1
  647. package/build/dist/Types/Telemetry/EntityTypeGroups.js.map +1 -1
  648. package/build/dist/Types/Workflow/Components/BaseModel.js +66 -28
  649. package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
  650. package/build/dist/Types/Workflow/Components/Discord.js +1 -0
  651. package/build/dist/Types/Workflow/Components/Discord.js.map +1 -1
  652. package/build/dist/Types/Workflow/Components/Email.js +12 -3
  653. package/build/dist/Types/Workflow/Components/Email.js.map +1 -1
  654. package/build/dist/Types/Workflow/Components/JavaScript.js +7 -0
  655. package/build/dist/Types/Workflow/Components/JavaScript.js.map +1 -1
  656. package/build/dist/Types/Workflow/Components/MicrosoftTeams.js +3 -2
  657. package/build/dist/Types/Workflow/Components/MicrosoftTeams.js.map +1 -1
  658. package/build/dist/Types/Workflow/Components/Slack.js +1 -0
  659. package/build/dist/Types/Workflow/Components/Slack.js.map +1 -1
  660. package/build/dist/Types/Workflow/Components/Telegram.js +1 -0
  661. package/build/dist/Types/Workflow/Components/Telegram.js.map +1 -1
  662. package/build/dist/Types/Workflow/TemplateSyntax.js +12 -0
  663. package/build/dist/Types/Workflow/TemplateSyntax.js.map +1 -1
  664. package/build/dist/Types/Workflow/Templates.js +1931 -38
  665. package/build/dist/Types/Workflow/Templates.js.map +1 -1
  666. package/build/dist/UI/Components/Calendar/Calendar.js +1 -1
  667. package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
  668. package/build/dist/UI/Components/Checkbox/Checkbox.js +1 -1
  669. package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
  670. package/build/dist/UI/Components/Dictionary/Dictionary.js +25 -11
  671. package/build/dist/UI/Components/Dictionary/Dictionary.js.map +1 -1
  672. package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
  673. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +27 -4
  674. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  675. package/build/dist/UI/Components/Input/Input.js +1 -0
  676. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  677. package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js +163 -0
  678. package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js.map +1 -0
  679. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js +47 -0
  680. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js.map +1 -0
  681. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +4 -4
  682. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  683. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +11 -1
  684. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
  685. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js +10 -8
  686. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js.map +1 -1
  687. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +227 -14
  688. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
  689. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +5 -0
  690. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  691. package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +69 -5
  692. package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
  693. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +8 -0
  694. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  695. package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
  696. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +9 -2
  697. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
  698. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +8 -21
  699. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  700. package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js +251 -0
  701. package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js.map +1 -0
  702. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js +9 -2
  703. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js.map +1 -1
  704. package/build/dist/UI/Components/Table/Table.js +27 -15
  705. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  706. package/build/dist/UI/Components/Table/TableBody.js +24 -18
  707. package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
  708. package/build/dist/UI/Components/Table/TableHeader.js +9 -1
  709. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  710. package/build/dist/UI/Components/Table/TableRow.js +29 -21
  711. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  712. package/build/dist/UI/Components/Workflow/ArgumentsForm.js +130 -12
  713. package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
  714. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +10 -1
  715. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
  716. package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +4 -4
  717. package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
  718. package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js +57 -7
  719. package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js.map +1 -1
  720. package/build/dist/UI/Components/Workflow/ComponentsModal.js +53 -18
  721. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  722. package/build/dist/UI/Components/Workflow/DocumentationViewer.js +19 -6
  723. package/build/dist/UI/Components/Workflow/DocumentationViewer.js.map +1 -1
  724. package/build/dist/UI/Components/Workflow/GraphLint.js +33 -4
  725. package/build/dist/UI/Components/Workflow/GraphLint.js.map +1 -1
  726. package/build/dist/UI/Components/Workflow/GraphLintSummary.js +231 -0
  727. package/build/dist/UI/Components/Workflow/GraphLintSummary.js.map +1 -0
  728. package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +116 -21
  729. package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -1
  730. package/build/dist/UI/Components/Workflow/ModelSchema.js +72 -34
  731. package/build/dist/UI/Components/Workflow/ModelSchema.js.map +1 -1
  732. package/build/dist/UI/Components/Workflow/RunStatusWatcher.js +1 -1
  733. package/build/dist/UI/Components/Workflow/RunStatusWatcher.js.map +1 -1
  734. package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
  735. package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
  736. package/build/dist/UI/Components/Workflow/UseRunWatch.js +123 -0
  737. package/build/dist/UI/Components/Workflow/UseRunWatch.js.map +1 -0
  738. package/build/dist/UI/Components/Workflow/VariableModal.js +3 -2
  739. package/build/dist/UI/Components/Workflow/VariableModal.js.map +1 -1
  740. package/build/dist/UI/Components/Workflow/Workflow.js +41 -1
  741. package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
  742. package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js +99 -0
  743. package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js.map +1 -0
  744. package/build/dist/UI/Components/Workflow/WorkflowLogModal.js +56 -0
  745. package/build/dist/UI/Components/Workflow/WorkflowLogModal.js.map +1 -0
  746. package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js +92 -0
  747. package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js.map +1 -0
  748. package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js +9 -0
  749. package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js.map +1 -1
  750. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +1 -1
  751. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  752. package/build/dist/UI/Utils/Platform.js +118 -0
  753. package/build/dist/UI/Utils/Platform.js.map +1 -0
  754. package/build/dist/UI/Utils/ProjectInvitationDisplay.js +106 -0
  755. package/build/dist/UI/Utils/ProjectInvitationDisplay.js.map +1 -0
  756. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +108 -0
  757. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -0
  758. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +642 -136
  759. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  760. package/build/dist/Utils/Telemetry/CrossSignalScope.js +328 -0
  761. package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -0
  762. package/build/dist/Utils/Telemetry/EntityKey.js +5 -5
  763. package/build/dist/Utils/Telemetry/EntityRelationship.js +1 -1
  764. package/jest.config.json +1 -0
  765. package/package.json +1 -1
  766. package/build/dist/Models/DatabaseModels/TelemetryEntity.js.map +0 -1
  767. package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js.map +0 -1
  768. package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +0 -1
  769. package/build/dist/Server/Services/TelemetryEntityService.js.map +0 -1
@@ -10,15 +10,35 @@
10
10
  * argument is "value" (not "log-message"), the Schedule trigger's is
11
11
  * "schedule" (not "schedule-at"), the Manual trigger leaves by "success" and
12
12
  * the Schedule trigger by "execute" (neither is "out").
13
+ *
14
+ * Two things here are load-bearing and easy to get wrong when extending this
15
+ * file:
16
+ *
17
+ * 1. The registry is the MERGED one (loadComponentsAndCategories), not the
18
+ * static Components array. Templates use database-model components like
19
+ * `incident-on-create`, which only exist in the merged registry. Against
20
+ * the static array those nodes get `metadata: undefined`, the linter's
21
+ * isRealNode silently drops them, and the lint test passes on a graph it
22
+ * never checked.
23
+ *
24
+ * 2. References are classified with parseReferencePath rather than by
25
+ * assuming every {{...}} is local.components.*. Templates now also carry
26
+ * {{local.variables.*}}, and a test that assumes otherwise fails on
27
+ * correct templates.
13
28
  */
14
29
 
15
30
  import {
31
+ WORKFLOW_TEMPLATE_VARIABLE_NAME_REGEX,
16
32
  WorkflowTemplate,
33
+ WorkflowTemplateCategories,
34
+ WorkflowTemplateCategory,
35
+ WorkflowTemplateVariable,
17
36
  buildGraphForTemplate,
18
37
  getTemplateGraphSpec,
38
+ getWorkflowTemplate,
19
39
  getWorkflowTemplates,
40
+ getWorkflowTemplatesByCategory,
20
41
  } from "../../../Types/Workflow/Templates";
21
- import Components from "../../../Types/Workflow/Components";
22
42
  import ComponentMetadata, {
23
43
  Argument,
24
44
  ComponentType,
@@ -26,7 +46,8 @@ import ComponentMetadata, {
26
46
  Port,
27
47
  ReturnValue,
28
48
  } from "../../../Types/Workflow/Component";
29
- import { JSONObject } from "../../../Types/JSON";
49
+ import { JSONObject, JSONValue } from "../../../Types/JSON";
50
+ import IconProp from "../../../Types/Icon/IconProp";
30
51
  import {
31
52
  LintGraphEdge,
32
53
  LintGraphNode,
@@ -35,10 +56,28 @@ import {
35
56
  WorkflowLintSeverity,
36
57
  lintWorkflowGraph,
37
58
  } from "../../../UI/Components/Workflow/GraphLint";
59
+ import { loadComponentsAndCategories } from "../../../UI/Components/Workflow/Utils";
60
+ import {
61
+ ParsedReferencePath,
62
+ ReferenceRootType,
63
+ TemplateExpression,
64
+ TemplateExpressionKind,
65
+ parseReferencePath,
66
+ parseTemplateExpressions,
67
+ } from "../../../Types/Workflow/TemplateSyntax";
38
68
  import { describe, expect, test } from "@jest/globals";
69
+ import ComponentID from "../../../Types/Workflow/ComponentID";
70
+ import CronTab from "../../../Utils/CronTab";
39
71
 
40
72
  const templates: Array<WorkflowTemplate> = getWorkflowTemplates();
41
73
 
74
+ /*
75
+ * The same registry the builder loads: static components plus one set per
76
+ * database model. Built once — it walks every entity in the models index.
77
+ */
78
+ const registry: Array<ComponentMetadata> =
79
+ loadComponentsAndCategories().components;
80
+
42
81
  type FindMetadataFunction = (
43
82
  metadataId: string,
44
83
  ) => ComponentMetadata | undefined;
@@ -46,7 +85,7 @@ type FindMetadataFunction = (
46
85
  const findMetadata: FindMetadataFunction = (
47
86
  metadataId: string,
48
87
  ): ComponentMetadata | undefined => {
49
- return Components.find((component: ComponentMetadata) => {
88
+ return registry.find((component: ComponentMetadata) => {
50
89
  return component.id === metadataId;
51
90
  });
52
91
  };
@@ -60,6 +99,30 @@ const generateId: GenerateIdFunction = (): string => {
60
99
  return `generated-${idCounter}`;
61
100
  };
62
101
 
102
+ interface TemplateNodeSpec {
103
+ componentId: string;
104
+ metadataId: string;
105
+ componentType: ComponentType;
106
+ args?: JSONObject | undefined;
107
+ }
108
+
109
+ interface TemplateEdgeSpec {
110
+ fromComponentId: string;
111
+ toComponentId: string;
112
+ fromPort: string;
113
+ }
114
+
115
+ interface TemplateSpec {
116
+ nodes: Array<TemplateNodeSpec>;
117
+ edges: Array<TemplateEdgeSpec>;
118
+ }
119
+
120
+ type SpecOfFunction = (templateId: string) => TemplateSpec;
121
+
122
+ const specOf: SpecOfFunction = (templateId: string): TemplateSpec => {
123
+ return getTemplateGraphSpec(templateId) as unknown as TemplateSpec;
124
+ };
125
+
63
126
  /**
64
127
  * Build a template's graph and hydrate each node with its real metadata, the
65
128
  * way the builder does on load. Without the metadata the linter cannot check
@@ -110,9 +173,128 @@ const hydrate: HydrateFunction = (
110
173
  return { nodes: nodes, edges: edges };
111
174
  };
112
175
 
176
+ /** Every string an argument holds, including strings nested inside JSON objects. */
177
+ type CollectStringsFunction = (value: JSONValue | undefined) => Array<string>;
178
+
179
+ const collectStrings: CollectStringsFunction = (
180
+ value: JSONValue | undefined,
181
+ ): Array<string> => {
182
+ if (typeof value === "string") {
183
+ return [value];
184
+ }
185
+
186
+ if (Array.isArray(value)) {
187
+ return value.flatMap((entry: JSONValue) => {
188
+ return collectStrings(entry);
189
+ });
190
+ }
191
+
192
+ if (value && typeof value === "object") {
193
+ return Object.values(value as JSONObject).flatMap((entry: JSONValue) => {
194
+ return collectStrings(entry);
195
+ });
196
+ }
197
+
198
+ return [];
199
+ };
200
+
201
+ interface TemplateReference {
202
+ /** The full {{...}} text. */
203
+ raw: string;
204
+ inner: string;
205
+ parsed: ParsedReferencePath;
206
+ /** The component id the argument lives on. */
207
+ onComponentId: string;
208
+ }
209
+
210
+ type ReferencesOfFunction = (templateId: string) => Array<TemplateReference>;
211
+
212
+ const referencesOf: ReferencesOfFunction = (
213
+ templateId: string,
214
+ ): Array<TemplateReference> => {
215
+ const spec: TemplateSpec = specOf(templateId);
216
+ const references: Array<TemplateReference> = [];
217
+
218
+ for (const node of spec.nodes) {
219
+ for (const value of Object.values(node.args || {})) {
220
+ for (const text of collectStrings(value as JSONValue)) {
221
+ const expressions: Array<TemplateExpression> =
222
+ parseTemplateExpressions(text);
223
+
224
+ for (const expression of expressions) {
225
+ if (expression.kind !== TemplateExpressionKind.Reference) {
226
+ continue;
227
+ }
228
+
229
+ references.push({
230
+ raw: expression.raw,
231
+ inner: expression.inner,
232
+ parsed: parseReferencePath(expression.inner),
233
+ onComponentId: node.componentId,
234
+ });
235
+ }
236
+ }
237
+ }
238
+ }
239
+
240
+ return references;
241
+ };
242
+
243
+ /**
244
+ * Whether a trigger's `select` argument actually asks for the field a
245
+ * reference reads. The runtime only hydrates what `select` names, so
246
+ * {{…returnValues.model.title}} against a select without `title` resolves to
247
+ * nothing — and an unresolved reference is not an error, it just ships the
248
+ * literal braces.
249
+ */
250
+ type SelectCoversFunction = (
251
+ select: JSONValue | undefined,
252
+ path: Array<string>,
253
+ ) => boolean;
254
+
255
+ const selectCovers: SelectCoversFunction = (
256
+ select: JSONValue | undefined,
257
+ path: Array<string>,
258
+ ): boolean => {
259
+ if (path.length === 0) {
260
+ return true;
261
+ }
262
+
263
+ /*
264
+ * ObjectID, Email, Phone and Date values are serialized for workflow storage
265
+ * as { _type, value }. Selecting the database column selects that wrapper;
266
+ * `.value` is a serialization detail rather than another database column.
267
+ */
268
+ if (path.length === 1 && path[0] === "value" && Boolean(select)) {
269
+ return true;
270
+ }
271
+
272
+ // The runtime always adds _id to the select it issues.
273
+ if (path.length === 1 && (path[0] === "_id" || path[0] === "id")) {
274
+ return true;
275
+ }
276
+
277
+ if (!select || typeof select !== "object" || Array.isArray(select)) {
278
+ return false;
279
+ }
280
+
281
+ const head: string = path[0] as string;
282
+ const branch: JSONValue | undefined = (select as JSONObject)[head];
283
+
284
+ if (branch === undefined) {
285
+ return false;
286
+ }
287
+
288
+ if (path.length === 1) {
289
+ return Boolean(branch);
290
+ }
291
+
292
+ return selectCovers(branch, path.slice(1));
293
+ };
294
+
113
295
  describe("workflow templates", () => {
114
- test("there is at least one", () => {
115
- expect(templates.length).toBeGreaterThan(0);
296
+ test("there are plenty to choose from", () => {
297
+ expect(templates.length).toBeGreaterThan(10);
116
298
  });
117
299
 
118
300
  test("each has a unique id", () => {
@@ -123,6 +305,20 @@ describe("workflow templates", () => {
123
305
  expect(new Set(ids).size).toBe(ids.length);
124
306
  });
125
307
 
308
+ test("each id is dash-cased, so it is safe in a URL and in a test name", () => {
309
+ for (const template of templates) {
310
+ expect(template.id).toMatch(/^[a-z0-9]+(-[a-z0-9]+)*$/);
311
+ }
312
+ });
313
+
314
+ test("each suggests a distinct workflow name", () => {
315
+ const names: Array<string> = templates.map((template: WorkflowTemplate) => {
316
+ return template.workflowName;
317
+ });
318
+
319
+ expect(new Set(names).size).toBe(names.length);
320
+ });
321
+
126
322
  test("each is described well enough to choose between them", () => {
127
323
  for (const template of templates) {
128
324
  expect(template.name.length).toBeGreaterThan(0);
@@ -133,35 +329,306 @@ describe("workflow templates", () => {
133
329
  }
134
330
  });
135
331
 
332
+ test("each belongs to a category the picker knows how to show", () => {
333
+ for (const template of templates) {
334
+ expect(WorkflowTemplateCategories).toContain(template.category);
335
+ }
336
+ });
337
+
338
+ test("each category in the picker has at least one template", () => {
339
+ for (const category of WorkflowTemplateCategories) {
340
+ expect(getWorkflowTemplatesByCategory(category).length).toBeGreaterThan(
341
+ 0,
342
+ );
343
+ }
344
+ });
345
+
346
+ test("grouping by category accounts for every template exactly once", () => {
347
+ const grouped: Array<WorkflowTemplate> = WorkflowTemplateCategories.flatMap(
348
+ (category: WorkflowTemplateCategory) => {
349
+ return getWorkflowTemplatesByCategory(category);
350
+ },
351
+ );
352
+
353
+ expect(grouped).toHaveLength(templates.length);
354
+ });
355
+
356
+ test("each has an icon that exists", () => {
357
+ const iconValues: Array<string> = Object.values(IconProp);
358
+
359
+ for (const template of templates) {
360
+ expect(iconValues).toContain(template.icon);
361
+ }
362
+ });
363
+
364
+ test("getWorkflowTemplate finds each one, and nothing else", () => {
365
+ for (const template of templates) {
366
+ expect(getWorkflowTemplate(template.id)?.name).toBe(template.name);
367
+ }
368
+
369
+ expect(getWorkflowTemplate("does-not-exist")).toBeNull();
370
+ });
371
+
136
372
  test("an unknown template id yields nothing rather than throwing", () => {
137
373
  expect(getTemplateGraphSpec("does-not-exist")).toBeNull();
138
374
  expect(buildGraphForTemplate("does-not-exist", generateId)).toBeNull();
139
375
  });
376
+
377
+ test("the public template carries no graph, so the picker cannot depend on one", () => {
378
+ for (const template of templates) {
379
+ expect((template as unknown as JSONObject)["graph"]).toBeUndefined();
380
+ }
381
+ });
382
+
383
+ /*
384
+ * Every field on WorkflowTemplate has to survive the trip out of the module.
385
+ * The accessor used to hand-enumerate its output fields, which silently
386
+ * dropped anything newly added — the picker would render a card with no icon
387
+ * and the wizard would show no variables step.
388
+ */
389
+ test("no declared field is dropped on the way out", () => {
390
+ for (const template of templates) {
391
+ expect(Object.keys(template).sort()).toEqual(
392
+ [
393
+ "category",
394
+ "description",
395
+ "icon",
396
+ "id",
397
+ "name",
398
+ "teaches",
399
+ "variables",
400
+ "workflowDescription",
401
+ "workflowName",
402
+ ].sort(),
403
+ );
404
+ }
405
+ });
406
+ });
407
+
408
+ describe("workflow template variables", () => {
409
+ test("names are usable in a reference path", () => {
410
+ for (const template of templates) {
411
+ for (const variable of template.variables) {
412
+ expect(variable.name).toMatch(WORKFLOW_TEMPLATE_VARIABLE_NAME_REGEX);
413
+ }
414
+ }
415
+ });
416
+
417
+ /*
418
+ * A dot is fatal specifically: VMUtil.deepFind splits the whole path on
419
+ * dots, so local.variables.slack.url looks for a variable called "slack".
420
+ */
421
+ test("no name contains a dot or whitespace", () => {
422
+ for (const template of templates) {
423
+ for (const variable of template.variables) {
424
+ expect(variable.name).not.toContain(".");
425
+ expect(variable.name).not.toMatch(/\s/);
426
+ }
427
+ }
428
+ });
429
+
430
+ test("names are unique within a template, because they become one row each", () => {
431
+ for (const template of templates) {
432
+ const names: Array<string> = template.variables.map(
433
+ (variable: WorkflowTemplateVariable) => {
434
+ return variable.name;
435
+ },
436
+ );
437
+
438
+ expect(new Set(names).size).toBe(names.length);
439
+ }
440
+ });
441
+
442
+ test("each is described well enough to fill in", () => {
443
+ for (const template of templates) {
444
+ for (const variable of template.variables) {
445
+ expect(variable.title.length).toBeGreaterThan(0);
446
+ expect(variable.description.length).toBeGreaterThan(0);
447
+ expect(variable.placeholder.length).toBeGreaterThan(0);
448
+ expect(typeof variable.required).toBe("boolean");
449
+ expect(typeof variable.isSecret).toBe("boolean");
450
+ }
451
+ }
452
+ });
453
+
454
+ /*
455
+ * A variable name is reused across templates on purpose (slackWebhookUrl
456
+ * appears in many), and each template is free to label and explain it in its
457
+ * own words — "URL to call" reads better on an hourly poll than "URL to
458
+ * check" does. Variables are workflow-scoped, so two templates never share a
459
+ * row, and nothing forces the wording to agree.
460
+ *
461
+ * What must NOT drift is the behaviour attached to the name. `required`
462
+ * decides whether a row is written at all, and `isSecret` decides whether
463
+ * the value is redacted from run logs. The same field being secret in one
464
+ * template and not in another is a bug, not a wording choice.
465
+ */
466
+ test("a name reused across templates behaves the same way", () => {
467
+ const byName: Map<string, { required: boolean; isSecret: boolean }> =
468
+ new Map();
469
+
470
+ for (const template of templates) {
471
+ for (const variable of template.variables) {
472
+ const behaviour: { required: boolean; isSecret: boolean } = {
473
+ required: variable.required,
474
+ isSecret: variable.isSecret,
475
+ };
476
+
477
+ const seen: { required: boolean; isSecret: boolean } | undefined =
478
+ byName.get(variable.name);
479
+
480
+ if (!seen) {
481
+ byName.set(variable.name, behaviour);
482
+ continue;
483
+ }
484
+
485
+ expect({ name: variable.name, ...behaviour }).toEqual({
486
+ name: variable.name,
487
+ ...seen,
488
+ });
489
+ }
490
+ }
491
+ });
492
+
493
+ test("secrets are the ones that should be secret", () => {
494
+ for (const template of templates) {
495
+ for (const variable of template.variables) {
496
+ if (!variable.isSecret) {
497
+ continue;
498
+ }
499
+
500
+ expect(variable.title.toLowerCase()).toMatch(
501
+ /url|token|password|key|secret/,
502
+ );
503
+ }
504
+ }
505
+ });
506
+ });
507
+
508
+ describe("workflow template runtime contracts", () => {
509
+ test("JavaScript transform receives the webhook body as an object-shaped whole argument", () => {
510
+ const javascriptNode: TemplateNodeSpec = specOf(
511
+ "javascript-transform",
512
+ ).nodes.find((node: TemplateNodeSpec) => {
513
+ return node.componentId === "javascript-1";
514
+ }) as TemplateNodeSpec;
515
+
516
+ expect(javascriptNode.args?.["arguments"]).toBe(
517
+ "{{local.components.webhook-1.returnValues.request-body}}",
518
+ );
519
+ expect(javascriptNode.args?.["code"] as string).toContain(
520
+ "const body = args || {};",
521
+ );
522
+ });
523
+
524
+ test("AI incident data stays in the protected context instead of the prompt", () => {
525
+ const aiNode: TemplateNodeSpec = specOf(
526
+ "incident-created-ai-summary",
527
+ ).nodes.find((node: TemplateNodeSpec) => {
528
+ return node.componentId === "ai-1";
529
+ }) as TemplateNodeSpec;
530
+
531
+ expect(aiNode.args?.["prompt"] as string).not.toContain("{{");
532
+ expect(aiNode.args?.["context"]).toBe(
533
+ "{{local.components.incident-on-create-1.returnValues.model}}",
534
+ );
535
+ });
536
+
537
+ test.each(["subscriber-added-slack", "subscriber-added-forward"])(
538
+ "%s waits for confirmation updates and normalizes the contact method",
539
+ (templateId: string) => {
540
+ const spec: TemplateSpec = specOf(templateId);
541
+ const trigger: TemplateNodeSpec = spec.nodes.find(
542
+ (node: TemplateNodeSpec) => {
543
+ return node.componentType === ComponentType.Trigger;
544
+ },
545
+ ) as TemplateNodeSpec;
546
+
547
+ expect(trigger.metadataId).toBe("status-page-subscriber-on-update");
548
+ expect(trigger.args?.["listen-on"]).toEqual({
549
+ isSubscriptionConfirmed: true,
550
+ });
551
+ expect(
552
+ spec.nodes.some((node: TemplateNodeSpec) => {
553
+ return node.componentId === "subscriber-normalize-1";
554
+ }),
555
+ ).toBe(true);
556
+ },
557
+ );
558
+
559
+ test("on-call notification follows real execution updates, not the scheduled create event", () => {
560
+ const trigger: TemplateNodeSpec = specOf(
561
+ "oncall-executed-slack",
562
+ ).nodes.find((node: TemplateNodeSpec) => {
563
+ return node.componentType === ComponentType.Trigger;
564
+ }) as TemplateNodeSpec;
565
+
566
+ expect(trigger.metadataId).toBe(
567
+ "on-call-duty-policy-execution-log-on-update",
568
+ );
569
+ expect(trigger.args?.["listen-on"]).toEqual({ status: true });
570
+ });
571
+
572
+ test("credential-bearing destination URLs are treated as secrets", () => {
573
+ for (const template of templates) {
574
+ for (const variable of template.variables) {
575
+ const normalizedVariableName: string = variable.name.toLowerCase();
576
+
577
+ if (
578
+ !["webhookurl", "forwardurl", "targeturl", "heartbeaturl"].some(
579
+ (secretUrlName: string): boolean => {
580
+ return normalizedVariableName.includes(secretUrlName);
581
+ },
582
+ )
583
+ ) {
584
+ continue;
585
+ }
586
+
587
+ expect({
588
+ template: template.id,
589
+ variable: variable.name,
590
+ isSecret: variable.isSecret,
591
+ }).toEqual({
592
+ template: template.id,
593
+ variable: variable.name,
594
+ isSecret: true,
595
+ });
596
+ }
597
+ }
598
+ });
140
599
  });
141
600
 
142
601
  describe.each(
143
602
  templates.map((template: WorkflowTemplate) => {
144
603
  return [template.id, template] as [string, WorkflowTemplate];
145
604
  }),
146
- )("template %s", (templateId: string) => {
605
+ )("template %s", (templateId: string, template: WorkflowTemplate) => {
147
606
  test("every component it uses exists in the registry", () => {
148
- const spec: { nodes: Array<{ metadataId: string }> } = getTemplateGraphSpec(
149
- templateId,
150
- ) as { nodes: Array<{ metadataId: string }> };
607
+ for (const node of specOf(templateId).nodes) {
608
+ expect({
609
+ metadataId: node.metadataId,
610
+ found: Boolean(findMetadata(node.metadataId)),
611
+ }).toEqual({ metadataId: node.metadataId, found: true });
612
+ }
613
+ });
151
614
 
152
- for (const node of spec.nodes) {
153
- expect(findMetadata(node.metadataId)).toBeDefined();
615
+ /*
616
+ * The builder throws BadDataException on load for a node whose metadataId is
617
+ * not in the registry, which breaks the whole page rather than one node. So
618
+ * a typo here does not degrade a template, it bricks it.
619
+ */
620
+ test("the node's declared componentType matches the registry's", () => {
621
+ for (const node of specOf(templateId).nodes) {
622
+ const metadata: ComponentMetadata = findMetadata(
623
+ node.metadataId,
624
+ ) as ComponentMetadata;
625
+
626
+ expect(node.componentType).toBe(metadata.componentType);
154
627
  }
155
628
  });
156
629
 
157
630
  test("every argument it sets is a real argument on that component", () => {
158
- const spec: {
159
- nodes: Array<{ metadataId: string; args?: JSONObject | undefined }>;
160
- } = getTemplateGraphSpec(templateId) as {
161
- nodes: Array<{ metadataId: string; args?: JSONObject | undefined }>;
162
- };
163
-
164
- for (const node of spec.nodes) {
631
+ for (const node of specOf(templateId).nodes) {
165
632
  const metadata: ComponentMetadata = findMetadata(
166
633
  node.metadataId,
167
634
  ) as ComponentMetadata;
@@ -173,7 +640,31 @@ describe.each(
173
640
  },
174
641
  );
175
642
 
176
- expect(argument).toBeDefined();
643
+ expect({
644
+ node: node.componentId,
645
+ argumentId: argumentId,
646
+ found: Boolean(argument),
647
+ }).toEqual({
648
+ node: node.componentId,
649
+ argumentId: argumentId,
650
+ found: true,
651
+ });
652
+ }
653
+ }
654
+ });
655
+
656
+ test("every required argument is filled in", () => {
657
+ for (const node of specOf(templateId).nodes) {
658
+ const metadata: ComponentMetadata = findMetadata(
659
+ node.metadataId,
660
+ ) as ComponentMetadata;
661
+
662
+ for (const argument of metadata.arguments) {
663
+ if (!argument.required) {
664
+ continue;
665
+ }
666
+
667
+ expect(Object.keys(node.args || {})).toContain(argument.id);
177
668
  }
178
669
  }
179
670
  });
@@ -184,20 +675,14 @@ describe.each(
184
675
  * first step.
185
676
  */
186
677
  test("every edge leaves a port the component actually has", () => {
187
- const spec: {
188
- nodes: Array<{ componentId: string; metadataId: string }>;
189
- edges: Array<{ fromComponentId: string; fromPort: string }>;
190
- } = getTemplateGraphSpec(templateId) as {
191
- nodes: Array<{ componentId: string; metadataId: string }>;
192
- edges: Array<{ fromComponentId: string; fromPort: string }>;
193
- };
678
+ const spec: TemplateSpec = specOf(templateId);
194
679
 
195
680
  for (const edge of spec.edges) {
196
- const node: { metadataId: string } = spec.nodes.find(
197
- (candidate: { componentId: string }) => {
681
+ const node: TemplateNodeSpec = spec.nodes.find(
682
+ (candidate: TemplateNodeSpec) => {
198
683
  return candidate.componentId === edge.fromComponentId;
199
684
  },
200
- ) as { metadataId: string };
685
+ ) as TemplateNodeSpec;
201
686
 
202
687
  const metadata: ComponentMetadata = findMetadata(
203
688
  node.metadataId,
@@ -209,89 +694,336 @@ describe.each(
209
694
  },
210
695
  );
211
696
 
212
- expect(port).toBeDefined();
697
+ expect({
698
+ from: edge.fromComponentId,
699
+ port: edge.fromPort,
700
+ found: Boolean(port),
701
+ }).toEqual({
702
+ from: edge.fromComponentId,
703
+ port: edge.fromPort,
704
+ found: true,
705
+ });
213
706
  }
214
707
  });
215
708
 
216
- test("every required argument is filled in", () => {
217
- const spec: {
218
- nodes: Array<{ metadataId: string; args?: JSONObject | undefined }>;
219
- } = getTemplateGraphSpec(templateId) as {
220
- nodes: Array<{ metadataId: string; args?: JSONObject | undefined }>;
221
- };
709
+ test("every fallible component handles its Error port", () => {
710
+ const spec: TemplateSpec = specOf(templateId);
222
711
 
223
712
  for (const node of spec.nodes) {
224
713
  const metadata: ComponentMetadata = findMetadata(
225
714
  node.metadataId,
226
715
  ) as ComponentMetadata;
716
+ const hasErrorPort: boolean = metadata.outPorts.some((port: Port) => {
717
+ return port.id === "error";
718
+ });
227
719
 
228
- for (const argument of metadata.arguments) {
229
- if (!argument.required) {
230
- continue;
231
- }
720
+ if (!hasErrorPort) {
721
+ continue;
722
+ }
232
723
 
233
- expect(Object.keys(node.args || {})).toContain(argument.id);
724
+ expect({
725
+ componentId: node.componentId,
726
+ handlesError: spec.edges.some((edge: TemplateEdgeSpec) => {
727
+ return (
728
+ edge.fromComponentId === node.componentId &&
729
+ edge.fromPort === "error"
730
+ );
731
+ }),
732
+ }).toEqual({ componentId: node.componentId, handlesError: true });
733
+ }
734
+ });
735
+
736
+ test("Slack messages start with an emoji and a scannable heading", () => {
737
+ for (const node of specOf(templateId).nodes) {
738
+ if (node.metadataId !== ComponentID.SlackSendMessageToChannel) {
739
+ continue;
234
740
  }
741
+
742
+ expect(node.args?.["text"]).toEqual(expect.any(String));
743
+ expect(node.args?.["text"] as string).toMatch(
744
+ /^:[a-z0-9_+-]+: \*[^\n]+\*/,
745
+ );
235
746
  }
236
747
  });
237
748
 
238
- test("every {{...}} reference points at a return value that exists", () => {
239
- const spec: {
240
- nodes: Array<{ componentId: string; metadataId: string }>;
241
- } = getTemplateGraphSpec(templateId) as {
242
- nodes: Array<{ componentId: string; metadataId: string }>;
243
- };
749
+ test("schedule expressions are valid cron", () => {
750
+ for (const node of specOf(templateId).nodes) {
751
+ if (node.metadataId !== ComponentID.Schedule) {
752
+ continue;
753
+ }
244
754
 
245
- const graph: { nodes: Array<LintGraphNode>; edges: Array<LintGraphEdge> } =
246
- hydrate(templateId);
755
+ expect(CronTab.isValid(node.args?.["schedule"] as string)).toBe(true);
756
+ }
757
+ });
247
758
 
248
- const references: Array<string> = [];
759
+ test("every edge connects component ids the template declares", () => {
760
+ const spec: TemplateSpec = specOf(templateId);
249
761
 
250
- for (const node of graph.nodes) {
251
- for (const value of Object.values(node.data.arguments || {})) {
252
- if (typeof value !== "string") {
253
- continue;
254
- }
762
+ const componentIds: Array<string> = spec.nodes.map(
763
+ (node: TemplateNodeSpec) => {
764
+ return node.componentId;
765
+ },
766
+ );
767
+
768
+ for (const edge of spec.edges) {
769
+ expect(componentIds).toContain(edge.fromComponentId);
770
+ expect(componentIds).toContain(edge.toComponentId);
771
+ }
772
+ });
773
+
774
+ test("component ids are unique and dot-free", () => {
775
+ const componentIds: Array<string> = specOf(templateId).nodes.map(
776
+ (node: TemplateNodeSpec) => {
777
+ return node.componentId;
778
+ },
779
+ );
780
+
781
+ expect(new Set(componentIds).size).toBe(componentIds.length);
782
+
783
+ for (const componentId of componentIds) {
784
+ expect(componentId).not.toContain(".");
785
+ }
786
+ });
787
+
788
+ test("has exactly one trigger, and it is a real trigger component", () => {
789
+ const triggers: Array<TemplateNodeSpec> = specOf(templateId).nodes.filter(
790
+ (node: TemplateNodeSpec) => {
791
+ return node.componentType === ComponentType.Trigger;
792
+ },
793
+ );
794
+
795
+ expect(triggers).toHaveLength(1);
796
+
797
+ const metadata: ComponentMetadata = findMetadata(
798
+ triggers[0]?.metadataId as string,
799
+ ) as ComponentMetadata;
800
+
801
+ expect(metadata.componentType).toBe(ComponentType.Trigger);
802
+ });
803
+
804
+ /*
805
+ * saveTriggerFromGraph takes the LAST trigger node in the graph while the
806
+ * runner takes the FIRST, so a second trigger would denormalize one id and
807
+ * run another.
808
+ */
809
+ test("no node other than the trigger is a trigger", () => {
810
+ const spec: TemplateSpec = specOf(templateId);
811
+
812
+ for (const node of spec.nodes) {
813
+ const metadata: ComponentMetadata = findMetadata(
814
+ node.metadataId,
815
+ ) as ComponentMetadata;
255
816
 
256
- const matches: Array<string> = value.match(/{{(.*?)}}/g) || [];
257
- references.push(...matches);
817
+ if (node.componentType === ComponentType.Trigger) {
818
+ continue;
258
819
  }
820
+
821
+ expect(metadata.componentType).not.toBe(ComponentType.Trigger);
259
822
  }
823
+ });
260
824
 
261
- for (const reference of references) {
262
- const path: string = reference.slice(2, -2);
263
- const parts: Array<string> = path.split(".");
825
+ test("every reference is a root the runtime actually has", () => {
826
+ for (const reference of referencesOf(templateId)) {
827
+ expect({
828
+ reference: reference.raw,
829
+ rootType: reference.parsed.rootType,
830
+ }).not.toEqual({
831
+ reference: reference.raw,
832
+ rootType: ReferenceRootType.Unknown,
833
+ });
834
+ }
835
+ });
264
836
 
265
- expect(parts[0]).toBe("local");
266
- expect(parts[1]).toBe("components");
837
+ /*
838
+ * The runtime hands the raw capture to deepFind without trimming, so a space
839
+ * inside the braces resolves to nothing. The linter calls it an error too.
840
+ */
841
+ test("no reference has whitespace inside its braces", () => {
842
+ for (const reference of referencesOf(templateId)) {
843
+ expect(reference.raw).toBe(`{{${reference.inner}}}`);
844
+ expect(reference.inner).not.toMatch(/\s/);
845
+ }
846
+ });
267
847
 
268
- const referencedNode: { metadataId: string } = spec.nodes.find(
269
- (candidate: { componentId: string }) => {
270
- return candidate.componentId === parts[2];
271
- },
272
- ) as { metadataId: string };
848
+ test("every component reference points at a component in this template", () => {
849
+ const componentIds: Array<string> = specOf(templateId).nodes.map(
850
+ (node: TemplateNodeSpec) => {
851
+ return node.componentId;
852
+ },
853
+ );
273
854
 
274
- expect(referencedNode).toBeDefined();
275
- expect(parts[3]).toBe("returnValues");
855
+ for (const reference of referencesOf(templateId)) {
856
+ if (
857
+ reference.parsed.rootType !== ReferenceRootType.ComponentReturnValue
858
+ ) {
859
+ continue;
860
+ }
861
+
862
+ expect(componentIds).toContain(reference.parsed.componentId);
863
+ }
864
+ });
865
+
866
+ test("every component reference points at a return value that exists", () => {
867
+ const spec: TemplateSpec = specOf(templateId);
868
+
869
+ for (const reference of referencesOf(templateId)) {
870
+ if (
871
+ reference.parsed.rootType !== ReferenceRootType.ComponentReturnValue
872
+ ) {
873
+ continue;
874
+ }
875
+
876
+ const referenced: TemplateNodeSpec = spec.nodes.find(
877
+ (node: TemplateNodeSpec) => {
878
+ return node.componentId === reference.parsed.componentId;
879
+ },
880
+ ) as TemplateNodeSpec;
276
881
 
277
882
  const metadata: ComponentMetadata = findMetadata(
278
- referencedNode.metadataId,
883
+ referenced.metadataId,
279
884
  ) as ComponentMetadata;
280
885
 
281
886
  const returnValue: ReturnValue | undefined = metadata.returnValues.find(
282
887
  (candidate: ReturnValue) => {
283
- return candidate.id === parts[4];
888
+ return candidate.id === reference.parsed.returnValueId;
284
889
  },
285
890
  );
286
891
 
287
- expect(returnValue).toBeDefined();
892
+ expect({
893
+ reference: reference.raw,
894
+ found: Boolean(returnValue),
895
+ }).toEqual({ reference: reference.raw, found: true });
288
896
  }
289
897
  });
290
898
 
291
899
  /*
292
- * The end-to-end check: run the shipped template through the same linter the
293
- * builder applies to a graph someone is editing. Zero errors is the bar.
900
+ * The one that catches the subtlest template bug there is. A database
901
+ * trigger only hydrates the columns its `select` names, so reading
902
+ * .model.title without asking for `title` yields nothing — and yielding
903
+ * nothing is not an error anywhere in the stack. The run succeeds and posts
904
+ * "Incident: {{local.components.…}}" to Slack.
294
905
  */
906
+ test("every field read off a database record was asked for in select", () => {
907
+ const spec: TemplateSpec = specOf(templateId);
908
+
909
+ for (const reference of referencesOf(templateId)) {
910
+ if (
911
+ reference.parsed.rootType !== ReferenceRootType.ComponentReturnValue
912
+ ) {
913
+ continue;
914
+ }
915
+
916
+ if (reference.parsed.returnValueId !== "model") {
917
+ continue;
918
+ }
919
+
920
+ const referenced: TemplateNodeSpec = spec.nodes.find(
921
+ (node: TemplateNodeSpec) => {
922
+ return node.componentId === reference.parsed.componentId;
923
+ },
924
+ ) as TemplateNodeSpec;
925
+
926
+ const select: JSONValue | undefined = (referenced.args || {})[
927
+ "select"
928
+ ] as JSONValue | undefined;
929
+
930
+ const segments: Array<string> = reference.inner.split(".");
931
+ // local . components . <id> . returnValues . model . <field...>
932
+ const fieldPath: Array<string> = segments.slice(5);
933
+
934
+ if (fieldPath.length === 0) {
935
+ continue;
936
+ }
937
+
938
+ expect({
939
+ reference: reference.raw,
940
+ covered: selectCovers(select, fieldPath),
941
+ }).toEqual({ reference: reference.raw, covered: true });
942
+ }
943
+ });
944
+
945
+ test("every variable it declares is actually used by the graph", () => {
946
+ const used: Set<string> = new Set(
947
+ referencesOf(templateId)
948
+ .filter((reference: TemplateReference) => {
949
+ return reference.parsed.rootType === ReferenceRootType.LocalVariable;
950
+ })
951
+ .map((reference: TemplateReference) => {
952
+ return reference.parsed.variableName as string;
953
+ }),
954
+ );
955
+
956
+ for (const variable of template.variables) {
957
+ expect({
958
+ variable: variable.name,
959
+ used: used.has(variable.name),
960
+ }).toEqual({ variable: variable.name, used: true });
961
+ }
962
+ });
963
+
964
+ /*
965
+ * The inverse, and the more dangerous direction: a reference to a variable
966
+ * the wizard never asks for means no row is ever written for it, and the
967
+ * literal braces ship.
968
+ */
969
+ test("every variable the graph references is declared by the template", () => {
970
+ const declared: Array<string> = template.variables.map(
971
+ (variable: WorkflowTemplateVariable) => {
972
+ return variable.name;
973
+ },
974
+ );
975
+
976
+ for (const reference of referencesOf(templateId)) {
977
+ if (reference.parsed.rootType !== ReferenceRootType.LocalVariable) {
978
+ continue;
979
+ }
980
+
981
+ expect({
982
+ reference: reference.raw,
983
+ declared: declared.includes(reference.parsed.variableName as string),
984
+ }).toEqual({ reference: reference.raw, declared: true });
985
+ }
986
+ });
987
+
988
+ /*
989
+ * The wizard only ever writes workflow-scoped variables, so a template
990
+ * reaching for a project-global one would silently find nothing.
991
+ */
992
+ test("it does not reach for project-global variables", () => {
993
+ for (const reference of referencesOf(templateId)) {
994
+ expect(reference.parsed.rootType).not.toBe(
995
+ ReferenceRootType.GlobalVariable,
996
+ );
997
+ }
998
+ });
999
+
1000
+ /*
1001
+ * An optional variable's reference must be the ENTIRE argument value. That
1002
+ * is what lets the wizard drop the argument when the field is left blank; a
1003
+ * reference embedded in a longer string would survive the strip and leave
1004
+ * the braces behind in the saved workflow.
1005
+ */
1006
+ test("an optional variable's reference is the whole argument, so it can be dropped", () => {
1007
+ for (const variable of template.variables) {
1008
+ if (variable.required) {
1009
+ continue;
1010
+ }
1011
+
1012
+ const spec: TemplateSpec = specOf(templateId);
1013
+ const token: string = `{{local.variables.${variable.name}}}`;
1014
+
1015
+ for (const node of spec.nodes) {
1016
+ for (const value of Object.values(node.args || {})) {
1017
+ if (typeof value !== "string" || !value.includes(token)) {
1018
+ continue;
1019
+ }
1020
+
1021
+ expect(value.trim()).toBe(token);
1022
+ }
1023
+ }
1024
+ }
1025
+ });
1026
+
295
1027
  test("passes the builder's own graph checks with no errors", () => {
296
1028
  const result: WorkflowLintResult = lintWorkflowGraph(hydrate(templateId));
297
1029
 
@@ -308,26 +1040,19 @@ describe.each(
308
1040
  ).toEqual([]);
309
1041
  });
310
1042
 
311
- test("has exactly one trigger, and it is a real trigger component", () => {
312
- const spec: {
313
- nodes: Array<{ metadataId: string; componentType: ComponentType }>;
314
- } = getTemplateGraphSpec(templateId) as {
315
- nodes: Array<{ metadataId: string; componentType: ComponentType }>;
316
- };
317
-
318
- const triggers: Array<{ metadataId: string }> = spec.nodes.filter(
319
- (node: { componentType: ComponentType }) => {
320
- return node.componentType === ComponentType.Trigger;
321
- },
322
- );
323
-
324
- expect(triggers).toHaveLength(1);
325
-
326
- const metadata: ComponentMetadata = findMetadata(
327
- triggers[0]?.metadataId as string,
328
- ) as ComponentMetadata;
1043
+ /*
1044
+ * Warnings too. UnreachableComponent is only a warning, so without this a
1045
+ * template could ship with a stray node that never runs and no test would
1046
+ * notice.
1047
+ */
1048
+ test("passes the builder's own graph checks with no warnings either", () => {
1049
+ const result: WorkflowLintResult = lintWorkflowGraph(hydrate(templateId));
329
1050
 
330
- expect(metadata.componentType).toBe(ComponentType.Trigger);
1051
+ expect(
1052
+ result.issues.map((issue: WorkflowLintIssue) => {
1053
+ return issue.message;
1054
+ }),
1055
+ ).toEqual([]);
331
1056
  });
332
1057
 
333
1058
  /*
@@ -360,7 +1085,52 @@ describe.each(
360
1085
  }
361
1086
  });
362
1087
 
1088
+ test("builds fresh edge ids each time too", () => {
1089
+ type EdgeIdsFunction = (graph: JSONObject) => Array<string>;
1090
+
1091
+ const edgeIds: EdgeIdsFunction = (graph: JSONObject): Array<string> => {
1092
+ return (graph["edges"] as Array<JSONObject>).map((edge: JSONObject) => {
1093
+ return edge["id"] as string;
1094
+ });
1095
+ };
1096
+
1097
+ const first: Array<string> = edgeIds(
1098
+ buildGraphForTemplate(templateId, generateId) as JSONObject,
1099
+ );
1100
+ const second: Array<string> = edgeIds(
1101
+ buildGraphForTemplate(templateId, generateId) as JSONObject,
1102
+ );
1103
+
1104
+ for (const id of first) {
1105
+ expect(second).not.toContain(id);
1106
+ }
1107
+ });
1108
+
363
1109
  test("keeps stable component ids, because references point at them", () => {
1110
+ type ComponentIdsFunction = (graph: JSONObject) => Array<string>;
1111
+
1112
+ const componentIds: ComponentIdsFunction = (
1113
+ graph: JSONObject,
1114
+ ): Array<string> => {
1115
+ return (graph["nodes"] as Array<JSONObject>).map((node: JSONObject) => {
1116
+ return (node["data"] as JSONObject)["id"] as string;
1117
+ });
1118
+ };
1119
+
1120
+ expect(
1121
+ componentIds(buildGraphForTemplate(templateId, generateId) as JSONObject),
1122
+ ).toEqual(
1123
+ componentIds(buildGraphForTemplate(templateId, generateId) as JSONObject),
1124
+ );
1125
+ });
1126
+
1127
+ /*
1128
+ * A built graph gets edited afterwards — by the wizard stripping arguments
1129
+ * for blank optional variables, and by the builder. Sharing the argument
1130
+ * object with the shipped definition would let that editing leak into every
1131
+ * later workflow built in the same process.
1132
+ */
1133
+ test("built graphs do not share argument objects with the definition", () => {
364
1134
  const first: JSONObject = buildGraphForTemplate(
365
1135
  templateId,
366
1136
  generateId,
@@ -370,17 +1140,25 @@ describe.each(
370
1140
  generateId,
371
1141
  ) as JSONObject;
372
1142
 
373
- type ComponentIdsFunction = (graph: JSONObject) => Array<string>;
374
-
375
- const componentIds: ComponentIdsFunction = (
1143
+ const argumentsOf: (graph: JSONObject, index: number) => JSONObject = (
376
1144
  graph: JSONObject,
377
- ): Array<string> => {
378
- return (graph["nodes"] as Array<JSONObject>).map((node: JSONObject) => {
379
- return (node["data"] as JSONObject)["id"] as string;
380
- });
1145
+ index: number,
1146
+ ): JSONObject => {
1147
+ const node: JSONObject = (graph["nodes"] as Array<JSONObject>)[
1148
+ index
1149
+ ] as JSONObject;
1150
+
1151
+ return (node["data"] as JSONObject)["arguments"] as JSONObject;
381
1152
  };
382
1153
 
383
- expect(componentIds(first)).toEqual(componentIds(second));
1154
+ const firstArguments: JSONObject = argumentsOf(first, 0);
1155
+
1156
+ (firstArguments as JSONObject)["__scribbled"] = "yes";
1157
+
1158
+ expect(argumentsOf(second, 0)["__scribbled"]).toBeUndefined();
1159
+ expect(
1160
+ (specOf(templateId).nodes[0]?.args || {})["__scribbled"],
1161
+ ).toBeUndefined();
384
1162
  });
385
1163
 
386
1164
  test("edges connect nodes that are in the graph", () => {
@@ -400,4 +1178,41 @@ describe.each(
400
1178
  expect(nodeIds).toContain(edge["target"] as string);
401
1179
  }
402
1180
  });
1181
+
1182
+ test("every edge targets the in port, which is what react-flow attaches to", () => {
1183
+ const graph: JSONObject = buildGraphForTemplate(
1184
+ templateId,
1185
+ generateId,
1186
+ ) as JSONObject;
1187
+
1188
+ for (const edge of graph["edges"] as Array<JSONObject>) {
1189
+ expect(edge["targetHandle"]).toBe("in");
1190
+ }
1191
+ });
1192
+
1193
+ test("every non-trigger node has an in port for that edge to land on", () => {
1194
+ const spec: TemplateSpec = specOf(templateId);
1195
+
1196
+ const targeted: Set<string> = new Set(
1197
+ spec.edges.map((edge: TemplateEdgeSpec) => {
1198
+ return edge.toComponentId;
1199
+ }),
1200
+ );
1201
+
1202
+ for (const node of spec.nodes) {
1203
+ if (!targeted.has(node.componentId)) {
1204
+ continue;
1205
+ }
1206
+
1207
+ const metadata: ComponentMetadata = findMetadata(
1208
+ node.metadataId,
1209
+ ) as ComponentMetadata;
1210
+
1211
+ expect(
1212
+ metadata.inPorts.map((port: Port) => {
1213
+ return port.id;
1214
+ }),
1215
+ ).toContain("in");
1216
+ }
1217
+ });
403
1218
  });