@oneuptime/common 14.0.10 → 14.0.11

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 (837) hide show
  1. package/Models/DatabaseModels/AIConversation.ts +127 -1
  2. package/Models/DatabaseModels/CephCluster.ts +12 -0
  3. package/Models/DatabaseModels/CloudResource.ts +12 -0
  4. package/Models/DatabaseModels/DatabaseServer.ts +12 -0
  5. package/Models/DatabaseModels/DockerHost.ts +12 -0
  6. package/Models/DatabaseModels/DockerSwarmCluster.ts +12 -0
  7. package/Models/DatabaseModels/GlobalOidc.ts +0 -4
  8. package/Models/DatabaseModels/GlobalOidcProject.ts +0 -4
  9. package/Models/DatabaseModels/GlobalSso.ts +0 -4
  10. package/Models/DatabaseModels/GlobalSsoProject.ts +0 -4
  11. package/Models/DatabaseModels/Host.ts +12 -0
  12. package/Models/DatabaseModels/IncidentForm.ts +594 -0
  13. package/Models/DatabaseModels/IncidentFormSubmission.ts +283 -0
  14. package/Models/DatabaseModels/IncidentTemplate.ts +59 -0
  15. package/Models/DatabaseModels/Index.ts +14 -0
  16. package/Models/DatabaseModels/IoTFleet.ts +12 -0
  17. package/Models/DatabaseModels/KubernetesCluster.ts +12 -0
  18. package/Models/DatabaseModels/MessageQueue.ts +1102 -0
  19. package/Models/DatabaseModels/MessageQueueLabelRule.ts +553 -0
  20. package/Models/DatabaseModels/MessageQueueOwnerRule.ts +633 -0
  21. package/Models/DatabaseModels/MessageQueueOwnerTeam.ts +491 -0
  22. package/Models/DatabaseModels/MessageQueueOwnerUser.ts +490 -0
  23. package/Models/DatabaseModels/PodmanHost.ts +12 -0
  24. package/Models/DatabaseModels/Project.ts +59 -0
  25. package/Models/DatabaseModels/ProjectOidc.ts +0 -4
  26. package/Models/DatabaseModels/ProjectSso.ts +0 -4
  27. package/Models/DatabaseModels/ProxmoxCluster.ts +12 -0
  28. package/Models/DatabaseModels/RumApplication.ts +12 -0
  29. package/Models/DatabaseModels/ServerlessFunction.ts +12 -0
  30. package/Models/DatabaseModels/Service.ts +12 -0
  31. package/Models/DatabaseModels/StatusPageOidc.ts +0 -4
  32. package/Models/DatabaseModels/StatusPageSso.ts +0 -4
  33. package/Models/DatabaseModels/TeamComplianceSetting.ts +47 -2
  34. package/Models/DatabaseModels/VMwareVCenter.ts +12 -0
  35. package/Server/API/AIChatAPI.ts +13 -114
  36. package/Server/API/AIInvestigationAPI.ts +3 -3
  37. package/Server/API/AIInvestigationConversationAPI.ts +266 -0
  38. package/Server/API/IncidentFormAPI.ts +376 -0
  39. package/Server/API/ProjectOIDC.ts +16 -25
  40. package/Server/API/ProjectSSO.ts +16 -24
  41. package/Server/API/StatusPageAPI.ts +42 -77
  42. package/Server/Enterprise/EnterpriseEdition.ts +93 -28
  43. package/Server/Enterprise/EnterpriseFeature.ts +25 -3
  44. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +1 -1
  45. package/Server/Enterprise/EnterpriseServerModule.ts +4 -1
  46. package/Server/EnvironmentConfig.ts +1 -1
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.ts +129 -0
  48. package/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.ts +52 -0
  49. package/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.ts +75 -0
  50. package/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.ts +477 -0
  51. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  52. package/Server/Middleware/IncidentFormRateLimit.ts +847 -0
  53. package/Server/Middleware/UserAuthorization.ts +16 -38
  54. package/Server/Services/AIService.ts +10 -13
  55. package/Server/Services/IncidentCustomFieldService.ts +112 -2
  56. package/Server/Services/IncidentEpisodeMemberService.ts +24 -4
  57. package/Server/Services/IncidentEpisodeService.ts +10 -1
  58. package/Server/Services/IncidentFormService.ts +1566 -0
  59. package/Server/Services/IncidentFormSubmissionService.ts +97 -0
  60. package/Server/Services/IncidentGroupingEngineService.ts +45 -8
  61. package/Server/Services/IncidentService.ts +123 -5
  62. package/Server/Services/IncidentTemplateService.ts +22 -0
  63. package/Server/Services/Index.ts +14 -0
  64. package/Server/Services/MessageQueueLabelRuleEngineService.ts +321 -0
  65. package/Server/Services/MessageQueueLabelRuleService.ts +14 -0
  66. package/Server/Services/MessageQueueOwnerRuleEngineService.ts +412 -0
  67. package/Server/Services/MessageQueueOwnerRuleService.ts +14 -0
  68. package/Server/Services/MessageQueueOwnerTeamService.ts +62 -0
  69. package/Server/Services/MessageQueueOwnerUserService.ts +62 -0
  70. package/Server/Services/MessageQueueService.ts +1463 -0
  71. package/Server/Services/OpenTelemetryIngestService.ts +37 -4
  72. package/Server/Services/ProjectService.ts +0 -59
  73. package/Server/Services/StatusPagePrivateUserService.ts +1 -4
  74. package/Server/Services/StatusPageService.ts +1 -51
  75. package/Server/Services/TeamComplianceSettingService.ts +163 -42
  76. package/Server/Services/UserNotificationRuleService.ts +8 -1
  77. package/Server/Services/WorkspaceNotificationSummaryService.ts +12 -3
  78. package/Server/Types/Database/Permissions/CreatePermission.ts +17 -3
  79. package/Server/Types/Database/Permissions/EditionPermission.ts +140 -38
  80. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +16 -0
  81. package/Server/Types/Database/Permissions/TablePermission.ts +3 -3
  82. package/Server/Types/Database/Permissions/UpdatePermission.ts +20 -6
  83. package/Server/Utils/AI/Chat/AgentContextCompactor.ts +200 -0
  84. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +307 -48
  85. package/Server/Utils/AI/Chat/ChatRunCancellation.ts +156 -0
  86. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +78 -18
  87. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
  88. package/Server/Utils/AI/Chat/ToolOutputPager.ts +322 -0
  89. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +88 -30
  90. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +13 -1
  91. package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +0 -32
  92. package/Server/Utils/AI/CodeFix/FixRunBudget.ts +27 -25
  93. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +7 -1
  94. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +34 -14
  95. package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +69 -24
  96. package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +9 -0
  97. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +53 -10
  98. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +27 -10
  99. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +27 -10
  100. package/Server/Utils/AI/SRE/InvestigationQueue.ts +16 -19
  101. package/Server/Utils/AI/SRE/InvestigationThread.ts +646 -0
  102. package/Server/Utils/AI/SRE/InvestigationThreadService.ts +715 -0
  103. package/Server/Utils/AI/Toolbox/Serializer.ts +10 -3
  104. package/Server/Utils/EditionEnforcement.ts +19 -202
  105. package/Server/Utils/LLM/LLMService.ts +259 -63
  106. package/Server/Utils/RelaxedScimTeamLocksReport.ts +245 -0
  107. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
  108. package/Server/Utils/SameOriginRequest.ts +203 -0
  109. package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
  110. package/Server/Utils/Telemetry/EntityRegistry.ts +4 -1
  111. package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +1402 -0
  112. package/Server/Utils/Telemetry/ResourceEntityFilter.ts +4 -1
  113. package/Server/Utils/VendorAssets.ts +3 -3
  114. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +3 -1
  115. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +3 -1
  116. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +10 -1
  117. package/Tests/App/Accounts/IncidentFormPage.test.tsx +2036 -0
  118. package/Tests/App/Accounts/IncidentFormServerMessages.test.ts +119 -0
  119. package/Tests/App/Accounts/IncidentFormUtils.test.ts +1157 -0
  120. package/Tests/App/Accounts/LoginPasskey.test.tsx +6 -4
  121. package/Tests/App/Accounts/LoginSso.test.tsx +724 -0
  122. package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +338 -0
  123. package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +331 -0
  124. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +47 -33
  125. package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +1021 -0
  126. package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +876 -78
  127. package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +20 -3
  128. package/Tests/App/Dashboard/CephProxmoxVMwareDocumentationCards.test.tsx +359 -0
  129. package/Tests/App/Dashboard/CephSetupGuide.test.ts +961 -0
  130. package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +381 -95
  131. package/Tests/App/Dashboard/CloudSetupGuide.test.ts +1463 -0
  132. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +174 -12
  133. package/Tests/App/Dashboard/ContainerSetupGuideCards.test.tsx +345 -0
  134. package/Tests/App/Dashboard/CoreListEmptyStates.test.tsx +501 -0
  135. package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +0 -1
  136. package/Tests/App/Dashboard/DatabaseDocumentationCard.test.tsx +400 -0
  137. package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +5 -0
  138. package/Tests/App/Dashboard/DatabaseSetupGuide.test.ts +1869 -0
  139. package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +44 -0
  140. package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +50 -9
  141. package/Tests/App/Dashboard/DockerSetupGuide.test.ts +899 -0
  142. package/Tests/App/Dashboard/DockerSwarmSetupGuide.test.ts +964 -0
  143. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +141 -7
  144. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +52 -39
  145. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +7 -1
  146. package/Tests/App/Dashboard/GettingStartedTaskRoutes.test.tsx +331 -0
  147. package/Tests/App/Dashboard/HomeOverviewStatsFirstRun.test.tsx +925 -0
  148. package/Tests/App/Dashboard/HostDocumentationCard.test.tsx +225 -0
  149. package/Tests/App/Dashboard/HostSetupGuide.test.ts +1183 -0
  150. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +69 -45
  151. package/Tests/App/Dashboard/IncidentCreateTemplateCustomFieldSettings.test.tsx +745 -0
  152. package/Tests/App/Dashboard/IncidentCreateTemplateOwners.test.tsx +414 -0
  153. package/Tests/App/Dashboard/IncidentCustomFieldCreateSettingsForm.test.ts +1042 -0
  154. package/Tests/App/Dashboard/IncidentCustomFieldSettingsCard.test.tsx +1816 -0
  155. package/Tests/App/Dashboard/IncidentFormPlan.test.ts +89 -0
  156. package/Tests/App/Dashboard/IncidentFormShareLinkCard.test.tsx +846 -0
  157. package/Tests/App/Dashboard/IncidentFormsPages.test.tsx +1324 -0
  158. package/Tests/App/Dashboard/IncidentTemplateCustomFieldSettings.test.tsx +630 -0
  159. package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +13 -0
  160. package/Tests/App/Dashboard/IncomingEmailMonitorLinkVerifyHint.test.tsx +104 -0
  161. package/Tests/App/Dashboard/InvestigationConversation.test.tsx +1107 -0
  162. package/Tests/App/Dashboard/InvestigationConversationData.test.ts +546 -0
  163. package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +170 -5
  164. package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +207 -2
  165. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +729 -34
  166. package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +9 -21
  167. package/Tests/App/Dashboard/InvestigationReportView.test.tsx +274 -37
  168. package/Tests/App/Dashboard/InvestigationStatusBadge.test.tsx +130 -0
  169. package/Tests/App/Dashboard/IoTDocumentationCard.test.tsx +218 -0
  170. package/Tests/App/Dashboard/IoTSetupGuide.test.ts +1124 -0
  171. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +20 -6
  172. package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +107 -83
  173. package/Tests/App/Dashboard/KubernetesSetupGuide.test.ts +787 -0
  174. package/Tests/App/Dashboard/MessageQueueBreadcrumbs.test.tsx +228 -0
  175. package/Tests/App/Dashboard/MessageQueueBrokerHealth.test.tsx +1538 -0
  176. package/Tests/App/Dashboard/MessageQueueBrokerHealthMetricChart.test.tsx +969 -0
  177. package/Tests/App/Dashboard/MessageQueueBrokerHealthReads.test.ts +889 -0
  178. package/Tests/App/Dashboard/MessageQueueBrokerMetricsReach.test.ts +236 -0
  179. package/Tests/App/Dashboard/MessageQueueDocumentationCard.test.tsx +479 -0
  180. package/Tests/App/Dashboard/MessageQueueListPages.test.tsx +1232 -0
  181. package/Tests/App/Dashboard/MessageQueueMetricDescriptions.test.ts +244 -0
  182. package/Tests/App/Dashboard/MessageQueueMonitorLink.test.ts +952 -0
  183. package/Tests/App/Dashboard/MessageQueueMonitorLinkMonitorCreate.test.tsx +859 -0
  184. package/Tests/App/Dashboard/MessageQueueOverview.test.tsx +1773 -0
  185. package/Tests/App/Dashboard/MessageQueueOverviewPresentation.test.ts +196 -0
  186. package/Tests/App/Dashboard/MessageQueuePresentation.test.ts +799 -0
  187. package/Tests/App/Dashboard/MessageQueueProducersConsumers.test.tsx +680 -0
  188. package/Tests/App/Dashboard/MessageQueueRoutes.test.tsx +383 -0
  189. package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +278 -0
  190. package/Tests/App/Dashboard/MessageQueueSetupGuide.test.ts +2778 -0
  191. package/Tests/App/Dashboard/MessageQueueSideMenus.test.tsx +273 -0
  192. package/Tests/App/Dashboard/MessageQueueSpanPopulations.test.ts +930 -0
  193. package/Tests/App/Dashboard/MessageQueueSpanStore.ts +351 -0
  194. package/Tests/App/Dashboard/MessageQueueTelemetryScope.test.ts +375 -0
  195. package/Tests/App/Dashboard/MessageQueueTelemetryScopeTabs.test.tsx +668 -0
  196. package/Tests/App/Dashboard/MessageQueueViewPages.test.tsx +685 -0
  197. package/Tests/App/Dashboard/MonitorAndHomeNotOperationalMenus.test.tsx +342 -0
  198. package/Tests/App/Dashboard/MonitorCreateFirstRunDefaults.test.tsx +623 -0
  199. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +442 -0
  200. package/Tests/App/Dashboard/MonitorLogsPageViewSummary.test.tsx +814 -0
  201. package/Tests/App/Dashboard/MonitorSetupCardBodies.test.tsx +246 -0
  202. package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +8 -0
  203. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +27 -12
  204. package/Tests/App/Dashboard/PlanGatedPage.test.tsx +292 -0
  205. package/Tests/App/Dashboard/PodmanSetupGuide.test.ts +948 -0
  206. package/Tests/App/Dashboard/ProductOrientation.test.tsx +5 -4
  207. package/Tests/App/Dashboard/ProductSettingsSectionCollapsed.test.tsx +266 -0
  208. package/Tests/App/Dashboard/ProxmoxSetupGuide.test.ts +1318 -0
  209. package/Tests/App/Dashboard/ResourceAiAgentAttentionServerParity.test.ts +555 -0
  210. package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +298 -9
  211. package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +453 -0
  212. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +16 -0
  213. package/Tests/App/Dashboard/ResourceConnectionGuideCard.test.tsx +444 -0
  214. package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsInfra.test.tsx +798 -0
  215. package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsPlatforms.test.tsx +717 -0
  216. package/Tests/App/Dashboard/ResourceConnectionGuides.test.ts +981 -0
  217. package/Tests/App/Dashboard/ResourceConnectionState.test.ts +132 -0
  218. package/Tests/App/Dashboard/RumDocumentationCard.test.tsx +293 -0
  219. package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +467 -0
  220. package/Tests/App/Dashboard/RumSetupGuide.test.ts +758 -0
  221. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +25 -0
  222. package/Tests/App/Dashboard/ServerlessDocumentationCard.test.tsx +254 -0
  223. package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1074 -0
  224. package/Tests/App/Dashboard/SetupGuide.test.ts +246 -0
  225. package/Tests/App/Dashboard/SetupGuideCard.test.tsx +756 -0
  226. package/Tests/App/Dashboard/SloListSideMenu.test.tsx +120 -0
  227. package/Tests/App/Dashboard/SsoPages.test.tsx +833 -0
  228. package/Tests/App/Dashboard/TelemetryDocumentation.test.tsx +253 -0
  229. package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +730 -0
  230. package/Tests/App/Dashboard/VMwareSetupGuide.test.ts +1033 -0
  231. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +87 -7
  232. package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +28 -9
  233. package/Tests/Models/DatabaseModels/IncidentFormModel.test.ts +1250 -0
  234. package/Tests/Models/DatabaseModels/MessageQueueModels.test.ts +1983 -0
  235. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  236. package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +190 -14
  237. package/Tests/Models/IncidentTemplateCustomFieldSettingsColumn.test.ts +291 -0
  238. package/Tests/Server/API/AIInvestigationConversationAPI.test.ts +412 -0
  239. package/Tests/Server/API/GlobalConfigLicense.test.ts +38 -9
  240. package/Tests/Server/API/IncidentFormAPI.test.ts +942 -0
  241. package/Tests/Server/API/IncidentFormPublicRoutes.test.ts +1653 -0
  242. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -1
  243. package/Tests/Server/API/{SsoProviderListingsEdition.test.ts → SsoProviderListings.test.ts} +164 -110
  244. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +76 -54
  245. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +125 -42
  246. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +36 -10
  247. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +51 -9
  248. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +13 -8
  249. package/Tests/Server/Enterprise/SsoInCommunityEdition.test.ts +540 -0
  250. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  251. package/Tests/Server/Infrastructure/Postgres/AddIncidentFormsMigration.test.ts +438 -0
  252. package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleNotificationChannelsMigration.test.ts +255 -0
  253. package/Tests/Server/Infrastructure/Postgres/MessageQueueTablesMigration.test.ts +637 -0
  254. package/Tests/Server/Middleware/IncidentFormRateLimit.test.ts +1630 -0
  255. package/Tests/Server/Middleware/UserAuthorization.test.ts +16 -17
  256. package/Tests/Server/Middleware/UserAuthorizationSsoEnforcement.test.ts +544 -0
  257. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +37 -8
  258. package/Tests/Server/Services/IncidentCreatedFeedTitle.test.ts +212 -0
  259. package/Tests/Server/Services/IncidentCustomFieldDeleteFormQuestions.test.ts +297 -0
  260. package/Tests/Server/Services/IncidentFormOwnersCreatedNotification.test.ts +497 -0
  261. package/Tests/Server/Services/IncidentFormPostgres.test.ts +958 -0
  262. package/Tests/Server/Services/IncidentFormPublicForm.test.ts +1260 -0
  263. package/Tests/Server/Services/IncidentFormPublicSubmission.test.ts +2520 -0
  264. package/Tests/Server/Services/IncidentFormRegistration.test.ts +159 -0
  265. package/Tests/Server/Services/IncidentFormService.test.ts +663 -0
  266. package/Tests/Server/Services/IncidentFormSubmissionService.test.ts +430 -0
  267. package/Tests/Server/Services/IncidentFormSubmissionTemplateBranch.test.ts +473 -0
  268. package/Tests/Server/Services/IncidentGroupingTemplateSubstitution.test.ts +81 -0
  269. package/Tests/Server/Services/IncidentTemplateCustomFieldSettings.test.ts +262 -0
  270. package/Tests/Server/Services/IncidentTemplateOwnersOnDeclare.test.ts +566 -0
  271. package/Tests/Server/Services/IncidentTitleMarkdownSinks.test.ts +640 -0
  272. package/Tests/Server/Services/LlmLogServiceTokenAggregateParams.test.ts +3 -3
  273. package/Tests/Server/Services/MessageQueueOwnerServices.test.ts +440 -0
  274. package/Tests/Server/Services/MessageQueueRegistries.test.ts +577 -0
  275. package/Tests/Server/Services/MessageQueueRuleEngines.test.ts +900 -0
  276. package/Tests/Server/Services/MessageQueueService.test.ts +2210 -0
  277. package/Tests/Server/Services/MessageQueueSqlPostgres.test.ts +1271 -0
  278. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
  279. package/Tests/Server/Services/OpenTelemetryRetentionOverrideEdition.test.ts +474 -0
  280. package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +21 -0
  281. package/Tests/Server/Services/OwnerRowUniqueness.test.ts +3 -0
  282. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +0 -1
  283. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +56 -6
  284. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -1
  285. package/Tests/Server/Services/SsoRequirementReads.test.ts +454 -0
  286. package/Tests/Server/Services/SsoRequirementWrites.test.ts +529 -0
  287. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
  288. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +107 -89
  289. package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +1068 -176
  290. package/Tests/Server/Services/TeamComplianceSettingService.test.ts +1962 -200
  291. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +654 -297
  292. package/Tests/Server/Types/Database/Permissions/RetentionOverrideColumns.test.ts +784 -0
  293. package/Tests/Server/Types/Database/Permissions/SsoScalePlanGate.test.ts +418 -0
  294. package/Tests/Server/Utils/AI/AIAlertGating.test.ts +0 -1
  295. package/Tests/Server/Utils/AI/AIInvestigationEngineRunLimits.test.ts +136 -0
  296. package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +15 -14
  297. package/Tests/Server/Utils/AI/AgentContextCompactor.test.ts +351 -0
  298. package/Tests/Server/Utils/AI/ChatAgentRunnerSharedThread.test.ts +842 -0
  299. package/Tests/Server/Utils/AI/ChatRunCancellation.test.ts +195 -0
  300. package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +10 -57
  301. package/Tests/Server/Utils/AI/FixRunBudget.test.ts +20 -24
  302. package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +7 -30
  303. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +225 -29
  304. package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +266 -25
  305. package/Tests/Server/Utils/AI/InvestigationThread.test.ts +580 -0
  306. package/Tests/Server/Utils/AI/InvestigationThreadService.test.ts +801 -0
  307. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +525 -43
  308. package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +4 -2
  309. package/Tests/Server/Utils/AI/LLMServiceUnreachableProvider.test.ts +435 -0
  310. package/Tests/Server/Utils/AI/ObservabilityAssistantLimits.test.ts +462 -0
  311. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +14 -25
  312. package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +2 -0
  313. package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +297 -15
  314. package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +10 -6
  315. package/Tests/Server/Utils/AI/ToolOutputPager.test.ts +382 -0
  316. package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +23 -4
  317. package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +25 -6
  318. package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +14 -3
  319. package/Tests/Server/Utils/EditionEnforcement.test.ts +107 -147
  320. package/Tests/Server/Utils/{CommunityEditionSsoReport.test.ts → RelaxedScimTeamLocksReport.test.ts} +212 -208
  321. package/Tests/Server/Utils/SameOriginRequest.test.ts +372 -0
  322. package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +20 -0
  323. package/Tests/Server/Utils/Telemetry/MessageQueueDiscovery.test.ts +2590 -0
  324. package/Tests/Server/Utils/Telemetry/MessageQueueSpanQueryTwin.ts +246 -0
  325. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +23 -0
  326. package/Tests/Types/AI/AIAgentRunLimits.test.ts +255 -0
  327. package/Tests/Types/Code/JsonSyntax.test.ts +1300 -0
  328. package/Tests/Types/CustomField/CustomFieldCreateSettings.test.ts +1113 -0
  329. package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +91 -0
  330. package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +30 -0
  331. package/Tests/Types/Incident/IncidentFormIpAllowlist.test.ts +227 -0
  332. package/Tests/Types/Incident/IncidentFormPublic.test.ts +1916 -0
  333. package/Tests/Types/MessageQueue/MessageQueueEntityKey.test.ts +916 -0
  334. package/Tests/Types/MessageQueue/MessageQueueIdentity.test.ts +567 -0
  335. package/Tests/Types/MessageQueue/MessageQueueManualIdentity.test.ts +686 -0
  336. package/Tests/Types/MessageQueue/MessageQueueMetricCatalog.test.ts +1726 -0
  337. package/Tests/Types/MessageQueue/MessageQueueMetricResolution.test.ts +1758 -0
  338. package/Tests/Types/MessageQueue/MessagingInstrumentationFixtures.test.ts +4686 -0
  339. package/Tests/Types/MessageQueue/MessagingSystem.test.ts +840 -0
  340. package/Tests/Types/MessageQueue/MessagingTelemetryFixtures.ts +3287 -0
  341. package/Tests/Types/MessageQueue/MessagingTelemetryResolver.test.ts +2966 -0
  342. package/Tests/Types/Monitor/MessageQueueAlertTemplates.test.ts +5401 -0
  343. package/Tests/Types/Monitor/MetricEngineFold.ts +154 -0
  344. package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +5 -3
  345. package/Tests/Types/Team/ComplianceRule.test.ts +588 -37
  346. package/Tests/Types/Team/TeamComplianceStatus.test.ts +64 -11
  347. package/Tests/Types/XML.test.ts +51 -0
  348. package/Tests/UI/Components/CodeEditor/CodeEditor.test.tsx +2362 -0
  349. package/Tests/UI/Components/CodeEditor/CodeEditorCommands.test.ts +810 -0
  350. package/Tests/UI/Components/CodeEditor/CodeEditorHighlight.test.ts +338 -0
  351. package/Tests/UI/Components/CodeEditor/CodeEditorLanguages.test.ts +222 -0
  352. package/Tests/UI/Components/CodeEditor/CodeEditorStyles.test.ts +807 -0
  353. package/Tests/UI/Components/CodeEditor/NoMonaco.test.ts +245 -0
  354. package/Tests/UI/Components/CodeEditor/YamlEditor.test.tsx +729 -0
  355. package/Tests/UI/Components/CopyTextButton.test.tsx +76 -0
  356. package/Tests/UI/Components/EditionLabelLapseCopy.ts +51 -14
  357. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +131 -23
  358. package/Tests/UI/Components/ErrorMessageAction.test.tsx +142 -0
  359. package/Tests/UI/Components/FacetSidebarInScope.test.tsx +459 -0
  360. package/Tests/UI/Components/FacetValuesInScope.test.ts +270 -0
  361. package/Tests/UI/Components/Forms/FormFieldCodeEditors.test.tsx +294 -0
  362. package/Tests/UI/Components/Forms/FormFieldMarkdown.test.tsx +126 -0
  363. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +22 -75
  364. package/Tests/UI/Components/Forms/ModelFormOnBeforeCreateMiscData.test.tsx +254 -0
  365. package/Tests/UI/Components/Icon.test.tsx +32 -0
  366. package/Tests/UI/Components/Input.test.tsx +31 -0
  367. package/Tests/UI/Components/LockedFilterChipScope.test.tsx +501 -0
  368. package/Tests/UI/Components/MarkdownConverters.test.ts +253 -1
  369. package/Tests/UI/Components/MarkdownEditor.test.tsx +2785 -2
  370. package/Tests/UI/Components/MarkdownEditorHistory.test.ts +243 -0
  371. package/Tests/UI/Components/MarkdownListEditing.test.ts +1118 -0
  372. package/Tests/UI/Components/MarkdownPaste.test.ts +1180 -0
  373. package/Tests/UI/Components/MarkdownViewerCopy.test.tsx +466 -0
  374. package/Tests/UI/Components/MarkdownVisualEditing.test.ts +1089 -0
  375. package/Tests/UI/Components/ModelTable/BaseModelTableEmptyStateAction.test.tsx +623 -0
  376. package/Tests/UI/Components/ResetObjectID.test.tsx +282 -0
  377. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  378. package/Tests/UI/Components/Table/EmptyTableMessage.test.ts +439 -0
  379. package/Tests/UI/Components/Table/TableEmptyState.test.tsx +352 -0
  380. package/Tests/UI/Components/TableRowMobileTitles.test.tsx +78 -0
  381. package/Tests/UI/Components/TextArea.test.tsx +19 -0
  382. package/Tests/UI/Components/Workflow/ModelColumnEditor.render.test.tsx +12 -29
  383. package/Tests/UI/Components/fixtures/MarkdownPasteFixtures.ts +460 -0
  384. package/Tests/UI/EsbuildConfig.test.ts +115 -39
  385. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +4 -4
  386. package/Tests/UI/Monitor/MonitorLogSummaryRender.test.tsx +377 -0
  387. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +81 -1
  388. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +17 -0
  389. package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
  390. package/Tests/Utils/Markdown/DashboardMarkdownRenderer.ts +81 -0
  391. package/Tests/Utils/Markdown/UntrustedMarkdown.test.ts +1339 -0
  392. package/Tests/Utils/Monitor/MonitorLogSummaryUtil.test.ts +862 -0
  393. package/Types/AI/AIAgentRunLimits.ts +146 -0
  394. package/Types/Code/CodeType.ts +2 -0
  395. package/Types/Code/JsonSyntax.ts +923 -0
  396. package/Types/CustomField/CustomFieldCreateSettings.ts +549 -0
  397. package/Types/CustomField/CustomFieldMappingCatalog.ts +77 -0
  398. package/Types/CustomField/CustomFieldValueValidator.ts +10 -7
  399. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +1 -1
  400. package/Types/Icon/IconProp.ts +2 -0
  401. package/Types/Incident/IncidentFormIpAllowlist.ts +206 -0
  402. package/Types/Incident/IncidentFormPublic.ts +1145 -0
  403. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +10 -3
  404. package/Types/MessageQueue/MessageQueueIdentity.ts +256 -0
  405. package/Types/MessageQueue/MessageQueueManualIdentity.ts +325 -0
  406. package/Types/MessageQueue/MessageQueueMetricCatalog.ts +1357 -0
  407. package/Types/MessageQueue/MessagingSystem.ts +518 -0
  408. package/Types/MessageQueue/MessagingTelemetryResolver.ts +2311 -0
  409. package/Types/Monitor/MessageQueueAlertTemplates.ts +2128 -0
  410. package/Types/Permission.ts +310 -0
  411. package/Types/ResourceAiAgent/ResourceAiAccess.ts +10 -4
  412. package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
  413. package/Types/Rules/RuleRun.ts +4 -0
  414. package/Types/Team/ComplianceNotificationChannel.ts +4 -3
  415. package/Types/Team/ComplianceRule.ts +71 -18
  416. package/Types/Team/ComplianceRuleType.ts +2 -2
  417. package/Types/Team/TeamComplianceStatus.ts +6 -2
  418. package/Types/Telemetry/EntityType.ts +16 -0
  419. package/Types/Telemetry/LockedFilterDetail.ts +22 -0
  420. package/Types/XML.ts +26 -0
  421. package/UI/Components/CodeEditor/CodeEditor.css +379 -0
  422. package/UI/Components/CodeEditor/CodeEditor.tsx +1128 -294
  423. package/UI/Components/CodeEditor/CodeEditorCommands.ts +774 -0
  424. package/UI/Components/CodeEditor/CodeEditorHighlight.ts +106 -0
  425. package/UI/Components/CodeEditor/CodeEditorLanguages.ts +164 -0
  426. package/UI/Components/CodeEditor/YamlEditor.tsx +28 -326
  427. package/UI/Components/CopyTextButton/CopyTextButton.tsx +5 -1
  428. package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +6 -25
  429. package/UI/Components/EditionLabel/EditionLabel.tsx +14 -13
  430. package/UI/Components/ErrorMessage/ErrorMessage.tsx +11 -1
  431. package/UI/Components/Forms/Fields/FormField.tsx +8 -0
  432. package/UI/Components/Forms/Types/Field.ts +8 -0
  433. package/UI/Components/Icon/Icon.tsx +18 -0
  434. package/UI/Components/Input/Input.tsx +11 -4
  435. package/UI/Components/LogsViewer/LogsViewer.tsx +4 -0
  436. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +21 -3
  437. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  438. package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +877 -79
  439. package/UI/Components/Markdown.tsx/MarkdownEditorHistory.ts +284 -0
  440. package/UI/Components/Markdown.tsx/MarkdownListEditing.ts +1362 -0
  441. package/UI/Components/Markdown.tsx/MarkdownPaste.ts +1326 -0
  442. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +106 -10
  443. package/UI/Components/Markdown.tsx/MarkdownVisualEditing.ts +1032 -0
  444. package/UI/Components/ModelTable/BaseModelTable.tsx +85 -7
  445. package/UI/Components/ResetObjectID/ResetObjectID.tsx +35 -9
  446. package/UI/Components/Table/EmptyTableMessage.ts +81 -0
  447. package/UI/Components/Table/Table.tsx +50 -21
  448. package/UI/Components/Table/TableRow.tsx +9 -1
  449. package/UI/Components/TelemetryViewer/FacetVisibility.ts +97 -2
  450. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +13 -0
  451. package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +214 -7
  452. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +21 -3
  453. package/UI/Components/TextArea/TextArea.tsx +9 -2
  454. package/UI/Components/Workflow/ModelFieldPicker.tsx +10 -12
  455. package/UI/Styles/Theme.css +8 -0
  456. package/UI/esbuild-config.js +2 -32
  457. package/Utils/LabelRuleImportExport.ts +2 -0
  458. package/Utils/Markdown/UntrustedMarkdown.ts +1513 -0
  459. package/Utils/Monitor/IncomingEmailMonitorRequestUtil.ts +41 -0
  460. package/Utils/Monitor/MonitorLogSummaryUtil.ts +212 -0
  461. package/Utils/Telemetry/EntityKey.ts +48 -0
  462. package/build/dist/Models/DatabaseModels/AIConversation.js +125 -1
  463. package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
  464. package/build/dist/Models/DatabaseModels/CephCluster.js +12 -0
  465. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
  466. package/build/dist/Models/DatabaseModels/CloudResource.js +12 -0
  467. package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
  468. package/build/dist/Models/DatabaseModels/DatabaseServer.js +12 -0
  469. package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
  470. package/build/dist/Models/DatabaseModels/DockerHost.js +12 -0
  471. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  472. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +12 -0
  473. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
  474. package/build/dist/Models/DatabaseModels/GlobalOidc.js +0 -4
  475. package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
  476. package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +0 -4
  477. package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
  478. package/build/dist/Models/DatabaseModels/GlobalSso.js +0 -4
  479. package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
  480. package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +0 -4
  481. package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
  482. package/build/dist/Models/DatabaseModels/Host.js +12 -0
  483. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  484. package/build/dist/Models/DatabaseModels/IncidentForm.js +605 -0
  485. package/build/dist/Models/DatabaseModels/IncidentForm.js.map +1 -0
  486. package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js +299 -0
  487. package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js.map +1 -0
  488. package/build/dist/Models/DatabaseModels/IncidentTemplate.js +60 -0
  489. package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
  490. package/build/dist/Models/DatabaseModels/Index.js +14 -0
  491. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  492. package/build/dist/Models/DatabaseModels/IoTFleet.js +12 -0
  493. package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
  494. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +12 -0
  495. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  496. package/build/dist/Models/DatabaseModels/MessageQueue.js +1106 -0
  497. package/build/dist/Models/DatabaseModels/MessageQueue.js.map +1 -0
  498. package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js +562 -0
  499. package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js.map +1 -0
  500. package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js +643 -0
  501. package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js.map +1 -0
  502. package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js +506 -0
  503. package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js.map +1 -0
  504. package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js +505 -0
  505. package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js.map +1 -0
  506. package/build/dist/Models/DatabaseModels/PodmanHost.js +12 -0
  507. package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
  508. package/build/dist/Models/DatabaseModels/Project.js +61 -0
  509. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  510. package/build/dist/Models/DatabaseModels/ProjectOidc.js +0 -4
  511. package/build/dist/Models/DatabaseModels/ProjectOidc.js.map +1 -1
  512. package/build/dist/Models/DatabaseModels/ProjectSso.js +0 -4
  513. package/build/dist/Models/DatabaseModels/ProjectSso.js.map +1 -1
  514. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +12 -0
  515. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
  516. package/build/dist/Models/DatabaseModels/RumApplication.js +12 -0
  517. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  518. package/build/dist/Models/DatabaseModels/ServerlessFunction.js +12 -0
  519. package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
  520. package/build/dist/Models/DatabaseModels/Service.js +12 -0
  521. package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
  522. package/build/dist/Models/DatabaseModels/StatusPageOidc.js +0 -4
  523. package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
  524. package/build/dist/Models/DatabaseModels/StatusPageSso.js +0 -4
  525. package/build/dist/Models/DatabaseModels/StatusPageSso.js.map +1 -1
  526. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +49 -3
  527. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
  528. package/build/dist/Models/DatabaseModels/VMwareVCenter.js +12 -0
  529. package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
  530. package/build/dist/Server/API/AIChatAPI.js +9 -103
  531. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  532. package/build/dist/Server/API/AIInvestigationAPI.js +3 -3
  533. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  534. package/build/dist/Server/API/AIInvestigationConversationAPI.js +162 -0
  535. package/build/dist/Server/API/AIInvestigationConversationAPI.js.map +1 -0
  536. package/build/dist/Server/API/IncidentFormAPI.js +245 -0
  537. package/build/dist/Server/API/IncidentFormAPI.js.map +1 -0
  538. package/build/dist/Server/API/ProjectOIDC.js +16 -24
  539. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  540. package/build/dist/Server/API/ProjectSSO.js +16 -24
  541. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  542. package/build/dist/Server/API/StatusPageAPI.js +42 -75
  543. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  544. package/build/dist/Server/Enterprise/EnterpriseEdition.js +79 -25
  545. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -1
  546. package/build/dist/Server/Enterprise/EnterpriseFeature.js +24 -3
  547. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -1
  548. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +1 -1
  549. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -1
  550. package/build/dist/Server/EnvironmentConfig.js +1 -1
  551. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js +63 -0
  552. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js.map +1 -0
  553. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js +41 -0
  554. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js.map +1 -0
  555. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js +40 -0
  556. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js.map +1 -0
  557. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js +183 -0
  558. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js.map +1 -0
  559. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  560. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  561. package/build/dist/Server/Middleware/IncidentFormRateLimit.js +559 -0
  562. package/build/dist/Server/Middleware/IncidentFormRateLimit.js.map +1 -0
  563. package/build/dist/Server/Middleware/UserAuthorization.js +11 -30
  564. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  565. package/build/dist/Server/Services/AIService.js +10 -13
  566. package/build/dist/Server/Services/AIService.js.map +1 -1
  567. package/build/dist/Server/Services/IncidentCustomFieldService.js +83 -0
  568. package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
  569. package/build/dist/Server/Services/IncidentEpisodeMemberService.js +8 -4
  570. package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
  571. package/build/dist/Server/Services/IncidentEpisodeService.js +10 -1
  572. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  573. package/build/dist/Server/Services/IncidentFormService.js +1202 -0
  574. package/build/dist/Server/Services/IncidentFormService.js.map +1 -0
  575. package/build/dist/Server/Services/IncidentFormSubmissionService.js +91 -0
  576. package/build/dist/Server/Services/IncidentFormSubmissionService.js.map +1 -0
  577. package/build/dist/Server/Services/IncidentGroupingEngineService.js +20 -8
  578. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  579. package/build/dist/Server/Services/IncidentService.js +106 -4
  580. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  581. package/build/dist/Server/Services/IncidentTemplateService.js +18 -0
  582. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  583. package/build/dist/Server/Services/Index.js +14 -0
  584. package/build/dist/Server/Services/Index.js.map +1 -1
  585. package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js +262 -0
  586. package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js.map +1 -0
  587. package/build/dist/Server/Services/MessageQueueLabelRuleService.js +13 -0
  588. package/build/dist/Server/Services/MessageQueueLabelRuleService.js.map +1 -0
  589. package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js +334 -0
  590. package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js.map +1 -0
  591. package/build/dist/Server/Services/MessageQueueOwnerRuleService.js +13 -0
  592. package/build/dist/Server/Services/MessageQueueOwnerRuleService.js.map +1 -0
  593. package/build/dist/Server/Services/MessageQueueOwnerTeamService.js +62 -0
  594. package/build/dist/Server/Services/MessageQueueOwnerTeamService.js.map +1 -0
  595. package/build/dist/Server/Services/MessageQueueOwnerUserService.js +62 -0
  596. package/build/dist/Server/Services/MessageQueueOwnerUserService.js.map +1 -0
  597. package/build/dist/Server/Services/MessageQueueService.js +1140 -0
  598. package/build/dist/Server/Services/MessageQueueService.js.map +1 -0
  599. package/build/dist/Server/Services/OpenTelemetryIngestService.js +25 -4
  600. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  601. package/build/dist/Server/Services/ProjectService.js +0 -54
  602. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  603. package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -4
  604. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  605. package/build/dist/Server/Services/StatusPageService.js +0 -46
  606. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  607. package/build/dist/Server/Services/TeamComplianceSettingService.js +120 -31
  608. package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
  609. package/build/dist/Server/Services/UserNotificationRuleService.js +8 -1
  610. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  611. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +12 -3
  612. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
  613. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +6 -3
  614. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  615. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +109 -37
  616. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  617. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +16 -0
  618. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  619. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +3 -3
  620. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +9 -6
  621. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  622. package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js +128 -0
  623. package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js.map +1 -0
  624. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +192 -50
  625. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  626. package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js +133 -0
  627. package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js.map +1 -0
  628. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +53 -13
  629. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  630. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
  631. package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js +206 -0
  632. package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js.map +1 -0
  633. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +53 -26
  634. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
  635. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +4 -2
  636. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
  637. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +1 -29
  638. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
  639. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +24 -24
  640. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
  641. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +7 -2
  642. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  643. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +29 -14
  644. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  645. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +38 -14
  646. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -1
  647. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +2 -0
  648. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -1
  649. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +40 -10
  650. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  651. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +19 -7
  652. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  653. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +19 -7
  654. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  655. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +15 -18
  656. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  657. package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js +412 -0
  658. package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js.map +1 -0
  659. package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js +495 -0
  660. package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js.map +1 -0
  661. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +10 -3
  662. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -1
  663. package/build/dist/Server/Utils/EditionEnforcement.js +20 -158
  664. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -1
  665. package/build/dist/Server/Utils/LLM/LLMService.js +193 -54
  666. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  667. package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js +160 -0
  668. package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js.map +1 -0
  669. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
  670. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  671. package/build/dist/Server/Utils/SameOriginRequest.js +151 -0
  672. package/build/dist/Server/Utils/SameOriginRequest.js.map +1 -0
  673. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
  674. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
  675. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -1
  676. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  677. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +1015 -0
  678. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -0
  679. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +4 -1
  680. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
  681. package/build/dist/Server/Utils/VendorAssets.js +3 -3
  682. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +3 -1
  683. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  684. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +3 -1
  685. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  686. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +10 -1
  687. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  688. package/build/dist/Types/AI/AIAgentRunLimits.js +91 -0
  689. package/build/dist/Types/AI/AIAgentRunLimits.js.map +1 -0
  690. package/build/dist/Types/Code/CodeType.js +2 -0
  691. package/build/dist/Types/Code/CodeType.js.map +1 -1
  692. package/build/dist/Types/Code/JsonSyntax.js +604 -0
  693. package/build/dist/Types/Code/JsonSyntax.js.map +1 -0
  694. package/build/dist/Types/CustomField/CustomFieldCreateSettings.js +310 -0
  695. package/build/dist/Types/CustomField/CustomFieldCreateSettings.js.map +1 -0
  696. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +38 -0
  697. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -1
  698. package/build/dist/Types/CustomField/CustomFieldValueValidator.js +10 -7
  699. package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -1
  700. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +1 -1
  701. package/build/dist/Types/Icon/IconProp.js +2 -0
  702. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  703. package/build/dist/Types/Incident/IncidentFormIpAllowlist.js +119 -0
  704. package/build/dist/Types/Incident/IncidentFormIpAllowlist.js.map +1 -0
  705. package/build/dist/Types/Incident/IncidentFormPublic.js +678 -0
  706. package/build/dist/Types/Incident/IncidentFormPublic.js.map +1 -0
  707. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +10 -3
  708. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
  709. package/build/dist/Types/MessageQueue/MessageQueueIdentity.js +184 -0
  710. package/build/dist/Types/MessageQueue/MessageQueueIdentity.js.map +1 -0
  711. package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js +190 -0
  712. package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js.map +1 -0
  713. package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js +1057 -0
  714. package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js.map +1 -0
  715. package/build/dist/Types/MessageQueue/MessagingSystem.js +394 -0
  716. package/build/dist/Types/MessageQueue/MessagingSystem.js.map +1 -0
  717. package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js +1768 -0
  718. package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js.map +1 -0
  719. package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js +1207 -0
  720. package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js.map +1 -0
  721. package/build/dist/Types/Permission.js +274 -0
  722. package/build/dist/Types/Permission.js.map +1 -1
  723. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +10 -4
  724. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -1
  725. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +12 -0
  726. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  727. package/build/dist/Types/Rules/RuleRun.js +4 -0
  728. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  729. package/build/dist/Types/Team/ComplianceNotificationChannel.js +4 -3
  730. package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -1
  731. package/build/dist/Types/Team/ComplianceRule.js +48 -14
  732. package/build/dist/Types/Team/ComplianceRule.js.map +1 -1
  733. package/build/dist/Types/Team/ComplianceRuleType.js +2 -2
  734. package/build/dist/Types/Telemetry/EntityType.js +16 -0
  735. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  736. package/build/dist/Types/XML.js +23 -0
  737. package/build/dist/Types/XML.js.map +1 -1
  738. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +641 -266
  739. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  740. package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js +464 -0
  741. package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js.map +1 -0
  742. package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js +69 -0
  743. package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js.map +1 -0
  744. package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js +108 -0
  745. package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js.map +1 -0
  746. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +14 -186
  747. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -1
  748. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
  749. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
  750. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +5 -14
  751. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -1
  752. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +14 -13
  753. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  754. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +1 -1
  755. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
  756. package/build/dist/UI/Components/Forms/Fields/FormField.js +8 -3
  757. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  758. package/build/dist/UI/Components/Icon/Icon.js +8 -0
  759. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  760. package/build/dist/UI/Components/Input/Input.js +11 -3
  761. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  762. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +2 -1
  763. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  764. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +14 -4
  765. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  766. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  767. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  768. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +710 -65
  769. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
  770. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js +238 -0
  771. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js.map +1 -0
  772. package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js +1028 -0
  773. package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js.map +1 -0
  774. package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js +1088 -0
  775. package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js.map +1 -0
  776. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +70 -10
  777. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  778. package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js +887 -0
  779. package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js.map +1 -0
  780. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +57 -6
  781. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  782. package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js +7 -5
  783. package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js.map +1 -1
  784. package/build/dist/UI/Components/Table/EmptyTableMessage.js +51 -0
  785. package/build/dist/UI/Components/Table/EmptyTableMessage.js.map +1 -0
  786. package/build/dist/UI/Components/Table/Table.js +30 -11
  787. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  788. package/build/dist/UI/Components/Table/TableRow.js +9 -2
  789. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  790. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +63 -1
  791. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -1
  792. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +4 -2
  793. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  794. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +91 -10
  795. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
  796. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +14 -4
  797. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  798. package/build/dist/UI/Components/TextArea/TextArea.js +9 -3
  799. package/build/dist/UI/Components/TextArea/TextArea.js.map +1 -1
  800. package/build/dist/UI/Components/Workflow/ModelFieldPicker.js +1 -2
  801. package/build/dist/UI/Components/Workflow/ModelFieldPicker.js.map +1 -1
  802. package/build/dist/Utils/LabelRuleImportExport.js +2 -0
  803. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  804. package/build/dist/Utils/Markdown/UntrustedMarkdown.js +988 -0
  805. package/build/dist/Utils/Markdown/UntrustedMarkdown.js.map +1 -0
  806. package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js +34 -0
  807. package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js.map +1 -0
  808. package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js +148 -0
  809. package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js.map +1 -0
  810. package/build/dist/Utils/Telemetry/EntityKey.js +36 -0
  811. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  812. package/package.json +1 -3
  813. package/Server/Utils/CommunityEditionSsoReport.ts +0 -361
  814. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +0 -616
  815. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +0 -217
  816. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +0 -271
  817. package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +0 -215
  818. package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +0 -784
  819. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +0 -518
  820. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +0 -419
  821. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +0 -769
  822. package/Tests/UI/Components/CodeEditor.test.tsx +0 -638
  823. package/Tests/UI/Components/MonacoLoader.test.ts +0 -67
  824. package/Tests/UI/Components/MonacoRuntime.test.ts +0 -121
  825. package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +0 -329
  826. package/Tests/UI/Components/YamlEditor.test.tsx +0 -847
  827. package/UI/Components/CodeEditor/MonacoLoader.ts +0 -36
  828. package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +0 -319
  829. package/UI/Components/Telemetry/TelemetryRetentionConfigSummary.tsx +0 -223
  830. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +0 -223
  831. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +0 -1
  832. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +0 -34
  833. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +0 -1
  834. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +0 -171
  835. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +0 -1
  836. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js +0 -119
  837. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js.map +0 -1
@@ -0,0 +1,1271 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import Entities from "../../../Models/DatabaseModels/Index";
3
+ import MessageQueue from "../../../Models/DatabaseModels/MessageQueue";
4
+ import GlobalCache from "../../../Server/Infrastructure/GlobalCache";
5
+ import PostgresAppInstance from "../../../Server/Infrastructure/PostgresDatabase";
6
+ import MessageQueueLabelRuleEngineService from "../../../Server/Services/MessageQueueLabelRuleEngineService";
7
+ import MessageQueueOwnerRuleEngineService from "../../../Server/Services/MessageQueueOwnerRuleEngineService";
8
+ import MessageQueueService, {
9
+ MessageQueueFindOrCreateResult,
10
+ } from "../../../Server/Services/MessageQueueService";
11
+ import logger from "../../../Server/Utils/Logger";
12
+ import SingleFlight from "../../../Server/Utils/SingleFlight";
13
+ import {
14
+ DiscoveredMessageQueue,
15
+ MessagingMetricDiscoveryRow,
16
+ getMessagingDiscoveryColumn,
17
+ resolveMessagingMetricDiscoveryRows,
18
+ } from "../../../Server/Utils/Telemetry/MessageQueueDiscovery";
19
+ import ResourceHeartbeat from "../../../Server/Utils/Telemetry/ResourceHeartbeat";
20
+ import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
21
+ import {
22
+ MessageQueueIdentity,
23
+ buildMessageQueueDisplayName,
24
+ toMessageQueueIdentity,
25
+ } from "../../../Types/MessageQueue/MessageQueueIdentity";
26
+ import { MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES } from "../../../Types/MessageQueue/MessagingTelemetryResolver";
27
+ import ObjectID from "../../../Types/ObjectID";
28
+ import Permission, { UserPermission } from "../../../Types/Permission";
29
+ import { DataSource } from "typeorm";
30
+
31
+ /*
32
+ * The hand-written Postgres of the Queues product, EXECUTED - not string
33
+ * matched. The unit suites replace manager.query with a mock, so a renamed
34
+ * join table or column (MessageQueueLabel, automaticAssignments, ...) or a
35
+ * name predicate Postgres reads differently from the TypeScript that wrote
36
+ * the name would pass them and then fail - or archive the wrong queues - in
37
+ * production every five minutes. Here the real service methods run against
38
+ * structure-only clones of the MIGRATED tables:
39
+ *
40
+ * - the (projectId, queueIdentifier) partial unique index, and
41
+ * findOrCreateByIdentity racing itself on it;
42
+ * - the family refinement compare-and-set and the auto-archive restore;
43
+ * - the auto-archive sweep (every "untouched" rule - description, rename,
44
+ * a person's labels and owners vs a rule's, a person's restore - its
45
+ * window, its batch bound and its order) and the budget count;
46
+ * - the automaticAssignments bookkeeping;
47
+ * - the sighting heartbeat's hook-free write;
48
+ * - a person adding a queue and restoring one through the real create and
49
+ * update pipelines.
50
+ *
51
+ * Opt in with RUN_POSTGRES_MESSAGE_QUEUE_SQL_TESTS=true against a Postgres
52
+ * migrated to the current head (the clones copy public.<table>) - the
53
+ * Postgres Schema Drift workflow's database right after its drift check, as
54
+ * for DatabaseServerSqlPostgres. Credentials from DATABASE_USERNAME /
55
+ * DATABASE_PASSWORD, database from MESSAGE_QUEUE_SQL_TEST_DATABASE_NAME or
56
+ * DATABASE_NAME, endpoint from MESSAGE_QUEUE_SQL_TEST_DATABASE_HOST / _PORT
57
+ * (default localhost:5400, Scripts/Dev/docker-compose.dev.yml). Every table
58
+ * and row lives in a unique schema that is dropped afterwards; search_path
59
+ * holds only that schema, so a statement naming a table that was not cloned
60
+ * fails loudly instead of touching real data.
61
+ */
62
+ const describePostgres: typeof describe =
63
+ process.env["RUN_POSTGRES_MESSAGE_QUEUE_SQL_TESTS"] === "true"
64
+ ? describe
65
+ : describe.skip;
66
+
67
+ const DAY_MS: number = 24 * 60 * 60 * 1000;
68
+
69
+ // Tables the SQL under test reads or writes.
70
+ const TABLES: Array<string> = [
71
+ "MessageQueue",
72
+ "MessageQueueLabel",
73
+ "MessageQueueOwnerUser",
74
+ "MessageQueueOwnerTeam",
75
+ "Label",
76
+ ];
77
+
78
+ /*
79
+ * Tables only ever seeded by hand here: their NOT NULL columns are relaxed
80
+ * so a fixture names only what the SQL reads. MessageQueue keeps every
81
+ * constraint - the ORM writes it.
82
+ */
83
+ const FIXTURE_TABLES: Array<string> = TABLES.filter((table: string) => {
84
+ return table !== "MessageQueue";
85
+ });
86
+
87
+ describePostgres("Queues SQL against Postgres", () => {
88
+ const schema: string = `message_queue_sql_${ObjectID.generate()
89
+ .toString()
90
+ .replace(/-/g, "")}`;
91
+ const projectId: ObjectID = ObjectID.generate();
92
+ const otherProjectId: ObjectID = ObjectID.generate();
93
+ const userId: ObjectID = ObjectID.generate();
94
+ const teamId: ObjectID = ObjectID.generate();
95
+ let database: DataSource;
96
+ let cache: Map<string, string>;
97
+
98
+ function silence(): void {
99
+ for (const level of ["debug", "info", "warn"] as const) {
100
+ jest.spyOn(logger, level).mockImplementation(() => {
101
+ return undefined as never;
102
+ });
103
+ }
104
+ }
105
+
106
+ // A faithful in-memory Redis for the heartbeat's atomic gates.
107
+ function mockCache(): void {
108
+ jest
109
+ .spyOn(GlobalCache, "setStringIfNotExists")
110
+ .mockImplementation(async (ns: string, key: string, value: string) => {
111
+ const full: string = `${ns}:${key}`;
112
+ if (cache.has(full)) {
113
+ return false;
114
+ }
115
+ cache.set(full, value);
116
+ return true;
117
+ });
118
+ jest
119
+ .spyOn(GlobalCache, "setStringIfChanged")
120
+ .mockImplementation(async (ns: string, key: string, value: string) => {
121
+ const full: string = `${ns}:${key}`;
122
+ if (cache.get(full) === value) {
123
+ return false;
124
+ }
125
+ cache.set(full, value);
126
+ return true;
127
+ });
128
+ jest
129
+ .spyOn(GlobalCache, "deleteKey")
130
+ .mockImplementation(async (ns: string, key: string) => {
131
+ cache.delete(`${ns}:${key}`);
132
+ });
133
+ }
134
+
135
+ beforeAll(async () => {
136
+ database = new DataSource({
137
+ type: "postgres",
138
+ host: process.env["MESSAGE_QUEUE_SQL_TEST_DATABASE_HOST"] || "localhost",
139
+ port: Number(
140
+ process.env["MESSAGE_QUEUE_SQL_TEST_DATABASE_PORT"] || "5400",
141
+ ),
142
+ username: process.env["DATABASE_USERNAME"] || "postgres",
143
+ password: process.env["DATABASE_PASSWORD"] || "password",
144
+ database:
145
+ process.env["MESSAGE_QUEUE_SQL_TEST_DATABASE_NAME"] ||
146
+ process.env["DATABASE_NAME"] ||
147
+ "oneuptimedb",
148
+ entities: Entities,
149
+ schema,
150
+ synchronize: false,
151
+ extra: { options: `-c search_path=${schema}` },
152
+ });
153
+ await database.initialize();
154
+ await database.query(`CREATE SCHEMA "${schema}"`);
155
+ for (const table of TABLES) {
156
+ await database.query(
157
+ `CREATE TABLE "${schema}"."${table}" (LIKE public."${table}" INCLUDING ALL)`,
158
+ );
159
+ }
160
+ for (const table of FIXTURE_TABLES) {
161
+ // Primary-key columns (a join table's pair included) stay NOT NULL.
162
+ const columns: Array<{ column_name: string }> = await database.query(
163
+ `SELECT c.column_name FROM information_schema.columns c
164
+ WHERE c.table_schema = $1 AND c.table_name = $2 AND c.is_nullable = 'NO'
165
+ AND c.column_name NOT IN (
166
+ SELECT a.attname FROM pg_index i
167
+ INNER JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
168
+ WHERE i.indrelid = format('%I.%I', $1::text, $2::text)::regclass AND i.indisprimary
169
+ )`,
170
+ [schema, table],
171
+ );
172
+ for (const column of columns) {
173
+ await database.query(
174
+ `ALTER TABLE "${schema}"."${table}" ALTER COLUMN "${column.column_name}" DROP NOT NULL`,
175
+ );
176
+ }
177
+ }
178
+ expect(
179
+ (await database.query("SELECT current_schema()"))[0].current_schema,
180
+ ).toBe(schema);
181
+ });
182
+
183
+ afterAll(async () => {
184
+ if (database?.isInitialized) {
185
+ await database.query(`DROP SCHEMA IF EXISTS "${schema}" CASCADE`);
186
+ await database.destroy();
187
+ }
188
+ });
189
+
190
+ let labelRules: jest.SpyInstance;
191
+ let ownerRules: jest.SpyInstance;
192
+
193
+ beforeEach(async () => {
194
+ silence();
195
+ cache = new Map<string, string>();
196
+ mockCache();
197
+ SingleFlight.clear();
198
+ ResourceHeartbeat.clearRecentHeartbeatMemo();
199
+ jest.spyOn(PostgresAppInstance, "isConnected").mockReturnValue(true);
200
+ jest.spyOn(PostgresAppInstance, "getDataSource").mockReturnValue(database);
201
+ labelRules = jest
202
+ .spyOn(MessageQueueLabelRuleEngineService, "applyRulesToMessageQueue")
203
+ .mockResolvedValue(undefined);
204
+ ownerRules = jest
205
+ .spyOn(MessageQueueOwnerRuleEngineService, "applyRulesToMessageQueue")
206
+ .mockResolvedValue(undefined);
207
+ jest
208
+ .spyOn(MessageQueueService as any, "onTriggerRealtime")
209
+ .mockResolvedValue(undefined);
210
+ jest
211
+ .spyOn(MessageQueueService as any, "onTriggerWorkflow")
212
+ .mockResolvedValue(undefined);
213
+ MessageQueueService.clearAutoCreateBudgetMemo();
214
+ await database.query(
215
+ TABLES.map((table: string): string => {
216
+ return `DELETE FROM "${schema}"."${table}"`;
217
+ }).join("; "),
218
+ );
219
+ });
220
+
221
+ afterEach(() => {
222
+ jest.restoreAllMocks();
223
+ SingleFlight.clear();
224
+ ResourceHeartbeat.clearRecentHeartbeatMemo();
225
+ });
226
+
227
+ function ago(ms: number): Date {
228
+ return new Date(Date.now() - ms);
229
+ }
230
+
231
+ function identityOf(value: {
232
+ system: string;
233
+ brokerScope?: string;
234
+ destination: string;
235
+ }): MessageQueueIdentity {
236
+ const identity: MessageQueueIdentity | null = toMessageQueueIdentity(value);
237
+ if (!identity) {
238
+ throw new Error(`not an identity: ${JSON.stringify(value)}`);
239
+ }
240
+ return identity;
241
+ }
242
+
243
+ async function insertQueue(data: {
244
+ name?: string;
245
+ destinationName?: string;
246
+ queueIdentifier?: string;
247
+ messagingSystem?: string;
248
+ description?: string | null;
249
+ project?: ObjectID;
250
+ source?: string | null;
251
+ lastSeenAt?: Date | null;
252
+ createdAt?: Date;
253
+ isArchived?: boolean;
254
+ archivedAt?: Date | null;
255
+ autoArchivedAt?: Date | null;
256
+ manuallyRestoredAt?: Date | null;
257
+ automaticAssignments?: unknown;
258
+ deletedAt?: Date | null;
259
+ }): Promise<ObjectID> {
260
+ const id: ObjectID = ObjectID.generate();
261
+ const destination: string =
262
+ data.destinationName || `queue-${id.toString().substring(0, 8)}`;
263
+ await database.query(
264
+ `INSERT INTO "${schema}"."MessageQueue" (
265
+ "_id", "version", "projectId", "name", "slug", "queueIdentifier",
266
+ "messagingSystem", "destinationName", "description", "discoverySource",
267
+ "lastSeenAt", "createdAt", "isArchived", "archivedAt", "autoArchivedAt",
268
+ "manuallyRestoredAt", "automaticAssignments", "deletedAt"
269
+ ) VALUES ($1, 1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)`,
270
+ [
271
+ id.toString(),
272
+ (data.project || projectId).toString(),
273
+ data.name === undefined ? destination : data.name,
274
+ `${destination.substring(0, 60)}-${id.toString()}`,
275
+ data.queueIdentifier || `kafka||${destination.toLowerCase()}`,
276
+ data.messagingSystem || "kafka",
277
+ destination,
278
+ data.description ?? null,
279
+ data.source === undefined ? "traces" : data.source,
280
+ data.lastSeenAt === undefined ? ago(10 * DAY_MS) : data.lastSeenAt,
281
+ data.createdAt || ago(30 * DAY_MS),
282
+ Boolean(data.isArchived),
283
+ data.archivedAt ?? null,
284
+ data.autoArchivedAt ?? null,
285
+ data.manuallyRestoredAt ?? null,
286
+ data.automaticAssignments === undefined
287
+ ? null
288
+ : JSON.stringify(data.automaticAssignments),
289
+ data.deletedAt ?? null,
290
+ ],
291
+ );
292
+ return id;
293
+ }
294
+
295
+ async function insertRow(
296
+ table: string,
297
+ values: Record<string, unknown>,
298
+ ): Promise<ObjectID> {
299
+ const id: ObjectID = ObjectID.generate();
300
+ const columns: Array<string> = ["_id", ...Object.keys(values)];
301
+ const parameters: Array<unknown> = [
302
+ id.toString(),
303
+ ...Object.values(values),
304
+ ];
305
+ await database.query(
306
+ `INSERT INTO "${schema}"."${table}" (${columns
307
+ .map((column: string): string => {
308
+ return `"${column}"`;
309
+ })
310
+ .join(", ")}) VALUES (${parameters
311
+ .map((_value: unknown, index: number): string => {
312
+ return `$${index + 1}`;
313
+ })
314
+ .join(", ")})`,
315
+ parameters.map((value: unknown): unknown => {
316
+ return value instanceof ObjectID ? value.toString() : value;
317
+ }),
318
+ );
319
+ return id;
320
+ }
321
+
322
+ async function link(
323
+ table: string,
324
+ columns: Record<string, ObjectID>,
325
+ ): Promise<void> {
326
+ const names: Array<string> = Object.keys(columns);
327
+ await database.query(
328
+ `INSERT INTO "${schema}"."${table}" (${names
329
+ .map((name: string): string => {
330
+ return `"${name}"`;
331
+ })
332
+ .join(", ")}) VALUES (${names
333
+ .map((_name: string, index: number): string => {
334
+ return `$${index + 1}`;
335
+ })
336
+ .join(", ")})`,
337
+ Object.values(columns).map((value: ObjectID): string => {
338
+ return value.toString();
339
+ }),
340
+ );
341
+ }
342
+
343
+ async function queueState(id: ObjectID): Promise<any> {
344
+ const rows: Array<any> = await database.query(
345
+ `SELECT * FROM "${schema}"."MessageQueue" WHERE "_id" = $1`,
346
+ [id.toString()],
347
+ );
348
+ return rows[0];
349
+ }
350
+
351
+ async function liveQueues(): Promise<Array<any>> {
352
+ return await database.query(
353
+ `SELECT * FROM "${schema}"."MessageQueue" WHERE "deletedAt" IS NULL ORDER BY "createdAt"`,
354
+ );
355
+ }
356
+
357
+ function flushPromises(): Promise<void> {
358
+ return new Promise((resolve: () => void) => {
359
+ setTimeout(resolve, 0);
360
+ });
361
+ }
362
+
363
+ function personProps(
364
+ permissions: Array<Permission>,
365
+ ): DatabaseCommonInteractionProps {
366
+ return {
367
+ userId: userId,
368
+ tenantId: projectId,
369
+ userGlobalAccessPermission: {
370
+ projectIds: [projectId],
371
+ globalPermissions: [Permission.Public, Permission.User],
372
+ _type: "UserGlobalAccessPermission",
373
+ },
374
+ userTenantAccessPermission: {
375
+ [projectId.toString()]: {
376
+ projectId: projectId,
377
+ permissions: permissions.map(
378
+ (permission: Permission): UserPermission => {
379
+ return {
380
+ permission,
381
+ labelIds: [],
382
+ isBlockPermission: false,
383
+ _type: "UserPermission",
384
+ };
385
+ },
386
+ ),
387
+ _type: "UserTenantAccessPermission",
388
+ },
389
+ },
390
+ userTeamIds: [],
391
+ };
392
+ }
393
+
394
+ /*
395
+ * -------------------------------------------------------------------------
396
+ * Identity
397
+ * -------------------------------------------------------------------------
398
+ */
399
+ test("the identity index keeps one LIVE row per project and identifier", async () => {
400
+ await insertQueue({
401
+ destinationName: "orders",
402
+ queueIdentifier: "kafka||orders",
403
+ });
404
+
405
+ await expect(
406
+ insertQueue({
407
+ destinationName: "orders",
408
+ queueIdentifier: "kafka||orders",
409
+ }),
410
+ ).rejects.toThrow(/IDX_message_queue_identifier|unique/);
411
+
412
+ // Another project, or a deleted row, never collides.
413
+ await insertQueue({
414
+ destinationName: "orders",
415
+ queueIdentifier: "kafka||orders",
416
+ project: otherProjectId,
417
+ });
418
+ await insertQueue({
419
+ destinationName: "payments",
420
+ queueIdentifier: "kafka||payments",
421
+ deletedAt: new Date(),
422
+ });
423
+ await insertQueue({
424
+ destinationName: "payments",
425
+ queueIdentifier: "kafka||payments",
426
+ });
427
+
428
+ /*
429
+ * The migrated schema carries the index under the name the model declares
430
+ * (a clone made with LIKE ... INCLUDING ALL renames it, so the name is
431
+ * read from public).
432
+ */
433
+ for (const [schemaName, indexName] of [
434
+ ["public", "IDX_message_queue_identifier"],
435
+ [schema, null],
436
+ ] as Array<[string, string | null]>) {
437
+ const indexes: Array<{ indexname: string; indexdef: string }> =
438
+ await database.query(
439
+ `SELECT indexname, indexdef FROM pg_indexes WHERE schemaname = $1 AND tablename = 'MessageQueue' AND indexdef LIKE '%("projectId", "queueIdentifier")%'`,
440
+ [schemaName],
441
+ );
442
+ expect(indexes).toHaveLength(1);
443
+ if (indexName) {
444
+ expect(indexes[0]!.indexname).toBe(indexName);
445
+ }
446
+ expect(indexes[0]!.indexdef).toContain("CREATE UNIQUE INDEX");
447
+ expect(indexes[0]!.indexdef).toContain('WHERE ("deletedAt" IS NULL)');
448
+ }
449
+ });
450
+
451
+ test("findOrCreateByIdentity creates once, then finds - with the columns discovery owns", async () => {
452
+ const first: MessageQueueFindOrCreateResult =
453
+ await MessageQueueService.findOrCreateByIdentity({
454
+ projectId: projectId,
455
+ identity: identityOf({ system: "jms", destination: "orders" }),
456
+ system: "activemq",
457
+ destination: "Orders",
458
+ brokerAddress: "broker-1.internal:61616",
459
+ source: "broker-metrics",
460
+ allowCreate: true,
461
+ });
462
+
463
+ expect(first.created).toBe(true);
464
+ const stored: any = await queueState(first.queue!.id!);
465
+ expect(stored.queueIdentifier).toBe("jms||orders");
466
+ expect(stored.messagingSystem).toBe("activemq");
467
+ expect(stored.destinationName).toBe("Orders");
468
+ expect(stored.name).toBe("Orders");
469
+ expect(stored.brokerAddress).toBe("broker-1.internal:61616");
470
+ expect(stored.discoverySource).toBe("broker-metrics");
471
+ expect(stored.lastSeenAt).toBeInstanceOf(Date);
472
+ // Left to the broker-metrics sighting that follows: its only writer.
473
+ expect(stored.brokerMetricsLastSeenAt).toBeNull();
474
+ expect(stored.isArchived).toBe(false);
475
+ expect(stored.slug).toBeTruthy();
476
+ await flushPromises();
477
+ expect(labelRules).toHaveBeenCalledTimes(1);
478
+ expect(ownerRules).toHaveBeenCalledTimes(1);
479
+
480
+ // Any spelling of the identity finds the same row.
481
+ const second: MessageQueueFindOrCreateResult =
482
+ await MessageQueueService.findOrCreateByIdentity({
483
+ projectId: projectId,
484
+ identity: {
485
+ system: "ActiveMQ",
486
+ brokerScope: "",
487
+ destination: "ORDERS",
488
+ },
489
+ system: "jms",
490
+ destination: "ORDERS",
491
+ source: "traces",
492
+ allowCreate: true,
493
+ });
494
+
495
+ expect(second.created).toBe(false);
496
+ expect(second.queue!.id!.toString()).toBe(first.queue!.id!.toString());
497
+ expect(await liveQueues()).toHaveLength(1);
498
+ });
499
+
500
+ test("racing writers end with one row and one creator; every loser gets the winner", async () => {
501
+ const results: Array<MessageQueueFindOrCreateResult> = await Promise.all(
502
+ Array.from({ length: 8 }, () => {
503
+ return MessageQueueService.findOrCreateByIdentity({
504
+ projectId: projectId,
505
+ identity: identityOf({
506
+ system: "kafka",
507
+ destination: "orders.created",
508
+ }),
509
+ system: "kafka",
510
+ destination: "orders.created",
511
+ source: "traces",
512
+ allowCreate: true,
513
+ });
514
+ }),
515
+ );
516
+
517
+ const rows: Array<any> = await liveQueues();
518
+ expect(rows).toHaveLength(1);
519
+ expect(
520
+ results.filter((result: MessageQueueFindOrCreateResult): boolean => {
521
+ return result.created;
522
+ }),
523
+ ).toHaveLength(1);
524
+ for (const result of results) {
525
+ expect(result.queue!.id!.toString()).toBe(rows[0]._id);
526
+ }
527
+ await flushPromises();
528
+ // Only the winner ran the rule engines.
529
+ expect(labelRules).toHaveBeenCalledTimes(1);
530
+ });
531
+
532
+ test("a sighting refines jms to activemq in the database - never back, never across", async () => {
533
+ const id: ObjectID = await insertQueue({
534
+ destinationName: "orders",
535
+ queueIdentifier: "jms||orders",
536
+ messagingSystem: "jms",
537
+ lastSeenAt: new Date(),
538
+ });
539
+ const sight: (system: string) => Promise<void> = async (
540
+ system: string,
541
+ ): Promise<void> => {
542
+ await MessageQueueService.findOrCreateByIdentity({
543
+ projectId: projectId,
544
+ identity: identityOf({ system: "jms", destination: "orders" }),
545
+ system: system,
546
+ destination: "orders",
547
+ source: "traces",
548
+ allowCreate: false,
549
+ });
550
+ };
551
+
552
+ await sight("kafka");
553
+ expect((await queueState(id)).messagingSystem).toBe("jms");
554
+
555
+ await sight("activemq");
556
+ expect((await queueState(id)).messagingSystem).toBe("activemq");
557
+
558
+ await sight("jms");
559
+ expect((await queueState(id)).messagingSystem).toBe("activemq");
560
+ });
561
+
562
+ test("discovery restores only a row it archived itself", async () => {
563
+ const autoArchived: ObjectID = await insertQueue({
564
+ destinationName: "auto",
565
+ queueIdentifier: "kafka||auto",
566
+ isArchived: true,
567
+ archivedAt: ago(DAY_MS),
568
+ autoArchivedAt: ago(DAY_MS),
569
+ });
570
+ const archivedByPerson: ObjectID = await insertQueue({
571
+ destinationName: "person",
572
+ queueIdentifier: "kafka||person",
573
+ isArchived: true,
574
+ archivedAt: ago(DAY_MS),
575
+ });
576
+
577
+ for (const destination of ["auto", "person"]) {
578
+ await MessageQueueService.findOrCreateByIdentity({
579
+ projectId: projectId,
580
+ identity: identityOf({ system: "kafka", destination }),
581
+ system: "kafka",
582
+ destination,
583
+ source: "traces",
584
+ allowCreate: false,
585
+ });
586
+ }
587
+
588
+ const restored: any = await queueState(autoArchived);
589
+ expect(restored.isArchived).toBe(false);
590
+ expect(restored.archivedAt).toBeNull();
591
+ expect(restored.autoArchivedAt).toBeNull();
592
+ expect((await queueState(archivedByPerson)).isArchived).toBe(true);
593
+ });
594
+
595
+ /*
596
+ * -------------------------------------------------------------------------
597
+ * The sweep
598
+ * -------------------------------------------------------------------------
599
+ */
600
+ test("the auto-archive sweep archives exactly the stale rows nobody invested in", async () => {
601
+ const archived: Map<string, ObjectID> = new Map();
602
+ const kept: Map<string, ObjectID> = new Map();
603
+
604
+ archived.set("plain stale", await insertQueue({}));
605
+ kept.set("manual", await insertQueue({ source: "manual" }));
606
+ kept.set("no discovery source", await insertQueue({ source: null }));
607
+ kept.set("seen yesterday", await insertQueue({ lastSeenAt: ago(DAY_MS) }));
608
+ archived.set(
609
+ "never seen, created long ago",
610
+ await insertQueue({ lastSeenAt: null, createdAt: ago(20 * DAY_MS) }),
611
+ );
612
+ kept.set(
613
+ "never seen, created yesterday",
614
+ await insertQueue({ lastSeenAt: null, createdAt: ago(DAY_MS) }),
615
+ );
616
+ kept.set(
617
+ "already archived by a person",
618
+ await insertQueue({ isArchived: true, archivedAt: ago(20 * DAY_MS) }),
619
+ );
620
+ kept.set("deleted", await insertQueue({ deletedAt: new Date() }));
621
+ archived.set(
622
+ "broker metrics source",
623
+ await insertQueue({ source: "broker-metrics" }),
624
+ );
625
+
626
+ // A description or a rename is a person's investment; a blank one is not.
627
+ kept.set(
628
+ "described",
629
+ await insertQueue({ description: "Checkout order events" }),
630
+ );
631
+ archived.set("blank description", await insertQueue({ description: " " }));
632
+ kept.set("renamed", await insertQueue({ name: "Orders (production)" }));
633
+
634
+ /*
635
+ * A destination longer than the name column gets a clamped name
636
+ * (buildMessageQueueDisplayName) - which Postgres must still read as
637
+ * discovery's own, with the trailing spaces the clamp trimmed.
638
+ */
639
+ const longDestination: string = `orders-${"x".repeat(150)}`;
640
+ archived.set(
641
+ "long destination, generated name",
642
+ await insertQueue({
643
+ destinationName: longDestination,
644
+ name: buildMessageQueueDisplayName({ destination: longDestination }),
645
+ }),
646
+ );
647
+ const spacedDestination: string = `${"a".repeat(98)} ${"b".repeat(40)}`;
648
+ expect(
649
+ buildMessageQueueDisplayName({ destination: spacedDestination }),
650
+ ).toBe(`${"a".repeat(98)}…`);
651
+ archived.set(
652
+ "long destination cut at a space, generated name",
653
+ await insertQueue({
654
+ destinationName: spacedDestination,
655
+ name: buildMessageQueueDisplayName({ destination: spacedDestination }),
656
+ }),
657
+ );
658
+ kept.set(
659
+ "long destination, renamed",
660
+ await insertQueue({
661
+ destinationName: `payments-${"y".repeat(150)}`,
662
+ name: "Payments",
663
+ }),
664
+ );
665
+
666
+ // Labels: a person's count, a rule's do not.
667
+ const labelA: ObjectID = await insertRow("Label", {
668
+ projectId: projectId,
669
+ name: "a",
670
+ });
671
+ const labelB: ObjectID = await insertRow("Label", {
672
+ projectId: projectId,
673
+ name: "b",
674
+ });
675
+ const foreignLabel: ObjectID = await insertRow("Label", {
676
+ projectId: otherProjectId,
677
+ name: "x",
678
+ });
679
+ const deletedLabel: ObjectID = await insertRow("Label", {
680
+ projectId: projectId,
681
+ name: "d",
682
+ deletedAt: new Date(),
683
+ });
684
+ const humanLabelled: ObjectID = await insertQueue({});
685
+ await link("MessageQueueLabel", {
686
+ messageQueueId: humanLabelled,
687
+ labelId: labelA,
688
+ });
689
+ kept.set("labelled by a person", humanLabelled);
690
+ const ruleLabelled: ObjectID = await insertQueue({
691
+ automaticAssignments: { labelIds: [labelA.toString()] },
692
+ });
693
+ await link("MessageQueueLabel", {
694
+ messageQueueId: ruleLabelled,
695
+ labelId: labelA,
696
+ });
697
+ archived.set("labelled only by a rule", ruleLabelled);
698
+ const mixedLabels: ObjectID = await insertQueue({
699
+ automaticAssignments: { labelIds: [labelA.toString()] },
700
+ });
701
+ await link("MessageQueueLabel", {
702
+ messageQueueId: mixedLabels,
703
+ labelId: labelA,
704
+ });
705
+ await link("MessageQueueLabel", {
706
+ messageQueueId: mixedLabels,
707
+ labelId: labelB,
708
+ });
709
+ kept.set("a rule's label plus a person's", mixedLabels);
710
+ const foreignLabelled: ObjectID = await insertQueue({});
711
+ await link("MessageQueueLabel", {
712
+ messageQueueId: foreignLabelled,
713
+ labelId: foreignLabel,
714
+ });
715
+ archived.set("labelled from another project", foreignLabelled);
716
+ const deletedLabelled: ObjectID = await insertQueue({});
717
+ await link("MessageQueueLabel", {
718
+ messageQueueId: deletedLabelled,
719
+ labelId: deletedLabel,
720
+ });
721
+ archived.set("labelled with a deleted label", deletedLabelled);
722
+
723
+ // Owners: the same rule.
724
+ const humanOwned: ObjectID = await insertQueue({});
725
+ await insertRow("MessageQueueOwnerUser", {
726
+ projectId: projectId,
727
+ messageQueueId: humanOwned,
728
+ userId: userId,
729
+ });
730
+ kept.set("owned by a person-added user", humanOwned);
731
+ const teamOwned: ObjectID = await insertQueue({});
732
+ await insertRow("MessageQueueOwnerTeam", {
733
+ projectId: projectId,
734
+ messageQueueId: teamOwned,
735
+ teamId: teamId,
736
+ });
737
+ kept.set("owned by a person-added team", teamOwned);
738
+ const ruleOwned: ObjectID = await insertQueue({
739
+ automaticAssignments: {
740
+ ownerUserIds: [userId.toString()],
741
+ ownerTeamIds: [teamId.toString()],
742
+ },
743
+ });
744
+ await insertRow("MessageQueueOwnerUser", {
745
+ projectId: projectId,
746
+ messageQueueId: ruleOwned,
747
+ userId: userId,
748
+ });
749
+ await insertRow("MessageQueueOwnerTeam", {
750
+ projectId: projectId,
751
+ messageQueueId: ruleOwned,
752
+ teamId: teamId,
753
+ });
754
+ archived.set("owned only through owner rules", ruleOwned);
755
+ const deletedOwner: ObjectID = await insertQueue({});
756
+ await insertRow("MessageQueueOwnerUser", {
757
+ projectId: projectId,
758
+ messageQueueId: deletedOwner,
759
+ userId: userId,
760
+ deletedAt: new Date(),
761
+ });
762
+ archived.set("owned by a deleted owner row", deletedOwner);
763
+ const foreignOwner: ObjectID = await insertQueue({});
764
+ await insertRow("MessageQueueOwnerUser", {
765
+ projectId: otherProjectId,
766
+ messageQueueId: foreignOwner,
767
+ userId: userId,
768
+ });
769
+ archived.set("owned by another project's row", foreignOwner);
770
+
771
+ // A person's Restore holds until seen again or 30 days pass.
772
+ kept.set(
773
+ "restored by a person last week, not seen since",
774
+ await insertQueue({ manuallyRestoredAt: ago(7 * DAY_MS) }),
775
+ );
776
+ archived.set(
777
+ "restored by a person 40 days ago",
778
+ await insertQueue({
779
+ lastSeenAt: ago(50 * DAY_MS),
780
+ manuallyRestoredAt: ago(40 * DAY_MS),
781
+ }),
782
+ );
783
+ archived.set(
784
+ "restored, then seen, then quiet",
785
+ await insertQueue({
786
+ lastSeenAt: ago(10 * DAY_MS),
787
+ manuallyRestoredAt: ago(12 * DAY_MS),
788
+ }),
789
+ );
790
+
791
+ const count: number =
792
+ await MessageQueueService.autoArchiveStaleMessageQueues();
793
+
794
+ const archivedIds: Set<string> = new Set();
795
+ for (const row of await liveQueues()) {
796
+ if (row.autoArchivedAt) {
797
+ archivedIds.add(row._id);
798
+ }
799
+ }
800
+
801
+ for (const [label, id] of archived) {
802
+ const state: any = await queueState(id);
803
+ expect({ label, isArchived: state.isArchived }).toEqual({
804
+ label,
805
+ isArchived: true,
806
+ });
807
+ expect({ label, auto: Boolean(state.autoArchivedAt) }).toEqual({
808
+ label,
809
+ auto: true,
810
+ });
811
+ expect(state.archivedAt).toBeInstanceOf(Date);
812
+ expect(state.archivedByUserId).toBeNull();
813
+ }
814
+ for (const [label, id] of kept) {
815
+ expect({ label, auto: archivedIds.has(id.toString()) }).toEqual({
816
+ label,
817
+ auto: false,
818
+ });
819
+ }
820
+ expect(count).toBe(archived.size);
821
+
822
+ // Nothing is archived twice.
823
+ await expect(
824
+ MessageQueueService.autoArchiveStaleMessageQueues(),
825
+ ).resolves.toBe(0);
826
+ });
827
+
828
+ test("the sweep archives at most 500 rows a run, the longest-unseen first", async () => {
829
+ await database.query(
830
+ `INSERT INTO "${schema}"."MessageQueue" (
831
+ "_id", "version", "projectId", "name", "slug", "queueIdentifier",
832
+ "messagingSystem", "destinationName", "discoverySource", "lastSeenAt",
833
+ "createdAt", "isArchived"
834
+ )
835
+ SELECT gen_random_uuid(), 1, $1, 'q-' || n, 'q-' || n || '-' || md5(random()::text), 'kafka||q-' || n,
836
+ 'kafka', 'q-' || n, 'traces', now() - make_interval(days => 1000 - n), now() - interval '1000 days', false
837
+ FROM generate_series(1, 502) AS n`,
838
+ [projectId.toString()],
839
+ );
840
+
841
+ await expect(
842
+ MessageQueueService.autoArchiveStaleMessageQueues(),
843
+ ).resolves.toBe(500);
844
+
845
+ const left: Array<{ name: string }> = await database.query(
846
+ `SELECT "name" FROM "${schema}"."MessageQueue" WHERE "isArchived" = false ORDER BY "name"`,
847
+ );
848
+ // The two seen most recently wait for the next run.
849
+ expect(
850
+ left.map((row: { name: string }): string => {
851
+ return row.name;
852
+ }),
853
+ ).toEqual(["q-501", "q-502"]);
854
+
855
+ await expect(
856
+ MessageQueueService.autoArchiveStaleMessageQueues(),
857
+ ).resolves.toBe(2);
858
+ });
859
+
860
+ test("the window follows MESSAGE_QUEUE_AUTO_ARCHIVE_DAYS", async () => {
861
+ const tenDays: ObjectID = await insertQueue({
862
+ lastSeenAt: ago(10 * DAY_MS),
863
+ });
864
+ const previous: string | undefined =
865
+ process.env["MESSAGE_QUEUE_AUTO_ARCHIVE_DAYS"];
866
+ process.env["MESSAGE_QUEUE_AUTO_ARCHIVE_DAYS"] = "14";
867
+
868
+ try {
869
+ await expect(
870
+ MessageQueueService.autoArchiveStaleMessageQueues(),
871
+ ).resolves.toBe(0);
872
+ expect((await queueState(tenDays)).isArchived).toBe(false);
873
+ } finally {
874
+ if (previous === undefined) {
875
+ delete process.env["MESSAGE_QUEUE_AUTO_ARCHIVE_DAYS"];
876
+ } else {
877
+ process.env["MESSAGE_QUEUE_AUTO_ARCHIVE_DAYS"] = previous;
878
+ }
879
+ }
880
+
881
+ await expect(
882
+ MessageQueueService.autoArchiveStaleMessageQueues(),
883
+ ).resolves.toBe(1);
884
+ });
885
+
886
+ test("the auto-create budget counts live, non-archived, non-manual rows of the project", async () => {
887
+ await insertQueue({ source: "traces" });
888
+ await insertQueue({ source: "broker-metrics" });
889
+ await insertQueue({ source: null });
890
+ await insertQueue({ source: "manual" });
891
+ await insertQueue({ source: "traces", isArchived: true });
892
+ await insertQueue({ source: "traces", deletedAt: new Date() });
893
+ await insertQueue({ source: "traces", project: otherProjectId });
894
+
895
+ // traces, broker-metrics and the NULL source count; the rest do not.
896
+ await expect(
897
+ MessageQueueService.countAutoCreatedMessageQueues(projectId),
898
+ ).resolves.toBe(3);
899
+ });
900
+
901
+ test("automatic assignments are recorded deduped and forgotten precisely", async () => {
902
+ const id: ObjectID = await insertQueue({});
903
+ const a: ObjectID = ObjectID.generate();
904
+ const b: ObjectID = ObjectID.generate();
905
+
906
+ await MessageQueueService.recordAutomaticAssignments({
907
+ messageQueueId: id,
908
+ kind: "labelIds",
909
+ ids: [a, a.toString().toUpperCase()],
910
+ });
911
+ await MessageQueueService.recordAutomaticAssignments({
912
+ messageQueueId: id,
913
+ kind: "labelIds",
914
+ ids: [a, b],
915
+ });
916
+ await MessageQueueService.recordAutomaticAssignments({
917
+ messageQueueId: id,
918
+ kind: "ownerTeamIds",
919
+ ids: [b],
920
+ });
921
+
922
+ let state: any = await queueState(id);
923
+ expect([...state.automaticAssignments.labelIds].sort()).toEqual(
924
+ [a.toString(), b.toString()].sort(),
925
+ );
926
+ expect(state.automaticAssignments.ownerTeamIds).toEqual([b.toString()]);
927
+
928
+ await MessageQueueService.forgetAutomaticAssignments({
929
+ messageQueueId: id,
930
+ kind: "labelIds",
931
+ ids: [a],
932
+ });
933
+
934
+ state = await queueState(id);
935
+ expect(state.automaticAssignments.labelIds).toEqual([b.toString()]);
936
+ expect(state.automaticAssignments.ownerTeamIds).toEqual([b.toString()]);
937
+
938
+ // Forgetting where nothing was recorded writes nothing.
939
+ const untouched: ObjectID = await insertQueue({});
940
+ await MessageQueueService.forgetAutomaticAssignments({
941
+ messageQueueId: untouched,
942
+ kind: "ownerUserIds",
943
+ ids: [a],
944
+ });
945
+ expect((await queueState(untouched)).automaticAssignments).toBeNull();
946
+
947
+ // A malformed value is replaced by a well-formed object.
948
+ const malformed: ObjectID = await insertQueue({
949
+ automaticAssignments: ["not", "an", "object"],
950
+ });
951
+ await MessageQueueService.recordAutomaticAssignments({
952
+ messageQueueId: malformed,
953
+ kind: "ownerUserIds",
954
+ ids: [a],
955
+ });
956
+ expect((await queueState(malformed)).automaticAssignments).toEqual({
957
+ ownerUserIds: [a.toString()],
958
+ });
959
+ });
960
+
961
+ test("a sighting writes its liveness and the broker address through the real heartbeat", async () => {
962
+ const id: ObjectID = await insertQueue({ lastSeenAt: ago(5 * DAY_MS) });
963
+ const at: Date = ago(60 * 1000);
964
+ const before: number = Date.now();
965
+
966
+ await MessageQueueService.recordSighting({
967
+ projectId: projectId,
968
+ queueId: id,
969
+ source: "broker-metrics",
970
+ brokerAddress: " kafka-1.internal:9092 ",
971
+ at: at,
972
+ });
973
+
974
+ let state: any = await queueState(id);
975
+ // When discovery saw it; the broker's own datapoint time has its column.
976
+ expect(state.lastSeenAt.getTime()).toBeGreaterThanOrEqual(before);
977
+ expect(state.brokerMetricsLastSeenAt.getTime()).toBe(at.getTime());
978
+ expect(state.brokerAddress).toBe("kafka-1.internal:9092");
979
+ const afterBrokerMetrics: number = state.lastSeenAt.getTime();
980
+
981
+ // A trace sighting in its own window moves lastSeenAt only.
982
+ await MessageQueueService.recordSighting({
983
+ projectId: projectId,
984
+ queueId: id,
985
+ source: "traces",
986
+ at: ago(10 * 60 * 1000),
987
+ });
988
+
989
+ state = await queueState(id);
990
+ expect(state.lastSeenAt.getTime()).toBeGreaterThanOrEqual(
991
+ afterBrokerMetrics,
992
+ );
993
+ expect(state.brokerMetricsLastSeenAt.getTime()).toBe(at.getTime());
994
+ expect(state.brokerAddress).toBe("kafka-1.internal:9092");
995
+
996
+ // A fresh sighting keeps the queue out of the sweep.
997
+ await expect(
998
+ MessageQueueService.autoArchiveStaleMessageQueues(),
999
+ ).resolves.toBe(0);
1000
+ });
1001
+
1002
+ /*
1003
+ * One pass: the queue is created from late broker metrics, then both
1004
+ * sources report it - traces first, then the broker's datapoints from
1005
+ * forty minutes ago (Azure Monitor / CloudWatch lag). The stored row must
1006
+ * never go back behind the create or the trace sighting.
1007
+ */
1008
+ test("lastSeenAt never moves backwards in the database, whichever source writes last", async () => {
1009
+ const created: MessageQueueFindOrCreateResult =
1010
+ await MessageQueueService.findOrCreateByIdentity({
1011
+ projectId: projectId,
1012
+ identity: identityOf({
1013
+ system: "servicebus",
1014
+ brokerScope: "orders-prod",
1015
+ destination: "orders",
1016
+ }),
1017
+ system: "servicebus",
1018
+ destination: "orders",
1019
+ source: "broker-metrics",
1020
+ allowCreate: true,
1021
+ });
1022
+ const id: ObjectID = created.queue!.id!;
1023
+ await flushPromises();
1024
+
1025
+ let state: any = await queueState(id);
1026
+ const createdLastSeenAt: number = state.lastSeenAt.getTime();
1027
+ expect(state.brokerMetricsLastSeenAt).toBeNull();
1028
+
1029
+ await MessageQueueService.recordSighting({
1030
+ projectId: projectId,
1031
+ queueId: id,
1032
+ source: "traces",
1033
+ at: ago(60 * 1000),
1034
+ });
1035
+
1036
+ state = await queueState(id);
1037
+ const afterTraces: number = state.lastSeenAt.getTime();
1038
+ expect(afterTraces).toBeGreaterThanOrEqual(createdLastSeenAt);
1039
+
1040
+ const newestDatapoint: Date = ago(40 * 60 * 1000);
1041
+ await MessageQueueService.recordSighting({
1042
+ projectId: projectId,
1043
+ queueId: id,
1044
+ source: "broker-metrics",
1045
+ at: newestDatapoint,
1046
+ });
1047
+
1048
+ state = await queueState(id);
1049
+ expect(state.lastSeenAt.getTime()).toBeGreaterThanOrEqual(afterTraces);
1050
+ expect(state.brokerMetricsLastSeenAt.getTime()).toBe(
1051
+ newestDatapoint.getTime(),
1052
+ );
1053
+ });
1054
+
1055
+ /*
1056
+ * -------------------------------------------------------------------------
1057
+ * People
1058
+ * -------------------------------------------------------------------------
1059
+ */
1060
+ describe("a person adding a queue", () => {
1061
+ function manual(
1062
+ messagingSystem: string,
1063
+ destinationName: string,
1064
+ brokerScope?: string,
1065
+ ): MessageQueue {
1066
+ const data: MessageQueue = new MessageQueue();
1067
+ data.messagingSystem = messagingSystem;
1068
+ data.destinationName = destinationName;
1069
+ if (brokerScope) {
1070
+ data.brokerScope = brokerScope;
1071
+ }
1072
+ return data;
1073
+ }
1074
+
1075
+ test("the real create pipeline stores the identity discovery would build", async () => {
1076
+ const created: MessageQueue = await MessageQueueService.create({
1077
+ data: manual(
1078
+ "azure_servicebus",
1079
+ "Orders/Subscriptions/Billing",
1080
+ "orders-prod.servicebus.windows.net",
1081
+ ),
1082
+ props: personProps([
1083
+ Permission.CreateMessageQueue,
1084
+ Permission.ReadMessageQueue,
1085
+ ]),
1086
+ });
1087
+
1088
+ const stored: any = await queueState(created.id!);
1089
+ expect(stored.projectId).toBe(projectId.toString());
1090
+ expect(stored.messagingSystem).toBe("servicebus");
1091
+ expect(stored.destinationName).toBe("Orders");
1092
+ expect(stored.brokerScope).toBe("orders-prod");
1093
+ expect(stored.queueIdentifier).toBe("servicebus|orders-prod|orders");
1094
+ expect(stored.discoverySource).toBe("manual");
1095
+ expect(stored.name).toBe("Orders");
1096
+ expect(stored.createdByUserId).toBe(userId.toString());
1097
+ await flushPromises();
1098
+ expect(labelRules).toHaveBeenCalledTimes(1);
1099
+
1100
+ // Discovery sighting the same queue finds the person's row.
1101
+ const found: MessageQueueFindOrCreateResult =
1102
+ await MessageQueueService.findOrCreateByIdentity({
1103
+ projectId: projectId,
1104
+ identity: identityOf({
1105
+ system: "servicebus",
1106
+ brokerScope: "orders-prod",
1107
+ destination: "orders",
1108
+ }),
1109
+ system: "servicebus",
1110
+ destination: "orders",
1111
+ source: "traces",
1112
+ allowCreate: true,
1113
+ });
1114
+ expect(found).toMatchObject({ created: false });
1115
+ expect(found.queue!.id!.toString()).toBe(created.id!.toString());
1116
+ });
1117
+
1118
+ /*
1119
+ * The rabbitmq receiver reports a queue under its exact name, and the
1120
+ * discovery cron creates or sights the queue by it. A queue a person
1121
+ * added is that queue - never a second one beside it - even when its
1122
+ * name carries the separators of a span's joined RabbitMQ name, as
1123
+ * Hutch's `namespace:consumer` and EasyNetQ's `Type, Assembly_sub`
1124
+ * queue names do.
1125
+ */
1126
+ test.each([
1127
+ ["myapp:billing:invoice_consumer"],
1128
+ ["MyApp.Messages.OrderCreated, MyApp.Messages_billing"],
1129
+ ])(
1130
+ "a RabbitMQ queue a person adds is the queue its broker's metrics sight: %p",
1131
+ async (queue: string) => {
1132
+ const created: MessageQueue = await MessageQueueService.create({
1133
+ data: manual("rabbitmq", queue),
1134
+ props: personProps([
1135
+ Permission.CreateMessageQueue,
1136
+ Permission.ReadMessageQueue,
1137
+ ]),
1138
+ });
1139
+
1140
+ // A rabbitmq.message.current row as the discovery SQL returns it.
1141
+ const attributes: Record<string, string> = {
1142
+ state: "ready",
1143
+ "resource.rabbitmq.node.name": "rabbit@broker-1",
1144
+ "resource.rabbitmq.queue.name": queue,
1145
+ "resource.rabbitmq.vhost.name": "/",
1146
+ };
1147
+ const row: MessagingMetricDiscoveryRow = {
1148
+ name: "rabbitmq.message.current",
1149
+ pointCount: 1,
1150
+ lastSeenUnixMs: Date.now(),
1151
+ };
1152
+ MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES.forEach(
1153
+ (key: string, index: number): void => {
1154
+ row[getMessagingDiscoveryColumn(index)] = attributes[key] ?? "";
1155
+ },
1156
+ );
1157
+ const discovered: Array<DiscoveredMessageQueue> =
1158
+ resolveMessagingMetricDiscoveryRows([row]);
1159
+ expect(discovered).toHaveLength(1);
1160
+ expect(discovered[0]!.identifier).toBe(
1161
+ `rabbitmq||${queue.toLowerCase()}`,
1162
+ );
1163
+
1164
+ const sighted: MessageQueueFindOrCreateResult =
1165
+ await MessageQueueService.findOrCreateByIdentity({
1166
+ projectId: projectId,
1167
+ identity: discovered[0]!.identity,
1168
+ system: discovered[0]!.system,
1169
+ destination: discovered[0]!.destination,
1170
+ source: "broker-metrics",
1171
+ allowCreate: true,
1172
+ });
1173
+
1174
+ expect(sighted).toMatchObject({ created: false });
1175
+ expect(sighted.queue!.id!.toString()).toBe(created.id!.toString());
1176
+ const live: Array<any> = await liveQueues();
1177
+ expect(live).toHaveLength(1);
1178
+ expect(live[0].destinationName).toBe(queue);
1179
+ expect(live[0].discoverySource).toBe("manual");
1180
+ },
1181
+ );
1182
+
1183
+ test("the same queue twice is refused, naming it for a caller who may read it", async () => {
1184
+ await insertQueue({
1185
+ name: "Checkout orders",
1186
+ destinationName: "orders",
1187
+ queueIdentifier: "aws_sqs||orders",
1188
+ messagingSystem: "aws_sqs",
1189
+ });
1190
+
1191
+ await expect(
1192
+ MessageQueueService.create({
1193
+ data: manual(
1194
+ "AmazonSQS",
1195
+ "https://sqs.us-east-1.amazonaws.com/123456789012/orders",
1196
+ ),
1197
+ props: personProps([
1198
+ Permission.CreateMessageQueue,
1199
+ Permission.ReadMessageQueue,
1200
+ ]),
1201
+ }),
1202
+ ).rejects.toThrow(
1203
+ 'The Amazon SQS queue "orders" already exists: "Checkout orders".',
1204
+ );
1205
+ expect(await liveQueues()).toHaveLength(1);
1206
+ });
1207
+ });
1208
+
1209
+ test("a person's Restore through the real update pipeline holds the sweep off", async () => {
1210
+ const id: ObjectID = await insertQueue({
1211
+ isArchived: true,
1212
+ archivedAt: ago(DAY_MS),
1213
+ autoArchivedAt: ago(DAY_MS),
1214
+ lastSeenAt: ago(20 * DAY_MS),
1215
+ });
1216
+
1217
+ await MessageQueueService.updateOneById({
1218
+ id: id,
1219
+ data: { isArchived: false } as any,
1220
+ props: personProps([
1221
+ Permission.EditMessageQueue,
1222
+ Permission.ReadMessageQueue,
1223
+ ]),
1224
+ });
1225
+
1226
+ const restored: any = await queueState(id);
1227
+ expect(restored.isArchived).toBe(false);
1228
+ expect(restored.autoArchivedAt).toBeNull();
1229
+ expect(restored.manuallyRestoredAt).toBeInstanceOf(Date);
1230
+
1231
+ // Stale for 20 days, but restored by a person just now: left alone.
1232
+ await expect(
1233
+ MessageQueueService.autoArchiveStaleMessageQueues(),
1234
+ ).resolves.toBe(0);
1235
+
1236
+ // And a person archiving it takes it out of discovery's hands.
1237
+ await MessageQueueService.updateOneById({
1238
+ id: id,
1239
+ data: { isArchived: true } as any,
1240
+ props: personProps([
1241
+ Permission.EditMessageQueue,
1242
+ Permission.ReadMessageQueue,
1243
+ ]),
1244
+ });
1245
+
1246
+ const archived: any = await queueState(id);
1247
+ expect(archived.isArchived).toBe(true);
1248
+ expect(archived.autoArchivedAt).toBeNull();
1249
+ expect(archived.manuallyRestoredAt).toBeNull();
1250
+ expect(archived.archivedByUserId).toBe(userId.toString());
1251
+
1252
+ await MessageQueueService.findOrCreateByIdentity({
1253
+ projectId: projectId,
1254
+ identity: parseIdentity(archived.queueIdentifier),
1255
+ system: archived.messagingSystem,
1256
+ destination: archived.destinationName,
1257
+ source: "traces",
1258
+ allowCreate: false,
1259
+ });
1260
+ expect((await queueState(id)).isArchived).toBe(true);
1261
+ });
1262
+
1263
+ function parseIdentity(identifier: string): MessageQueueIdentity {
1264
+ const [system, brokerScope, destination] = identifier.split("|");
1265
+ return identityOf({
1266
+ system: system!,
1267
+ brokerScope: brokerScope!,
1268
+ destination: destination!,
1269
+ });
1270
+ }
1271
+ });