@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,847 @@
1
+ import Redis, { ClientType } from "../Infrastructure/Redis";
2
+ import {
3
+ ExpressRequest,
4
+ ExpressResponse,
5
+ NextFunction,
6
+ OneUptimeRequest,
7
+ } from "../Utils/Express";
8
+ import logger, { getLogAttributesFromRequest } from "../Utils/Logger";
9
+ import resolveTrustedClientIp, { ClientIpRequestLike } from "../Utils/ClientIp";
10
+ import Response from "../Utils/Response";
11
+ import ObjectID from "../../Types/ObjectID";
12
+ import ServiceUnavailableException from "../../Types/Exception/ServiceUnavailableException";
13
+ import TooManyRequestsException from "../../Types/Exception/TooManyRequestsException";
14
+
15
+ /*
16
+ * Rate limiting for the public incident form routes:
17
+ *
18
+ * GET /api/incident-form/public/:shareKey (the form's questions)
19
+ * POST /api/incident-form/public/:shareKey/submit (declare an incident)
20
+ *
21
+ * Both are anonymous: anyone holding a form's link can call them, from any
22
+ * network, with no session and no API key. A sibling of
23
+ * PublicDashboardRateLimit rather than a reuse of it, because the two routes
24
+ * here need budgets that differ in kind, not only in size:
25
+ *
26
+ * - reading a form is load control, like reading a public dashboard;
27
+ *
28
+ * - submitting one declares an incident, and every incident pages on-call.
29
+ * The counter there is not protecting a database from load, it is the
30
+ * only thing standing between a leaked link and a night of pages. So the
31
+ * submit budget is sized for people rather than for load, adds a ceiling
32
+ * per form that no number of addresses gets around, and refuses to serve
33
+ * at all when it cannot count (see getMiddleware).
34
+ *
35
+ * The per-address counters are middleware, so a flood is refused before it
36
+ * costs a session lookup, a Postgres read or a captcha round trip. Only the
37
+ * routes' own-page checks come before them (IncidentFormAPI): a request
38
+ * another site's page had a browser send, a read without the header the
39
+ * form's page sends, or a submission that is not JSON, is refused without
40
+ * being counted, so such a page cannot use up the budget its visitors'
41
+ * addresses share. The per-form ceiling is not middleware at all:
42
+ * IncidentFormService spends it (reserveFormSubmission) only for a
43
+ * submission that has passed every other check - the form, its plan, its
44
+ * IP allowlist, the captcha, the answers, the severity - right before the
45
+ * incident is declared. It bounds incidents, so only a submission about to
46
+ * become one may count against it; were every attempt to count, anyone
47
+ * holding the link - even from outside the allowlist, or without solving
48
+ * the captcha - could use it up with requests that are refused, and lock the
49
+ * form for everybody.
50
+ */
51
+
52
+ /*
53
+ * Which counter rejected a request. Every request that reaches the
54
+ * middleware consumes the first two; a submission about to declare an
55
+ * incident consumes the third:
56
+ *
57
+ * - FormAndIp, keyed on the form + client address: the budget one reporter
58
+ * (or one office behind one NAT) gets on one form.
59
+ *
60
+ * - Ip, keyed on the client address alone. Without it the first counter is
61
+ * bypassed by rotating the share key on every request, landing in a
62
+ * fresh bucket each time while still costing a Postgres lookup, 404 or
63
+ * not.
64
+ *
65
+ * - Form, keyed on the form alone, across every address (submissions that
66
+ * passed every check only). The ceiling that survives address rotation:
67
+ * a botnet holding the link gets no more pages out of it than one
68
+ * determined person does.
69
+ *
70
+ * Every counter is incremented on each request that reaches it, including
71
+ * one it rejects, so a client that keeps hammering keeps its window pinned
72
+ * rather than being handed a fresh allowance for free.
73
+ */
74
+ export enum IncidentFormRateLimitScope {
75
+ FormAndIp = "form-and-ip",
76
+ Ip = "ip",
77
+ Form = "form",
78
+ }
79
+
80
+ export enum IncidentFormRateLimitBucket {
81
+ // GET /incident-form/public/:shareKey. Fails open.
82
+ Read = "read",
83
+
84
+ // POST /incident-form/public/:shareKey/submit. Fails closed.
85
+ Submit = "submit",
86
+ }
87
+
88
+ export enum IncidentFormRateLimitOutcome {
89
+ Allowed = "allowed",
90
+ RateLimited = "rate-limited",
91
+
92
+ // Redis is unreachable, so no limit can be honoured either way.
93
+ CounterUnavailable = "counter-unavailable",
94
+ }
95
+
96
+ export interface IncidentFormRateLimitDecision {
97
+ outcome: IncidentFormRateLimitOutcome;
98
+ retryAfterSeconds?: number | undefined;
99
+
100
+ // Which counter rejected, for logs and the message. Unset unless rejected.
101
+ scope?: IncidentFormRateLimitScope | undefined;
102
+
103
+ /*
104
+ * True only on the request that first crossed the line in this window.
105
+ * The caller keeps knocking - that is why there is a limiter - so logging
106
+ * every refusal would turn a flood into a second flood in the log
107
+ * pipeline. Logging only the crossing gives one line per key per window.
108
+ */
109
+ isFirstRejectionInWindow?: boolean | undefined;
110
+ }
111
+
112
+ // The ceiling on one form across every address, per window.
113
+ export interface IncidentFormRateLimitFormCeiling {
114
+ windowSeconds: number;
115
+ limit: number;
116
+ }
117
+
118
+ export interface IncidentFormRateLimitBucketConfig {
119
+ windowSeconds: number;
120
+ perFormAndIpLimit: number;
121
+ perIpLimit: number;
122
+
123
+ // Submit only. Its own window, since it bounds pages per hour.
124
+ perForm?: IncidentFormRateLimitFormCeiling | undefined;
125
+
126
+ /*
127
+ * Refuse with 503 when the counter is unavailable, rather than letting the
128
+ * request through uncounted. See getMiddleware for why the two buckets
129
+ * differ.
130
+ */
131
+ failsClosed: boolean;
132
+ }
133
+
134
+ /*
135
+ * What a refused caller is told. None of them names a number: the limits are
136
+ * for the operator to tune, not for a caller to pace itself against.
137
+ */
138
+ export const INCIDENT_FORM_READ_RATE_LIMIT_MESSAGE: string =
139
+ "Too many requests. Please try again later.";
140
+
141
+ export const INCIDENT_FORM_SUBMIT_RATE_LIMIT_MESSAGE: string =
142
+ "Too many submissions from your network. Please wait a few minutes and try again.";
143
+
144
+ /*
145
+ * The per-form ceiling is not about the caller's network at all, so it gets
146
+ * its own words: telling someone whose first report this is that "your
147
+ * network" sent too many would send them hunting for a problem they do not
148
+ * have.
149
+ */
150
+ export const INCIDENT_FORM_TOTAL_RATE_LIMIT_MESSAGE: string =
151
+ "This form is receiving too many reports right now. Please try again later.";
152
+
153
+ export const INCIDENT_FORM_RATE_LIMIT_UNAVAILABLE_MESSAGE: string =
154
+ "Reports cannot be accepted right now. Please try again in a few minutes.";
155
+
156
+ /*
157
+ * A submission the per-form ceiling refused. Thrown from inside
158
+ * IncidentFormService (reserveFormSubmission), where there is no response to
159
+ * write a header on, so it carries when to come back; the submit route
160
+ * writes that as Retry-After (setRetryAfterFor) before the error handler
161
+ * answers 429.
162
+ */
163
+ export class IncidentFormCeilingException extends TooManyRequestsException {
164
+ public readonly retryAfterSeconds: number;
165
+
166
+ public constructor(retryAfterSeconds: number) {
167
+ super(INCIDENT_FORM_TOTAL_RATE_LIMIT_MESSAGE);
168
+ this.retryAfterSeconds = retryAfterSeconds;
169
+ }
170
+ }
171
+
172
+ const parsePositiveIntFromEnv: (envKey: string, fallback: number) => number = (
173
+ envKey: string,
174
+ fallback: number,
175
+ ): number => {
176
+ const rawValue: string | undefined = process.env[envKey];
177
+
178
+ if (!rawValue) {
179
+ return fallback;
180
+ }
181
+
182
+ const parsedValue: number = parseInt(rawValue, 10);
183
+
184
+ if (!Number.isFinite(parsedValue) || parsedValue <= 0) {
185
+ return fallback;
186
+ }
187
+
188
+ return parsedValue;
189
+ };
190
+
191
+ /*
192
+ * Read budget: 120 per minute per form + address, 600 per minute per
193
+ * address.
194
+ *
195
+ * The page asks for the form once when it opens, so a real reporter uses one
196
+ * or two of these. The headroom is for a whole office behind one NAT opening
197
+ * the same link during an outage - which is exactly when a form gets used -
198
+ * and the per-address ceiling for that office opening several forms. What
199
+ * matters is that "as fast as a loop runs" becomes a fixed ceiling at all;
200
+ * operators who want it tighter have the environment variables.
201
+ */
202
+ const READ_BUCKET: IncidentFormRateLimitBucketConfig = {
203
+ windowSeconds: parsePositiveIntFromEnv(
204
+ "INCIDENT_FORM_RATE_LIMIT_WINDOW_SECONDS",
205
+ 60,
206
+ ),
207
+ perFormAndIpLimit: parsePositiveIntFromEnv(
208
+ "INCIDENT_FORM_RATE_LIMIT_PER_FORM_AND_IP_PER_WINDOW",
209
+ 120,
210
+ ),
211
+ perIpLimit: parsePositiveIntFromEnv(
212
+ "INCIDENT_FORM_RATE_LIMIT_PER_IP_PER_WINDOW",
213
+ 600,
214
+ ),
215
+ failsClosed: false,
216
+ };
217
+
218
+ /*
219
+ * Submit budget: 10 per 15 minutes per form + address, 30 per 15 minutes
220
+ * per address, and 60 incidents per hour per form across every address.
221
+ *
222
+ * Sized for people. Ten reports to one form from one network in a quarter
223
+ * of an hour already covers a team that all saw the same outage, plus a few
224
+ * attempts that failed validation (those count against the address budgets
225
+ * - the middleware runs before the form is checked). The per-form ceiling
226
+ * is the one that bounds pages: only a submission about to declare an
227
+ * incident counts against it, so an hour of it is sixty incidents, far past
228
+ * the point where more reports add information, and no number of addresses
229
+ * raises it.
230
+ *
231
+ * The per-form ceiling is keyed on the share key, like everything here, so
232
+ * resetting a form's link in the dashboard - the remedy for a link that went
233
+ * somewhere it should not have - also starts the new link with a fresh
234
+ * allowance.
235
+ */
236
+ const SUBMIT_BUCKET: IncidentFormRateLimitBucketConfig = {
237
+ windowSeconds: parsePositiveIntFromEnv(
238
+ "INCIDENT_FORM_SUBMIT_RATE_LIMIT_WINDOW_SECONDS",
239
+ 15 * 60,
240
+ ),
241
+ perFormAndIpLimit: parsePositiveIntFromEnv(
242
+ "INCIDENT_FORM_SUBMIT_RATE_LIMIT_PER_FORM_AND_IP_PER_WINDOW",
243
+ 10,
244
+ ),
245
+ perIpLimit: parsePositiveIntFromEnv(
246
+ "INCIDENT_FORM_SUBMIT_RATE_LIMIT_PER_IP_PER_WINDOW",
247
+ 30,
248
+ ),
249
+ perForm: {
250
+ windowSeconds: parsePositiveIntFromEnv(
251
+ "INCIDENT_FORM_SUBMIT_RATE_LIMIT_PER_FORM_WINDOW_SECONDS",
252
+ 60 * 60,
253
+ ),
254
+ limit: parsePositiveIntFromEnv(
255
+ "INCIDENT_FORM_SUBMIT_RATE_LIMIT_PER_FORM_PER_WINDOW",
256
+ 60,
257
+ ),
258
+ },
259
+ failsClosed: true,
260
+ };
261
+
262
+ /*
263
+ * Redis namespace for every counter here, so a SCAN for incident form keys
264
+ * never shows another surface's, and the two surfaces never share a count.
265
+ */
266
+ const KEY_PREFIX: string = "iform:rl:";
267
+
268
+ /*
269
+ * Counter keys outlive their window by one full window, so a request landing
270
+ * on a boundary cannot read a key that was reclaimed mid-window.
271
+ */
272
+ const TTL_MULTIPLIER: number = 2;
273
+
274
+ // Bounds a Redis key built from attacker-supplied request data.
275
+ const MAX_KEY_SEGMENT_LENGTH: number = 64;
276
+
277
+ // How often the "counter unavailable" condition may be logged, per bucket.
278
+ const COUNTER_UNAVAILABLE_LOG_INTERVAL_MS: number = 60 * 1000;
279
+
280
+ export default class IncidentFormRateLimit {
281
+ // The limits in force for a bucket, for tests and operators' diagnostics.
282
+ public static getBucketConfig(
283
+ bucket: IncidentFormRateLimitBucket,
284
+ ): IncidentFormRateLimitBucketConfig {
285
+ const config: IncidentFormRateLimitBucketConfig =
286
+ IncidentFormRateLimit.getConfig(bucket);
287
+
288
+ return {
289
+ ...config,
290
+ perForm: config.perForm ? { ...config.perForm } : undefined,
291
+ };
292
+ }
293
+
294
+ /*
295
+ * The client address to bill this request to.
296
+ *
297
+ * The shared ClientIp helper reads X-Forwarded-For from the trusted
298
+ * (right-hand) end under the instance-wide TRUSTED_PROXY_HOPS setting -
299
+ * never the leftmost entry, which any caller can set, and which would hand
300
+ * a caller a fresh bucket per request. It is also what IncidentFormService
301
+ * checks the form's IP allowlist against, so the limiter and the allowlist
302
+ * always agree on who is calling.
303
+ */
304
+ public static resolveClientIp(req: ExpressRequest): string {
305
+ const clientIp: string | undefined = resolveTrustedClientIp(
306
+ req as unknown as ClientIpRequestLike,
307
+ );
308
+
309
+ if (clientIp) {
310
+ return IncidentFormRateLimit.sanitizeKeySegment(clientIp);
311
+ }
312
+
313
+ /*
314
+ * No address at all. Everything in this state shares one bucket, which
315
+ * is the conservative direction: an unidentifiable caller should not get
316
+ * a private allowance of its own.
317
+ */
318
+ return "unknown";
319
+ }
320
+
321
+ /*
322
+ * The form this request is about, as a key segment.
323
+ *
324
+ * A share key is a UUID, so anything else cannot name a form and every
325
+ * such request shares one "invalid" bucket. That bounds Redis memory
326
+ * against a caller feeding junk path segments, and it is the right grouping
327
+ * anyway: none of them can reach a form. Case and surrounding whitespace do
328
+ * not split a bucket, or varying them would be a way around the limit.
329
+ *
330
+ * The key is used as it is rather than hashed: a share key sits in an
331
+ * address bar and in access logs by design (see IncidentForm.shareKey), so
332
+ * it is a link identifier like a public dashboard id, not a secret.
333
+ */
334
+ public static resolveFormKey(req: ExpressRequest): string {
335
+ return IncidentFormRateLimit.getFormKey(req.params?.["shareKey"]);
336
+ }
337
+
338
+ /*
339
+ * The key segment for a share key, however it was read: from the path by
340
+ * the middleware, or handed over by IncidentFormService when it spends the
341
+ * form's ceiling - so both always count the same form under one key.
342
+ */
343
+ public static getFormKey(shareKey: unknown): string {
344
+ if (typeof shareKey !== "string" || shareKey.trim().length === 0) {
345
+ return "none";
346
+ }
347
+
348
+ const value: string = shareKey.trim();
349
+
350
+ if (ObjectID.isValidUUID(value)) {
351
+ return `k:${value.toLowerCase()}`;
352
+ }
353
+
354
+ return "invalid";
355
+ }
356
+
357
+ private static sanitizeKeySegment(value: string): string {
358
+ return (
359
+ value
360
+ .slice(0, MAX_KEY_SEGMENT_LENGTH)
361
+ /*
362
+ * Redis keys are binary safe, but a predictable charset keeps
363
+ * operational tooling (KEYS/SCAN patterns, dashboards) sane.
364
+ */
365
+ .replace(/[^a-zA-Z0-9._:%\-[\]]/g, "_")
366
+ );
367
+ }
368
+
369
+ private static getConfig(
370
+ bucket: IncidentFormRateLimitBucket,
371
+ ): IncidentFormRateLimitBucketConfig {
372
+ if (bucket === IncidentFormRateLimitBucket.Submit) {
373
+ return SUBMIT_BUCKET;
374
+ }
375
+
376
+ return READ_BUCKET;
377
+ }
378
+
379
+ /*
380
+ * Count this request against the two per-address counters and decide.
381
+ *
382
+ * Both go out in one pipeline, so a request costs a single round trip. The
383
+ * form's own ceiling is not counted here, for either bucket: that is
384
+ * spent by a submission that has passed every check (consumeFormCeiling),
385
+ * so a request that is refused - by these counters or by anything after
386
+ * them - never uses up the allowance everybody else shares.
387
+ */
388
+ public static async consume(data: {
389
+ // From resolveFormKey.
390
+ formKey: string;
391
+ // From resolveClientIp.
392
+ clientIp: string;
393
+ bucket: IncidentFormRateLimitBucket;
394
+ }): Promise<IncidentFormRateLimitDecision> {
395
+ const client: ClientType | null = Redis.getClient();
396
+
397
+ if (!client || !Redis.isConnected()) {
398
+ return { outcome: IncidentFormRateLimitOutcome.CounterUnavailable };
399
+ }
400
+
401
+ const config: IncidentFormRateLimitBucketConfig =
402
+ IncidentFormRateLimit.getConfig(data.bucket);
403
+
404
+ const keyPrefix: string = `${KEY_PREFIX}${data.bucket}:`;
405
+ const windowIndex: number = IncidentFormRateLimit.getWindowIndex(
406
+ config.windowSeconds,
407
+ );
408
+
409
+ const formAndIpCounterKey: string = `${keyPrefix}fi:${data.formKey}:${data.clientIp}:${windowIndex}`;
410
+ const ipCounterKey: string = `${keyPrefix}i:${data.clientIp}:${windowIndex}`;
411
+
412
+ try {
413
+ const addressCounts: Array<number> =
414
+ await IncidentFormRateLimit.incrementCounters({
415
+ client,
416
+ keys: [formAndIpCounterKey, ipCounterKey],
417
+ windowSeconds: config.windowSeconds,
418
+ });
419
+
420
+ const formAndIpCount: number = addressCounts[0] ?? 0;
421
+ const ipCount: number = addressCounts[1] ?? 0;
422
+
423
+ /*
424
+ * The per-form + address counter is reported first when both are over:
425
+ * it is the more specific of the two and the more useful thing to see
426
+ * in a log line.
427
+ */
428
+ if (formAndIpCount > config.perFormAndIpLimit) {
429
+ return IncidentFormRateLimit.rejected({
430
+ scope: IncidentFormRateLimitScope.FormAndIp,
431
+ count: formAndIpCount,
432
+ limit: config.perFormAndIpLimit,
433
+ windowSeconds: config.windowSeconds,
434
+ });
435
+ }
436
+
437
+ if (ipCount > config.perIpLimit) {
438
+ return IncidentFormRateLimit.rejected({
439
+ scope: IncidentFormRateLimitScope.Ip,
440
+ count: ipCount,
441
+ limit: config.perIpLimit,
442
+ windowSeconds: config.windowSeconds,
443
+ });
444
+ }
445
+
446
+ return { outcome: IncidentFormRateLimitOutcome.Allowed };
447
+ } catch (err) {
448
+ /*
449
+ * Throttled for the same reason as the middleware's unavailable
450
+ * branch: whatever broke Redis is unlikely to break it for one request
451
+ * only, and a per-request log line buries the incident it reports.
452
+ */
453
+ if (IncidentFormRateLimit.shouldLogCounterUnavailable(data.bucket)) {
454
+ logger.warn(
455
+ `IncidentFormRateLimit: counter failed for incident form ${data.formKey}`,
456
+ );
457
+ logger.warn(err);
458
+ }
459
+
460
+ return { outcome: IncidentFormRateLimitOutcome.CounterUnavailable };
461
+ }
462
+ }
463
+
464
+ /*
465
+ * Count one incident against the form's ceiling - across every address,
466
+ * per clock hour - and decide. For a submission that has passed every
467
+ * other check and is about to declare its incident; see
468
+ * reserveFormSubmission, which is what the service calls.
469
+ */
470
+ public static async consumeFormCeiling(data: {
471
+ // From getFormKey.
472
+ formKey: string;
473
+ }): Promise<IncidentFormRateLimitDecision> {
474
+ const client: ClientType | null = Redis.getClient();
475
+
476
+ if (!client || !Redis.isConnected()) {
477
+ return { outcome: IncidentFormRateLimitOutcome.CounterUnavailable };
478
+ }
479
+
480
+ const ceiling: IncidentFormRateLimitFormCeiling | undefined =
481
+ SUBMIT_BUCKET.perForm;
482
+
483
+ if (!ceiling) {
484
+ return { outcome: IncidentFormRateLimitOutcome.Allowed };
485
+ }
486
+
487
+ const formCounterKey: string = `${KEY_PREFIX}${IncidentFormRateLimitBucket.Submit}:f:${data.formKey}:${IncidentFormRateLimit.getWindowIndex(
488
+ ceiling.windowSeconds,
489
+ )}`;
490
+
491
+ try {
492
+ const formCounts: Array<number> =
493
+ await IncidentFormRateLimit.incrementCounters({
494
+ client,
495
+ keys: [formCounterKey],
496
+ windowSeconds: ceiling.windowSeconds,
497
+ });
498
+
499
+ const formCount: number = formCounts[0] ?? 0;
500
+
501
+ if (formCount > ceiling.limit) {
502
+ return IncidentFormRateLimit.rejected({
503
+ scope: IncidentFormRateLimitScope.Form,
504
+ count: formCount,
505
+ limit: ceiling.limit,
506
+ windowSeconds: ceiling.windowSeconds,
507
+ });
508
+ }
509
+
510
+ return { outcome: IncidentFormRateLimitOutcome.Allowed };
511
+ } catch (err) {
512
+ if (
513
+ IncidentFormRateLimit.shouldLogCounterUnavailable(
514
+ IncidentFormRateLimitBucket.Submit,
515
+ )
516
+ ) {
517
+ logger.warn(
518
+ `IncidentFormRateLimit: form ceiling counter failed for incident form ${data.formKey}`,
519
+ );
520
+ logger.warn(err);
521
+ }
522
+
523
+ return { outcome: IncidentFormRateLimitOutcome.CounterUnavailable };
524
+ }
525
+ }
526
+
527
+ /*
528
+ * Spend one of the form's hourly incidents, or refuse: 429
529
+ * (IncidentFormCeilingException, carrying when to come back) once the
530
+ * hour's allowance is used, and 503 when the counter cannot be reached -
531
+ * the ceiling is what bounds the pages a link can cause, so without it the
532
+ * submission fails closed, as the submit middleware does.
533
+ *
534
+ * Called by IncidentFormService.submitPublicForm right before it declares
535
+ * the incident, once the form, its plan, its IP allowlist, the captcha,
536
+ * the answers and the severity have all been checked: a refused request
537
+ * never spends it.
538
+ */
539
+ public static async reserveFormSubmission(data: {
540
+ shareKey: string | undefined;
541
+ }): Promise<void> {
542
+ const formKey: string = IncidentFormRateLimit.getFormKey(data.shareKey);
543
+
544
+ const decision: IncidentFormRateLimitDecision =
545
+ await IncidentFormRateLimit.consumeFormCeiling({ formKey });
546
+
547
+ if (decision.outcome === IncidentFormRateLimitOutcome.RateLimited) {
548
+ if (decision.isFirstRejectionInWindow) {
549
+ logger.warn(
550
+ `IncidentFormRateLimit: rejected a submission to incident form ${formKey} (${IncidentFormRateLimitScope.Form} limit)`,
551
+ );
552
+ }
553
+
554
+ throw new IncidentFormCeilingException(decision.retryAfterSeconds || 1);
555
+ }
556
+
557
+ if (decision.outcome === IncidentFormRateLimitOutcome.CounterUnavailable) {
558
+ if (
559
+ IncidentFormRateLimit.shouldLogCounterUnavailable(
560
+ IncidentFormRateLimitBucket.Submit,
561
+ )
562
+ ) {
563
+ logger.error(
564
+ `IncidentFormRateLimit: rate limit counter unavailable, refusing incident form submissions (incident form ${formKey})`,
565
+ );
566
+ }
567
+
568
+ throw new ServiceUnavailableException(
569
+ INCIDENT_FORM_RATE_LIMIT_UNAVAILABLE_MESSAGE,
570
+ );
571
+ }
572
+ }
573
+
574
+ /*
575
+ * For the submit route: when the service refused a submission for the
576
+ * form's ceiling, say when to come back, as the middleware does for its
577
+ * own refusals. Anything else is left alone.
578
+ */
579
+ public static setRetryAfterFor(res: ExpressResponse, error: unknown): void {
580
+ if (error instanceof IncidentFormCeilingException) {
581
+ IncidentFormRateLimit.setRetryAfterHeader(res, error.retryAfterSeconds);
582
+ }
583
+ }
584
+
585
+ /*
586
+ * INCR each key in one pipeline and return the new counts, in order.
587
+ *
588
+ * The expiry is set only on the write that created a key. Re-issuing
589
+ * EXPIRE on every increment would slide the window forward for as long as
590
+ * the load continued, so the counter would never reset and a client that
591
+ * tripped the limit once could never recover.
592
+ */
593
+ private static async incrementCounters(data: {
594
+ client: ClientType;
595
+ keys: Array<string>;
596
+ windowSeconds: number;
597
+ }): Promise<Array<number>> {
598
+ const pipeline: ReturnType<ClientType["pipeline"]> = data.client.pipeline();
599
+
600
+ for (const key of data.keys) {
601
+ pipeline.incr(key);
602
+ }
603
+
604
+ const pipelineResults: Array<[Error | null, unknown]> | null =
605
+ (await pipeline.exec()) as Array<[Error | null, unknown]> | null;
606
+
607
+ if (!pipelineResults || pipelineResults.length < data.keys.length) {
608
+ throw new Error("Rate limit pipeline returned no result");
609
+ }
610
+
611
+ const counts: Array<number> = data.keys.map(
612
+ (_key: string, index: number): number => {
613
+ return IncidentFormRateLimit.readCounterResult(pipelineResults[index]);
614
+ },
615
+ );
616
+
617
+ const keysToExpire: Array<string> = data.keys.filter(
618
+ (_key: string, index: number): boolean => {
619
+ return counts[index] === 1;
620
+ },
621
+ );
622
+
623
+ if (keysToExpire.length > 0) {
624
+ const expirePipeline: ReturnType<ClientType["pipeline"]> =
625
+ data.client.pipeline();
626
+
627
+ for (const key of keysToExpire) {
628
+ expirePipeline.expire(key, data.windowSeconds * TTL_MULTIPLIER);
629
+ }
630
+
631
+ await expirePipeline.exec();
632
+ }
633
+
634
+ return counts;
635
+ }
636
+
637
+ private static rejected(data: {
638
+ scope: IncidentFormRateLimitScope;
639
+ count: number;
640
+ limit: number;
641
+ windowSeconds: number;
642
+ }): IncidentFormRateLimitDecision {
643
+ return {
644
+ outcome: IncidentFormRateLimitOutcome.RateLimited,
645
+ retryAfterSeconds: IncidentFormRateLimit.getSecondsUntilWindowEnd(
646
+ data.windowSeconds,
647
+ ),
648
+ scope: data.scope,
649
+ isFirstRejectionInWindow: data.count === data.limit + 1,
650
+ };
651
+ }
652
+
653
+ private static readCounterResult(
654
+ result: [Error | null, unknown] | undefined,
655
+ ): number {
656
+ if (!result) {
657
+ throw new Error("Rate limit counter returned no result");
658
+ }
659
+
660
+ const [error, value] = result;
661
+
662
+ if (error) {
663
+ throw error;
664
+ }
665
+
666
+ if (typeof value !== "number") {
667
+ throw new Error("Rate limit counter returned a non-numeric value");
668
+ }
669
+
670
+ return value;
671
+ }
672
+
673
+ private static getWindowIndex(windowSeconds: number): number {
674
+ return Math.floor(Date.now() / (windowSeconds * 1000));
675
+ }
676
+
677
+ /*
678
+ * Remaining seconds in the window of the counter that refused, so a
679
+ * rejected caller is told to come back when that window actually rolls -
680
+ * an hour for the per-form ceiling, a quarter of one for the per-address
681
+ * counters - rather than every caller backing off by one constant and
682
+ * colliding again.
683
+ */
684
+ private static getSecondsUntilWindowEnd(windowSeconds: number): number {
685
+ const windowMs: number = windowSeconds * 1000;
686
+ const msIntoWindow: number = Date.now() % windowMs;
687
+
688
+ return Math.max(1, Math.ceil((windowMs - msIntoWindow) / 1000));
689
+ }
690
+
691
+ /*
692
+ * The middleware only ever refuses on the per-address counters, so a
693
+ * refused submission is always about the caller's network. (The form's
694
+ * own ceiling has its own words: see IncidentFormCeilingException.)
695
+ */
696
+ private static getRateLimitedMessage(
697
+ bucket: IncidentFormRateLimitBucket,
698
+ ): string {
699
+ if (bucket === IncidentFormRateLimitBucket.Read) {
700
+ return INCIDENT_FORM_READ_RATE_LIMIT_MESSAGE;
701
+ }
702
+
703
+ return INCIDENT_FORM_SUBMIT_RATE_LIMIT_MESSAGE;
704
+ }
705
+
706
+ /*
707
+ * Express middleware, mounted on each public form route ahead of
708
+ * UserMiddleware (it reads :shareKey from req.params, so it must sit on
709
+ * the route rather than the router), so a flood is refused before it costs
710
+ * a session lookup, let alone a Postgres read or a captcha check.
711
+ */
712
+ public static getMiddleware(
713
+ bucket: IncidentFormRateLimitBucket = IncidentFormRateLimitBucket.Read,
714
+ ): (
715
+ req: ExpressRequest,
716
+ res: ExpressResponse,
717
+ next: NextFunction,
718
+ ) => Promise<void> {
719
+ return async (
720
+ req: ExpressRequest,
721
+ res: ExpressResponse,
722
+ next: NextFunction,
723
+ ): Promise<void> => {
724
+ const config: IncidentFormRateLimitBucketConfig =
725
+ IncidentFormRateLimit.getConfig(bucket);
726
+ const formKey: string = IncidentFormRateLimit.resolveFormKey(req);
727
+ const clientIp: string = IncidentFormRateLimit.resolveClientIp(req);
728
+
729
+ const decision: IncidentFormRateLimitDecision =
730
+ await IncidentFormRateLimit.consume({
731
+ formKey,
732
+ clientIp,
733
+ bucket,
734
+ });
735
+
736
+ if (decision.outcome === IncidentFormRateLimitOutcome.RateLimited) {
737
+ if (decision.retryAfterSeconds) {
738
+ IncidentFormRateLimit.setRetryAfterHeader(
739
+ res,
740
+ decision.retryAfterSeconds,
741
+ );
742
+ }
743
+
744
+ if (decision.isFirstRejectionInWindow) {
745
+ logger.warn(
746
+ `IncidentFormRateLimit: rejected ${bucket} request for incident form ${formKey} from ${clientIp} (${decision.scope} limit)`,
747
+ );
748
+ }
749
+
750
+ return Response.sendErrorResponse(
751
+ req,
752
+ res,
753
+ new TooManyRequestsException(
754
+ IncidentFormRateLimit.getRateLimitedMessage(bucket),
755
+ ),
756
+ );
757
+ }
758
+
759
+ if (
760
+ decision.outcome === IncidentFormRateLimitOutcome.CounterUnavailable
761
+ ) {
762
+ /*
763
+ * The two buckets fail in opposite directions, on purpose.
764
+ *
765
+ * Reads fail OPEN. Showing a form's questions is read-only, and the
766
+ * counter there is load control: turning every company's report
767
+ * form into an error page because Redis blipped is worse than an
768
+ * unbounded window for the length of the blip, which is itself
769
+ * alarmed on.
770
+ *
771
+ * Submits fail CLOSED. There the counter is the only bound on how
772
+ * many incidents - and pages - a link can produce. Serving the route
773
+ * without it would serve an unlimited pager, so the reporter gets a
774
+ * 503 and can send the report when Redis is back.
775
+ */
776
+ if (config.failsClosed) {
777
+ if (IncidentFormRateLimit.shouldLogCounterUnavailable(bucket)) {
778
+ logger.error(
779
+ `IncidentFormRateLimit: rate limit counter unavailable, refusing incident form submissions (incident form ${formKey})`,
780
+ );
781
+ }
782
+
783
+ return Response.sendErrorResponse(
784
+ req,
785
+ res,
786
+ new ServiceUnavailableException(
787
+ INCIDENT_FORM_RATE_LIMIT_UNAVAILABLE_MESSAGE,
788
+ ),
789
+ );
790
+ }
791
+
792
+ if (IncidentFormRateLimit.shouldLogCounterUnavailable(bucket)) {
793
+ logger.warn(
794
+ "IncidentFormRateLimit: rate limit counter unavailable, serving incident forms unthrottled",
795
+ );
796
+ logger.warn(getLogAttributesFromRequest(req as OneUptimeRequest));
797
+ }
798
+ }
799
+
800
+ return next();
801
+ };
802
+ }
803
+
804
+ /*
805
+ * A Redis outage puts EVERY request on the unavailable path, so an
806
+ * unguarded log line there is one per request for as long as the outage
807
+ * lasts. One line per bucket per interval is enough to make the condition
808
+ * visible without burying everything else.
809
+ */
810
+ private static shouldLogCounterUnavailable(
811
+ bucket: IncidentFormRateLimitBucket,
812
+ ): boolean {
813
+ const now: number = Date.now();
814
+ const lastLoggedAt: number =
815
+ IncidentFormRateLimit.counterUnavailableLastLoggedAt.get(bucket) || 0;
816
+
817
+ if (now - lastLoggedAt < COUNTER_UNAVAILABLE_LOG_INTERVAL_MS) {
818
+ return false;
819
+ }
820
+
821
+ IncidentFormRateLimit.counterUnavailableLastLoggedAt.set(bucket, now);
822
+
823
+ return true;
824
+ }
825
+
826
+ private static counterUnavailableLastLoggedAt: Map<
827
+ IncidentFormRateLimitBucket,
828
+ number
829
+ > = new Map();
830
+
831
+ private static setRetryAfterHeader(
832
+ res: ExpressResponse,
833
+ retryAfterSeconds: number,
834
+ ): void {
835
+ const setHeader: unknown = (res as unknown as Record<string, unknown>)[
836
+ "setHeader"
837
+ ];
838
+
839
+ if (typeof setHeader === "function") {
840
+ (setHeader as (name: string, value: string) => void).call(
841
+ res,
842
+ "Retry-After",
843
+ String(retryAfterSeconds),
844
+ );
845
+ }
846
+ }
847
+ }