@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,1180 @@
1
+ import { afterEach, describe, expect, it, jest } from "@jest/globals";
2
+ import type { SpyInstance } from "jest-mock";
3
+ import { marked, Token, Tokens } from "marked";
4
+ import {
5
+ htmlToMarkdown,
6
+ markdownToHtml,
7
+ } from "../../../UI/Components/Markdown.tsx/MarkdownConverters";
8
+ import {
9
+ clipboardToMarkdown,
10
+ isRichClipboardHtml,
11
+ normalizePlainTextListMarkers,
12
+ pastedHtmlToMarkdown,
13
+ PastedClipboard,
14
+ } from "../../../UI/Components/Markdown.tsx/MarkdownPaste";
15
+ import {
16
+ CHROME_CODE_VIEW_TABLE_COPY_HTML,
17
+ CHROME_VIEWER_CODE_LINES_COPY_HTML,
18
+ CHROME_VIEWER_CODE_PART_OF_LINE_COPY_HTML,
19
+ CHROME_VIEWER_CODE_WORD_COPY_HTML,
20
+ CHROME_VIEWER_COPY_HTML,
21
+ CHROME_VIEWER_COPY_TEXT,
22
+ CODE_VIEW_TABLE_COPY_TEXT,
23
+ FIREFOX_VIEWER_CODE_LINES_COPY_HTML,
24
+ FIREFOX_VIEWER_CODE_PART_OF_LINE_COPY_HTML,
25
+ FIREFOX_VIEWER_CODE_WORD_COPY_HTML,
26
+ FIREFOX_VIEWER_COPY_HTML,
27
+ FIREFOX_VIEWER_COPY_TEXT,
28
+ GOOGLE_DOCS_LIST_COPY_HTML,
29
+ GOOGLE_DOCS_LIST_COPY_MARKDOWN,
30
+ GOOGLE_DOCS_LIST_COPY_TEXT,
31
+ VIEWER_CODE_LINES_COPY_TEXT,
32
+ VIEWER_COPY_SOURCE_MARKDOWN,
33
+ WEBKIT_CODE_VIEW_TABLE_COPY_HTML,
34
+ WEBKIT_VIEWER_CODE_PART_OF_LINE_COPY_HTML,
35
+ WEBKIT_VIEWER_CODE_WORD_COPY_HTML,
36
+ WORD_OUTLOOK_ISSUE_4114_HTML,
37
+ } from "./fixtures/MarkdownPasteFixtures";
38
+
39
+ /*
40
+ * Clipboard -> markdown for the MarkdownEditor (issue #4114: a pasted bullet
41
+ * showed its dot but was not a list, nested lists came out flat, and copying
42
+ * a previous incident lost its formatting).
43
+ *
44
+ * Every conversion is checked three ways: the exact markdown written, the
45
+ * list nesting as marked (the email renderer) reads it, and that the result
46
+ * is a fixed point of the editor's render / serialize loop -- markdown the
47
+ * editor would rewrite on the next keystroke is not a finished paste.
48
+ */
49
+
50
+ const NBSP: string = String.fromCharCode(0xa0);
51
+ const SYMBOL_FONT_BULLET: string = String.fromCharCode(0xf0b7);
52
+ const WINGDINGS_SQUARE: string = String.fromCharCode(0xf0a7);
53
+
54
+ // A list's nesting as marked sees it: "ul[li[ul[li]],li]".
55
+ const listShape: (markdown: string) => string = (markdown: string): string => {
56
+ const describe: (token: Token) => string = (token: Token): string => {
57
+ if (token.type !== "list") {
58
+ return token.type;
59
+ }
60
+ const list: Tokens.List = token as Tokens.List;
61
+ const items: Array<string> = list.items.map(
62
+ (item: Tokens.ListItem): string => {
63
+ const nested: Array<string> = item.tokens
64
+ .filter((child: Token): boolean => {
65
+ return child.type === "list";
66
+ })
67
+ .map(describe);
68
+ return nested.length > 0 ? `li[${nested.join("")}]` : "li";
69
+ },
70
+ );
71
+ return `${list.ordered ? "ol" : "ul"}[${items.join(",")}]`;
72
+ };
73
+ return marked
74
+ .lexer(markdown)
75
+ .filter((token: Token): boolean => {
76
+ return token.type !== "space";
77
+ })
78
+ .map(describe)
79
+ .join(" ");
80
+ };
81
+
82
+ // What the editor saves after rendering `markdown` and serializing it back.
83
+ const afterEditorLoop: (markdown: string) => string = (
84
+ markdown: string,
85
+ ): string => {
86
+ return htmlToMarkdown(markdownToHtml(markdown));
87
+ };
88
+
89
+ const clipboard: (
90
+ data: { [format: string]: string },
91
+ types?: ReadonlyArray<string>,
92
+ ) => PastedClipboard = (
93
+ data: { [format: string]: string },
94
+ types?: ReadonlyArray<string>,
95
+ ): PastedClipboard => {
96
+ return {
97
+ getData: (format: string): string => {
98
+ return data[format] ?? "";
99
+ },
100
+ types: types ?? Object.keys(data),
101
+ };
102
+ };
103
+
104
+ describe("normalizePlainTextListMarkers", () => {
105
+ /*
106
+ * Word and Outlook write a list into plain text as a bullet character and
107
+ * a tab, and mark the level with the character alone -- "•", then "o",
108
+ * then "§" -- without indenting anything.
109
+ */
110
+ it("turns Word's plain-text bullets into a nested markdown list", () => {
111
+ const markdown: string = normalizePlainTextListMarkers(
112
+ "•\tService down\no\tUsers cannot log in\no\tError shown\n•\tInvestigating\no\tTeam notified\n§\tPaged",
113
+ );
114
+
115
+ expect(markdown).toBe(
116
+ "- Service down\n - Users cannot log in\n - Error shown\n- Investigating\n - Team notified\n - Paged",
117
+ );
118
+ expect(listShape(markdown)).toBe("ul[li[ul[li,li]],li[ul[li[ul[li]]]]]");
119
+ expect(afterEditorLoop(markdown)).toBe(markdown);
120
+ });
121
+
122
+ it("reads Word's Symbol and Wingdings bullets from the private use area", () => {
123
+ expect(
124
+ normalizePlainTextListMarkers(
125
+ `${SYMBOL_FONT_BULLET}\tA\no\tB\n${WINGDINGS_SQUARE}\tC`,
126
+ ),
127
+ ).toBe("- A\n - B\n - C");
128
+ });
129
+
130
+ it("never opens a level more than one deeper than the item above", () => {
131
+ expect(normalizePlainTextListMarkers("•\ta\n§\tb")).toBe("- a\n - b");
132
+ expect(normalizePlainTextListMarkers("o\tfirst")).toBe("- first");
133
+ });
134
+
135
+ it("nests by indentation when the text is indented, as Slack writes it", () => {
136
+ const markdown: string = normalizePlainTextListMarkers(
137
+ "• Main item\n ◦ Nested item\n ▪ Further nested\n• Next",
138
+ );
139
+
140
+ expect(markdown).toBe(
141
+ "- Main item\n - Nested item\n - Further nested\n- Next",
142
+ );
143
+ expect(listShape(markdown)).toBe("ul[li[ul[li[ul[li]]]],li]");
144
+ });
145
+
146
+ it("counts a tab of indentation as four columns", () => {
147
+ expect(normalizePlainTextListMarkers("•\tA\n\t•\tB\n•\tC")).toBe(
148
+ "- A\n - B\n- C",
149
+ );
150
+ });
151
+
152
+ /*
153
+ * "●", "○", "■" are the bullets of three levels (the ones Google Docs
154
+ * draws, though its own plain text has no bullets at all); a dash or an
155
+ * arrow says nothing about the level, so it is a top-level item.
156
+ */
157
+ it("reads the other bullets and dashes people use", () => {
158
+ expect(normalizePlainTextListMarkers("● one\n○ two\n■ three")).toBe(
159
+ "- one\n - two\n - three",
160
+ );
161
+ expect(normalizePlainTextListMarkers("– four\n— five")).toBe(
162
+ "- four\n- five",
163
+ );
164
+ expect(normalizePlainTextListMarkers("➤ go\n► on")).toBe("- go\n- on");
165
+ });
166
+
167
+ it("takes a non-breaking space after the bullet", () => {
168
+ expect(normalizePlainTextListMarkers(`•${NBSP}item`)).toBe("- item");
169
+ });
170
+
171
+ it("writes numbered lines with a parenthesis the way the editor reads them", () => {
172
+ expect(normalizePlainTextListMarkers("1) one\n2) two")).toBe(
173
+ "1. one\n2. two",
174
+ );
175
+ });
176
+
177
+ it("starts again at the top after a paragraph ends the list", () => {
178
+ expect(
179
+ normalizePlainTextListMarkers("•\ta\no\tb\nA paragraph.\no\tc"),
180
+ ).toBe("- a\n - b\nA paragraph.\n- c");
181
+ });
182
+
183
+ it("keeps a blank line between two bullets inside the same list", () => {
184
+ expect(normalizePlainTextListMarkers("•\ta\n\no\tb")).toBe("- a\n\n - b");
185
+ });
186
+
187
+ it("leaves the inside of a fenced code block alone", () => {
188
+ expect(
189
+ normalizePlainTextListMarkers("```\n• not a list\n1) nor this\n```\n• a"),
190
+ ).toBe("```\n• not a list\n1) nor this\n```\n- a");
191
+ });
192
+
193
+ it("reads Windows line endings", () => {
194
+ expect(normalizePlainTextListMarkers("•\ta\r\n•\tb")).toBe("- a\n- b");
195
+ });
196
+
197
+ describe("returns text with no bullet lines exactly as it came", () => {
198
+ const untouched: Array<string> = [
199
+ "Price • quality",
200
+ "o no, not again",
201
+ "o gato\no cão",
202
+ "•item without a space",
203
+ "- already markdown\n - nested",
204
+ "Line one\r\nLine two",
205
+ "",
206
+ ];
207
+ for (const text of untouched) {
208
+ it(JSON.stringify(text), () => {
209
+ expect(normalizePlainTextListMarkers(text)).toBe(text);
210
+ });
211
+ }
212
+ });
213
+ });
214
+
215
+ describe("pastedHtmlToMarkdown", () => {
216
+ describe("Word and Outlook", () => {
217
+ /*
218
+ * The complaint in issue #4114 itself: its body is Outlook's clipboard
219
+ * HTML, with nested lists written as a <ul> directly inside a <ul> --
220
+ * which the serializer skipped, flattening every nested item away.
221
+ */
222
+ it("keeps the nested lists of the issue's own Outlook HTML", () => {
223
+ const markdown: string = pastedHtmlToMarkdown(
224
+ WORD_OUTLOOK_ISSUE_4114_HTML,
225
+ );
226
+
227
+ expect(markdown).toContain(
228
+ "For example, a previous incident might contain:\n\n- Service is currently unavailable\n - Users are unable to log in\n - Users are receiving an error message\n- Investigation is in progress\n - Technical team has been notified\n - Vendor has been contacted\n\nA user may want to copy",
229
+ );
230
+ expect(markdown).toContain(
231
+ "For example:\n\n- Main item\n - Nested item\n - Further nested item\n\nThe underlying Markdown",
232
+ );
233
+ });
234
+
235
+ it("writes the whole document as markdown the editor keeps as it is", () => {
236
+ const markdown: string = pastedHtmlToMarkdown(
237
+ WORD_OUTLOOK_ISSUE_4114_HTML,
238
+ );
239
+
240
+ expect(afterEditorLoop(markdown)).toBe(markdown);
241
+ expect(
242
+ markdown.startsWith(
243
+ "**Is your feature request related to a problem? Please describe.**\n\nWith the new custom fields",
244
+ ),
245
+ ).toBe(true);
246
+ expect(markdown).toContain("\n\n---\n\n**Markdown Editor Enhancements**");
247
+ expect(markdown).toContain(
248
+ "- **Shown / Hidden**\n- **Required / Optional**",
249
+ );
250
+ expect(markdown).toContain(
251
+ "**Which fields are displayed → Which fields are required → What the message looks like**",
252
+ );
253
+ });
254
+
255
+ it("gives marked the same nesting", () => {
256
+ const markdown: string = pastedHtmlToMarkdown(
257
+ WORD_OUTLOOK_ISSUE_4114_HTML,
258
+ );
259
+
260
+ expect(listShape(markdown)).toContain("ul[li[ul[li,li]],li[ul[li,li]]]");
261
+ expect(listShape(markdown)).toContain("ul[li[ul[li[ul[li]]]]]");
262
+ });
263
+
264
+ it("joins Word's hard-wrapped lines and leaks none of its markup", () => {
265
+ const markdown: string = pastedHtmlToMarkdown(
266
+ WORD_OUTLOOK_ISSUE_4114_HTML,
267
+ );
268
+
269
+ expect(markdown).toContain("- Affected Location\n");
270
+ expect(markdown).not.toMatch(/Service\s*\n\s+is currently/);
271
+ for (const leak of [
272
+ "<",
273
+ "mso",
274
+ "o:p",
275
+ "StartFragment",
276
+ "VML",
277
+ "WordDocument",
278
+ NBSP,
279
+ ]) {
280
+ expect(markdown).not.toContain(leak);
281
+ }
282
+ });
283
+
284
+ /*
285
+ * Word itself (rather than Outlook) writes a list as paragraphs, each with
286
+ * its level in a mso-list style and its bullet or number as text between
287
+ * <![if !supportLists]> and <![endif]>. Without reading that, the bullet
288
+ * came through as "·" at the start of a plain paragraph.
289
+ */
290
+ const wordParagraph: (
291
+ level: number,
292
+ marker: string,
293
+ text: string,
294
+ ) => string = (level: number, marker: string, text: string): string => {
295
+ return `<p class=MsoListParagraphCxSpMiddle style='margin-left:${36 * level}.0pt;mso-add-space:auto;text-indent:-18.0pt;mso-list:l0 level${level} lfo1'><![if !supportLists]><span style='font-family:Symbol;mso-fareast-font-family:Symbol'><span style='mso-list:Ignore'>${marker}<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><![endif]>${text}<o:p></o:p></p>\n`;
296
+ };
297
+
298
+ it("rebuilds Word's paragraph list, bullets removed, levels nested", () => {
299
+ const html: string =
300
+ "<p class=MsoNormal>Before<o:p></o:p></p>\n" +
301
+ wordParagraph(1, "·", "One") +
302
+ wordParagraph(2, "o", "Nested <b>bold</b>") +
303
+ wordParagraph(3, "§", "Deeper") +
304
+ wordParagraph(1, "·", "Two") +
305
+ "<p class=MsoNormal>After<o:p></o:p></p>";
306
+
307
+ const markdown: string = pastedHtmlToMarkdown(html);
308
+
309
+ expect(markdown).toBe(
310
+ "Before\n\n- One\n - Nested **bold**\n - Deeper\n- Two\n\nAfter",
311
+ );
312
+ expect(listShape(markdown)).toBe(
313
+ "paragraph ul[li[ul[li[ul[li]]]],li] paragraph",
314
+ );
315
+ expect(afterEditorLoop(markdown)).toBe(markdown);
316
+ });
317
+
318
+ it("reads a numbered Word list as an ordered list", () => {
319
+ const html: string =
320
+ wordParagraph(1, "1.", "First") +
321
+ wordParagraph(2, "a.", "Sub step") +
322
+ wordParagraph(1, "2.", "Second");
323
+
324
+ const markdown: string = pastedHtmlToMarkdown(html);
325
+
326
+ expect(markdown).toBe("1. First\n 1. Sub step\n2. Second");
327
+ expect(listShape(markdown)).toBe("ol[li[ol[li]],li]");
328
+ });
329
+
330
+ it("starts a new list where Word switches between bullets and numbers", () => {
331
+ const html: string =
332
+ wordParagraph(1, "·", "Bullet") + wordParagraph(1, "1.", "Number");
333
+
334
+ expect(pastedHtmlToMarkdown(html)).toBe("- Bullet\n\n1. Number");
335
+ });
336
+
337
+ it("strips a marker Word wrote without the conditional comments", () => {
338
+ const html: string =
339
+ "<p style='mso-list:l0 level1 lfo1'><span style='mso-list:Ignore'>·<span>&nbsp;&nbsp; </span></span>Only item</p>";
340
+
341
+ expect(pastedHtmlToMarkdown(html)).toBe("- Only item");
342
+ });
343
+
344
+ it("keeps an <o:p> that holds text, and drops an empty one", () => {
345
+ expect(
346
+ pastedHtmlToMarkdown(
347
+ "<p class=MsoNormal>a<o:p>b</o:p></p><p class=MsoNormal><o:p>&nbsp;</o:p></p><p>c</p>",
348
+ ),
349
+ ).toBe("ab\n\nc");
350
+ });
351
+ });
352
+
353
+ describe("Google Docs", () => {
354
+ /*
355
+ * The shape of a Google Docs copy: everything inside one
356
+ * <b style="font-weight:normal" id="docs-internal-guid-...">, formatting
357
+ * as span styles, each item's text in a <p>, and nested lists directly
358
+ * inside their parent list.
359
+ */
360
+ const GOOGLE_DOCS_HTML: string =
361
+ '<meta charset="utf-8"><b style="font-weight:normal;" id="docs-internal-guid-2f1b3c4d-7fff-a1b2-c3d4-e5f6a7b8c9d0"><ul style="margin-top:0;margin-bottom:0;padding-inline-start:48px;"><li dir="ltr" style="list-style-type:disc;font-size:11pt;font-family:Arial,sans-serif;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;" aria-level="1"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;" role="presentation"><span style="font-size:11pt;font-family:Arial,sans-serif;color:#000000;background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Bold</span><span style="font-size:11pt;font-family:Arial,sans-serif;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;"> and </span><span style="font-size:11pt;font-family:Arial,sans-serif;color:#000000;background-color:transparent;font-weight:400;font-style:italic;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">italic</span></p></li><ul style="margin-top:0;margin-bottom:0;padding-inline-start:48px;"><li dir="ltr" aria-level="2"><p dir="ltr" role="presentation"><a href="https://example.com/runbook" style="text-decoration:none;"><span style="font-size:11pt;color:#1155cc;font-weight:400;text-decoration:underline;white-space:pre;white-space:pre-wrap;">runbook</span></a><span style="font-weight:400;white-space:pre;white-space:pre-wrap;"> </span><span style="font-weight:400;text-decoration:line-through;white-space:pre;white-space:pre-wrap;">gone</span></p></li></ul><li dir="ltr" aria-level="1"><p dir="ltr" role="presentation"><span style="font-weight:700;font-style:italic;white-space:pre;white-space:pre-wrap;">Both</span></p></li></ul><br></b>';
362
+
363
+ it("unwraps the whole-document bold and reads formatting from styles", () => {
364
+ const markdown: string = pastedHtmlToMarkdown(GOOGLE_DOCS_HTML);
365
+
366
+ expect(markdown).toBe(
367
+ "- **Bold** and *italic*\n - [runbook](https://example.com/runbook) ~~gone~~\n- ***Both***",
368
+ );
369
+ expect(listShape(markdown)).toBe("ul[li[ul[li]],li]");
370
+ expect(afterEditorLoop(markdown)).toBe(markdown);
371
+ });
372
+
373
+ it("renders text that is bold and italic at once as both", () => {
374
+ expect(markdownToHtml(pastedHtmlToMarkdown(GOOGLE_DOCS_HTML))).toContain(
375
+ "<em><strong>Both</strong></em>",
376
+ );
377
+ });
378
+
379
+ /*
380
+ * Docs puts "white-space:pre" on every list item it copies, and the
381
+ * paste took that for a code editor's copy (VS Code's white-space:pre
382
+ * <div>) and used the plain text instead -- the lines alone, with no
383
+ * bullets -- so every Docs copy with a list lost its lists, links and
384
+ * formatting. These go through the editor's own entry point.
385
+ */
386
+ it("counts a Docs copy with a list in it as rich", () => {
387
+ expect(isRichClipboardHtml(GOOGLE_DOCS_HTML)).toBe(true);
388
+ expect(isRichClipboardHtml(GOOGLE_DOCS_LIST_COPY_HTML)).toBe(true);
389
+ });
390
+
391
+ it("pastes a Docs list as the list it is, not as its plain text", () => {
392
+ expect(
393
+ clipboardToMarkdown(
394
+ clipboard({
395
+ "text/html": GOOGLE_DOCS_HTML,
396
+ "text/plain": "Bold and italic\nrunbook gone\nBoth",
397
+ }),
398
+ ),
399
+ ).toBe(
400
+ "- **Bold** and *italic*\n - [runbook](https://example.com/runbook) ~~gone~~\n- ***Both***",
401
+ );
402
+ expect(
403
+ clipboardToMarkdown(
404
+ clipboard({
405
+ "text/html": GOOGLE_DOCS_LIST_COPY_HTML,
406
+ "text/plain": GOOGLE_DOCS_LIST_COPY_TEXT,
407
+ }),
408
+ ),
409
+ ).toBe(GOOGLE_DOCS_LIST_COPY_MARKDOWN);
410
+ });
411
+
412
+ // Chromium, Safari and Docs write a tab as a white-space:pre <span>.
413
+ it("counts a Docs paragraph with a tab in it as rich", () => {
414
+ const html: string =
415
+ '<b style="font-weight:normal;" id="docs-internal-guid-2"><p dir="ltr"><span style="font-weight:700;white-space:pre;white-space:pre-wrap;">Owner:</span><span style="font-weight:400;white-space:pre;white-space:pre-wrap;"><span class="Apple-tab-span" style="white-space:pre;">\t</span>Jane</span></p></b>';
416
+
417
+ expect(isRichClipboardHtml(html)).toBe(true);
418
+ expect(
419
+ clipboardToMarkdown(
420
+ clipboard({ "text/html": html, "text/plain": "Owner:\tJane" }),
421
+ ),
422
+ ).toBe("**Owner:** Jane");
423
+ });
424
+
425
+ it("counts plain Docs text as plain, so its plain text is pasted", () => {
426
+ expect(
427
+ isRichClipboardHtml(
428
+ '<b style="font-weight:normal;" id="docs-internal-guid-1"><span style="font-weight:400;white-space:pre-wrap;">Just text</span></b>',
429
+ ),
430
+ ).toBe(false);
431
+ });
432
+ });
433
+
434
+ describe("a note copied out of MarkdownViewer", () => {
435
+ /*
436
+ * Real copies of two lines of a viewer code block: neither browser keeps
437
+ * the block's <div>, only the <pre> around the text, which carries the
438
+ * viewer's hints -- so the lines come back as a fenced block in their
439
+ * language rather than as markdown ("- name: web" a list item).
440
+ */
441
+ it("comes back as a fenced block when only some of a code block's lines were copied", () => {
442
+ for (const html of [
443
+ CHROME_VIEWER_CODE_LINES_COPY_HTML,
444
+ FIREFOX_VIEWER_CODE_LINES_COPY_HTML,
445
+ ]) {
446
+ expect(
447
+ clipboardToMarkdown(
448
+ clipboard({
449
+ "text/html": html,
450
+ "text/plain": VIEWER_CODE_LINES_COPY_TEXT,
451
+ }),
452
+ ),
453
+ ).toBe("```yaml\nreplicas: 3\nimage: api_server:v2\n```");
454
+ }
455
+ });
456
+
457
+ /*
458
+ * Every browser keeps the viewer's hinted <pre> around even a word it
459
+ * copies. As a fenced block, a pod name copied out of a note split the
460
+ * sentence it was pasted into, and in the markdown source ran into the
461
+ * rest of the line.
462
+ */
463
+ it("comes back as inline code when less than a line of a code block was copied", () => {
464
+ for (const html of [
465
+ CHROME_VIEWER_CODE_WORD_COPY_HTML,
466
+ FIREFOX_VIEWER_CODE_WORD_COPY_HTML,
467
+ WEBKIT_VIEWER_CODE_WORD_COPY_HTML,
468
+ ]) {
469
+ expect(
470
+ clipboardToMarkdown(
471
+ clipboard({ "text/html": html, "text/plain": "api_server" }),
472
+ ),
473
+ ).toBe("`api_server`");
474
+ }
475
+ for (const html of [
476
+ CHROME_VIEWER_CODE_PART_OF_LINE_COPY_HTML,
477
+ FIREFOX_VIEWER_CODE_PART_OF_LINE_COPY_HTML,
478
+ WEBKIT_VIEWER_CODE_PART_OF_LINE_COPY_HTML,
479
+ ]) {
480
+ expect(
481
+ clipboardToMarkdown(
482
+ clipboard({ "text/html": html, "text/plain": "kubectl get pods" }),
483
+ ),
484
+ ).toBe("`kubectl get pods`");
485
+ }
486
+ });
487
+
488
+ /*
489
+ * A line triple-clicked in Chromium or Safari is copied with its line
490
+ * break: a line of the block, which stays a fenced block of its own.
491
+ */
492
+ it("keeps a line copied with its line break a fenced block", () => {
493
+ expect(
494
+ pastedHtmlToMarkdown(
495
+ '<pre data-markdown-code-block="true" data-language="bash"><code>npm install\n</code></pre>',
496
+ ),
497
+ ).toBe("```bash\nnpm install\n```");
498
+ });
499
+
500
+ /*
501
+ * A copy that carries the block's root -- all of a one-line block, or a
502
+ * line Chromium and Safari triple-click -- is the block, language and
503
+ * all.
504
+ */
505
+ it("keeps a one-line block copied whole a fenced block", () => {
506
+ expect(
507
+ pastedHtmlToMarkdown(
508
+ '<div data-markdown-code-block="true" data-language="bash"><div data-markdown-ignore="true"><span>Bash</span><button>Copy</button></div><pre data-markdown-code-block="true" data-language="bash"><code>npm install</code></pre></div>',
509
+ ),
510
+ ).toBe("```bash\nnpm install\n```");
511
+ });
512
+
513
+ // Inline code has no way to hold a backtick of its own.
514
+ it("keeps less than a line holding a backtick a fenced block", () => {
515
+ expect(
516
+ pastedHtmlToMarkdown(
517
+ '<pre data-markdown-code-block="true" data-language="bash"><code>echo `date`</code></pre>',
518
+ ),
519
+ ).toBe("```bash\necho `date`\n```");
520
+ });
521
+
522
+ /*
523
+ * The fixtures are real copies of the real viewer: the code block comes
524
+ * back as a fence with its language (not the "Copy" button's text), the
525
+ * localized timestamp as the ISO value it was rendered from, and every
526
+ * list at its depth -- the same markdown the note was written in.
527
+ */
528
+ it("comes back from Chromium's copy exactly as the note was written", () => {
529
+ const markdown: string = pastedHtmlToMarkdown(CHROME_VIEWER_COPY_HTML);
530
+
531
+ expect(markdown).toBe(VIEWER_COPY_SOURCE_MARKDOWN);
532
+ expect(afterEditorLoop(markdown)).toBe(markdown);
533
+ });
534
+
535
+ it("comes back from Firefox's copy exactly as the note was written", () => {
536
+ const markdown: string = pastedHtmlToMarkdown(FIREFOX_VIEWER_COPY_HTML);
537
+
538
+ expect(markdown).toBe(VIEWER_COPY_SOURCE_MARKDOWN);
539
+ });
540
+
541
+ it("leaves out the code block's Copy button and language label", () => {
542
+ const markdown: string = pastedHtmlToMarkdown(CHROME_VIEWER_COPY_HTML);
543
+
544
+ expect(markdown).not.toMatch(/\bCopy\b/);
545
+ expect(markdown).not.toContain("TYPESCRIPT");
546
+ });
547
+
548
+ it("writes a code block without a language as a bare fence", () => {
549
+ expect(
550
+ pastedHtmlToMarkdown(
551
+ '<div data-markdown-code-block="true" data-language="text"><div data-markdown-ignore="true"><span>Text</span><button>Copy</button></div><div style="white-space: pre;"><code class="font-mono">line 1\nline 2</code></div></div>',
552
+ ),
553
+ ).toBe("```\nline 1\nline 2\n```");
554
+ });
555
+
556
+ it("ignores a language attribute that is not a language name", () => {
557
+ expect(
558
+ pastedHtmlToMarkdown(
559
+ '<div data-markdown-code-block="true" data-language="x`y"><code>a</code></div>',
560
+ ),
561
+ ).toBe("```\na\n```");
562
+ });
563
+
564
+ it("keeps the text of a timestamp that is not the viewer's", () => {
565
+ expect(
566
+ pastedHtmlToMarkdown(
567
+ '<p>Due <time datetime="2026-05-01">May 1</time></p>',
568
+ ),
569
+ ).toBe("Due May 1");
570
+ });
571
+ });
572
+
573
+ describe("lists", () => {
574
+ it("moves a list written directly inside a list into the item before it", () => {
575
+ expect(
576
+ pastedHtmlToMarkdown(
577
+ "<ul><li>a</li><ul><li>b</li><ol><li>c</li></ol></ul><li>d</li></ul>",
578
+ ),
579
+ ).toBe("- a\n - b\n 1. c\n- d");
580
+ });
581
+
582
+ it("gives a list with no item before it an item of its own", () => {
583
+ expect(pastedHtmlToMarkdown("<ul><ul><li>a</li></ul></ul>")).toBe(
584
+ "- - a",
585
+ );
586
+ });
587
+
588
+ it("wraps loose content in a list in an item instead of dropping it", () => {
589
+ expect(
590
+ pastedHtmlToMarkdown("<ul><span>x</span> y<li>a</li><p>z</p></ul>"),
591
+ ).toBe("- x y\n- a\n- z");
592
+ });
593
+
594
+ it("keeps a task list's boxes", () => {
595
+ expect(
596
+ pastedHtmlToMarkdown(
597
+ '<ul><li><input type="checkbox" checked> done</li><li><input type="checkbox"> todo</li></ul>',
598
+ ),
599
+ ).toBe("- [x] done\n- [ ] todo");
600
+ });
601
+
602
+ it("keeps an item with two paragraphs loose", () => {
603
+ expect(pastedHtmlToMarkdown("<ul><li><p>a</p><p>b</p></li></ul>")).toBe(
604
+ "- a\n\n b",
605
+ );
606
+ });
607
+ });
608
+
609
+ describe("whitespace", () => {
610
+ it("collapses runs of whitespace and non-breaking spaces outside code", () => {
611
+ expect(pastedHtmlToMarkdown(`<p>a \n\t b&nbsp;&nbsp;c${NBSP}d</p>`)).toBe(
612
+ "a b c d",
613
+ );
614
+ });
615
+
616
+ it("keeps the whitespace of a code block", () => {
617
+ expect(
618
+ pastedHtmlToMarkdown("<pre><code> indented\n\n more</code></pre>"),
619
+ ).toBe("```\n indented\n\n more\n```");
620
+ });
621
+
622
+ it("drops the whitespace between blocks and at their edges", () => {
623
+ expect(
624
+ pastedHtmlToMarkdown(
625
+ "\n<p>\n <span> one </span>\n</p>\n\n<p> two <br> three </p>\n",
626
+ ),
627
+ ).toBe("one\n\ntwo\nthree");
628
+ });
629
+
630
+ it("writes one space where spaces meet across inline elements", () => {
631
+ expect(
632
+ pastedHtmlToMarkdown("<p><span>a </span> <span> b</span></p>"),
633
+ ).toBe("a b");
634
+ });
635
+
636
+ it("keeps the spaces on either side of an image", () => {
637
+ expect(
638
+ pastedHtmlToMarkdown('<p>a <img src="https://i.test/x.png"> b</p>'),
639
+ ).toBe("a ![](https://i.test/x.png) b");
640
+ });
641
+
642
+ it("keeps the space between two formatted words", () => {
643
+ expect(pastedHtmlToMarkdown("<p><b>a</b> <i>b</i></p>")).toBe(
644
+ "**a** *b*",
645
+ );
646
+ });
647
+
648
+ /*
649
+ * "**bold **text" is not bold in CommonMark: marked (the email) and the
650
+ * viewer print the asterisks.
651
+ */
652
+ it("moves the spaces at the edge of bold or italic text outside it", () => {
653
+ const markdown: string = pastedHtmlToMarkdown(
654
+ "<p><b>bold </b>text <i> italic</i> end</p>",
655
+ );
656
+
657
+ expect(markdown).toBe("**bold** text *italic* end");
658
+ expect(marked.parse(markdown)).toContain("<strong>bold</strong>");
659
+ });
660
+
661
+ it("drops empty formatting and keeps the space it held", () => {
662
+ expect(pastedHtmlToMarkdown("<p>a<b> </b>b<i></i>c<s></s></p>")).toBe(
663
+ "a bc",
664
+ );
665
+ });
666
+ });
667
+
668
+ describe("links and images", () => {
669
+ it("keeps http, https, mailto, tel and relative links", () => {
670
+ expect(
671
+ pastedHtmlToMarkdown(
672
+ '<p><a href="https://a.test/x">a</a> <a href="http://b.test">b</a> <a href="mailto:ops@c.test">c</a> <a href="tel:+15550100">d</a> <a href="/dashboard/1">e</a> <a href="#part">f</a></p>',
673
+ ),
674
+ ).toBe(
675
+ "[a](https://a.test/x) [b](http://b.test) [c](mailto:ops@c.test) [d](tel:+15550100) [e](/dashboard/1) [f](#part)",
676
+ );
677
+ });
678
+
679
+ it("keeps only the text of a link with any other scheme", () => {
680
+ expect(
681
+ pastedHtmlToMarkdown(
682
+ '<p><a href="javascript:alert(1)">js</a> <a href="JAVASCRIPT:alert(1)">upper</a> <a href="data:text/html,x">data</a> <a href="vbscript:x">vb</a> <a href="file:///C:/x">file</a> <a href="">empty</a></p>',
683
+ ),
684
+ ).toBe("js upper data vb file empty");
685
+ });
686
+
687
+ it("sees through a scheme hidden with whitespace, control characters or entities", () => {
688
+ const control: string = String.fromCharCode(1);
689
+ expect(
690
+ pastedHtmlToMarkdown(
691
+ `<p><a href="java\tscript:alert(1)">tab</a> <a href=" javascript:alert(1)">space</a> <a href="&#106;avascript:alert(1)">entity</a> <a href="${control}javascript:alert(1)">control</a></p>`,
692
+ ),
693
+ ).toBe("tab space entity control");
694
+ });
695
+
696
+ it("encodes the spaces and parentheses that would end a markdown link early", () => {
697
+ const markdown: string = pastedHtmlToMarkdown(
698
+ '<p><a href="https://w.test/wiki/Foo_(bar) baz">wiki</a></p>',
699
+ );
700
+
701
+ expect(markdown).toBe("[wiki](https://w.test/wiki/Foo_%28bar%29%20baz)");
702
+ expect(markdownToHtml(markdown)).toContain(
703
+ 'href="https://w.test/wiki/Foo_%28bar%29%20baz"',
704
+ );
705
+ });
706
+
707
+ it("keeps http, https and relative images and drops every other kind", () => {
708
+ expect(
709
+ pastedHtmlToMarkdown(
710
+ '<p><img src="https://i.test/a.png" alt="a"><img src="/file/image/b.png" alt="b"><img src="data:image/png;base64,AAAA" alt="c"><img src="blob:https://x/1" alt="d"><img src="file:///C:/e.png" alt="e"><img src="cid:image001.png@01D" alt="f"><img alt="g"></p>',
711
+ ),
712
+ ).toBe("![a](https://i.test/a.png)![b](/file/image/b.png)");
713
+ });
714
+
715
+ it("drops the viewer's sessionRetry cache buster from an image", () => {
716
+ expect(
717
+ pastedHtmlToMarkdown(
718
+ '<img src="https://oneuptime.test/file/image/access-token/t1?sessionRetry=1714"><img src="https://oneuptime.test/file/image/access-token/t2?sessionRetry=1&amp;v=2"><img src="https://oneuptime.test/x.png?v=2&amp;sessionRetry=9">',
719
+ ),
720
+ ).toBe(
721
+ "![](https://oneuptime.test/file/image/access-token/t1)![](https://oneuptime.test/file/image/access-token/t2?v=2)![](https://oneuptime.test/x.png?v=2)",
722
+ );
723
+ });
724
+
725
+ /*
726
+ * A link with nothing left to read once its icon is dropped came out
727
+ * with its URL as its text: every heading copied from a GitHub README
728
+ * gained a line of "[https://github.com/...#install](...)". Browsers
729
+ * make the href absolute on the clipboard, as here.
730
+ */
731
+ it("drops the permalink GitHub puts beside a heading", () => {
732
+ expect(
733
+ pastedHtmlToMarkdown(
734
+ '<div class="markdown-heading"><h2 class="heading-element">Install</h2><a id="user-content-install" class="anchor" aria-label="Permalink: Install" href="https://github.com/o/r#install"><svg class="octicon octicon-link" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275"></path></svg></a></div><p>Run <code>npm i</code>.</p>',
735
+ ),
736
+ ).toBe("## Install\n\nRun `npm i`.");
737
+ expect(
738
+ pastedHtmlToMarkdown(
739
+ '<h2><a class="anchor" href="https://github.com/o/r#install"><svg><path d="m7"></path></svg></a>Install</h2><p>Run <code>npm i</code>.</p>',
740
+ ),
741
+ ).toBe("## Install\n\nRun `npm i`.");
742
+ });
743
+
744
+ it("drops the empty and zero-width permalinks of GitLab and Docusaurus", () => {
745
+ expect(
746
+ pastedHtmlToMarkdown(
747
+ '<h2 id="setup"><a class="anchor" href="https://gitlab.test/g/p#setup" aria-hidden="true"></a>Setup</h2>',
748
+ ),
749
+ ).toBe("## Setup");
750
+ expect(
751
+ pastedHtmlToMarkdown(
752
+ '<h2>Install<a href="https://docs.test/intro#install" class="hash-link" aria-label="Direct link to Install">\u200b</a></h2>',
753
+ ),
754
+ ).toBe("## Install");
755
+ });
756
+
757
+ it("drops an icon-only link without running the words around it together", () => {
758
+ expect(
759
+ pastedHtmlToMarkdown(
760
+ '<p>Follow us <a href="https://social.test/oneuptime"><svg><path d="m1"></path></svg></a> and <b>more</b></p>',
761
+ ),
762
+ ).toBe("Follow us and **more**");
763
+ });
764
+
765
+ it("keeps a link with text, a linked image, and an icon beside text", () => {
766
+ expect(
767
+ pastedHtmlToMarkdown(
768
+ '<p><a href="https://a.test">text</a> <a href="https://b.test"><img src="https://i.test/b.png" alt="b"></a> <a href="https://c.test"><svg></svg>GitHub</a> a<a href="https://x.test"> </a>b</p>',
769
+ ),
770
+ ).toBe(
771
+ "[text](https://a.test) [![b](https://i.test/b.png)](https://b.test) [GitHub](https://c.test) a b",
772
+ );
773
+ });
774
+
775
+ it("drops a link whose only image was dropped", () => {
776
+ expect(
777
+ pastedHtmlToMarkdown(
778
+ '<p>see <a href="https://a.test"><img src="data:image/png;base64,AAAA"></a> here</p>',
779
+ ),
780
+ ).toBe("see here");
781
+ });
782
+
783
+ it("keeps an image's alt text from breaking the markdown around it", () => {
784
+ expect(
785
+ pastedHtmlToMarkdown(
786
+ '<img src="https://i.test/a.png" alt="a [b]\n c" title="has &quot;quotes&quot;">',
787
+ ),
788
+ ).toBe("![a b c](https://i.test/a.png)");
789
+ });
790
+ });
791
+
792
+ describe("what is not content", () => {
793
+ it("drops scripts, styles, buttons, icons, frames and form controls", () => {
794
+ expect(
795
+ pastedHtmlToMarkdown(
796
+ '<style>p { color: red }</style><script>var x = 1;</script><p>kept<button>Copy</button><svg><text>icon</text></svg></p><iframe src="https://x.test"></iframe><select><option>opt</option></select><textarea>draft</textarea><input type="text" value="v">',
797
+ ),
798
+ ).toBe("kept");
799
+ });
800
+
801
+ it("drops what is marked for the paste handler to ignore, or hidden", () => {
802
+ expect(
803
+ pastedHtmlToMarkdown(
804
+ '<p>a<span data-markdown-ignore="true">chrome</span><span style="display:none">hidden</span><span style="mso-hide:all">word hidden</span>b</p>',
805
+ ),
806
+ ).toBe("ab");
807
+ });
808
+
809
+ it("keeps headings, quotes, rules and tables", () => {
810
+ expect(
811
+ pastedHtmlToMarkdown(
812
+ "<h2>Status</h2><blockquote><p>Quoted</p></blockquote><hr><table><tr><td>Host</td><td>State</td></tr><tr><td>db-1</td><td>down</td></tr></table>",
813
+ ),
814
+ ).toBe(
815
+ "## Status\n\n> Quoted\n\n---\n\n| Host | State |\n| ---- | ----- |\n| db-1 | down |",
816
+ );
817
+ });
818
+ });
819
+
820
+ /*
821
+ * The clipboard's HTML comes from anywhere. It is parsed with DOMParser,
822
+ * whose document is inert, and never assigned to innerHTML -- in Chromium
823
+ * an <img onerror> set through a detached element's innerHTML runs.
824
+ */
825
+ describe("hostile HTML", () => {
826
+ afterEach(() => {
827
+ jest.restoreAllMocks();
828
+ delete (window as unknown as { __pasteRan?: number }).__pasteRan;
829
+ });
830
+
831
+ const HOSTILE: Array<string> = [
832
+ '<img src="x" onerror="window.__pasteRan=1">',
833
+ '<svg onload="window.__pasteRan=2"><circle r="1"></circle></svg>',
834
+ "<script>window.__pasteRan=3</script>",
835
+ '<body onload="window.__pasteRan=4"><p>body</p></body>',
836
+ '<iframe srcdoc="<script>parent.__pasteRan=5</script>"></iframe>',
837
+ '<a href="javascript:window.__pasteRan=6">link</a>',
838
+ '<details open ontoggle="window.__pasteRan=7"><summary>s</summary></details>',
839
+ '<math><mtext><table><mglyph><style><img src=x onerror="window.__pasteRan=8"></style></mglyph></table></mtext></math>',
840
+ ];
841
+
842
+ it("runs nothing and lets no markup through", async () => {
843
+ const markdown: string = pastedHtmlToMarkdown(HOSTILE.join("<p>ok</p>"));
844
+
845
+ // Give a handler that was queued the chance to run.
846
+ await new Promise((resolve: (value: unknown) => void) => {
847
+ setTimeout(resolve, 20);
848
+ });
849
+ expect((window as unknown as { __pasteRan?: number }).__pasteRan).toBe(
850
+ undefined,
851
+ );
852
+ expect(markdown).not.toMatch(/<[a-z!/]/i);
853
+ expect(markdown).not.toMatch(/on(error|load|toggle)|javascript|pasteRan/);
854
+ });
855
+
856
+ it("never assigns clipboard HTML to innerHTML", () => {
857
+ const setter: SpyInstance<(value: string) => void> = jest.spyOn(
858
+ Element.prototype,
859
+ "innerHTML",
860
+ "set",
861
+ );
862
+
863
+ pastedHtmlToMarkdown(HOSTILE.join(""));
864
+ isRichClipboardHtml(HOSTILE.join(""));
865
+ clipboardToMarkdown(clipboard({ "text/html": HOSTILE.join("") }));
866
+
867
+ expect(setter).not.toHaveBeenCalled();
868
+ });
869
+
870
+ it("returns an empty string for empty HTML", () => {
871
+ expect(pastedHtmlToMarkdown("")).toBe("");
872
+ });
873
+ });
874
+ });
875
+
876
+ describe("isRichClipboardHtml", () => {
877
+ const rich: Array<string> = [
878
+ "<ul><li>a</li></ul>",
879
+ "<ol><li>a</li></ol>",
880
+ "<h2>Title</h2>",
881
+ '<p>see <a href="https://x.test">x</a></p>',
882
+ "<p><strong>bold</strong></p>",
883
+ "<p><em>it</em></p>",
884
+ "<p><s>gone</s></p>",
885
+ "<table><tr><td>a</td></tr></table>",
886
+ "<pre><code>x</code></pre>",
887
+ "<p><code>x</code></p>",
888
+ '<img src="https://i.test/a.png">',
889
+ "<blockquote><p>q</p></blockquote>",
890
+ '<p style="mso-list:l0 level1 lfo1"><span style="mso-list:Ignore">·</span>Word item</p>',
891
+ '<span style="font-weight:700">docs bold</span>',
892
+ '<p>At <time datetime="2026-04-20T11:21:00.000Z">Apr 20</time></p>',
893
+ ];
894
+ for (const html of rich) {
895
+ it(`converts ${html}`, () => {
896
+ expect(isRichClipboardHtml(html)).toBe(true);
897
+ });
898
+ }
899
+
900
+ const plain: Array<string> = [
901
+ "",
902
+ "<p>hello</p>",
903
+ "<p>one</p><p>two<br>three</p>",
904
+ '<p style="font-weight: 400; white-space: normal;">Chrome copy of plain text</p>',
905
+ '<a name="_Toc1">bookmark only</a>',
906
+ '<p><a href="javascript:alert(1)">unsafe link</a></p>',
907
+ '<img src="data:image/png;base64,AAAA">',
908
+ ];
909
+ for (const html of plain) {
910
+ it(`leaves ${JSON.stringify(html)} to its plain text`, () => {
911
+ expect(isRichClipboardHtml(html)).toBe(false);
912
+ });
913
+ }
914
+
915
+ // An icon-only link is not a link once its icon is gone.
916
+ it("leaves a paragraph whose only link is an icon to its plain text", () => {
917
+ expect(
918
+ isRichClipboardHtml(
919
+ '<p>see <a href="https://x.test"><svg></svg></a> here</p>',
920
+ ),
921
+ ).toBe(false);
922
+ });
923
+
924
+ /*
925
+ * VS Code (and other code editors) put coloured spans in a
926
+ * white-space:pre <div> on the clipboard -- bold ones too, for keywords.
927
+ * The plain text is the content, often markdown source itself.
928
+ */
929
+ it("leaves a code editor's copy to its plain text", () => {
930
+ expect(
931
+ isRichClipboardHtml(
932
+ '<meta charset="utf-8"><div style="color: #cccccc;background-color: #1f1f1f;font-family: Menlo, monospace;font-weight: normal;font-size: 12px;line-height: 18px;white-space: pre;"><div><span style="color: #569cd6;font-weight: bold;"># Heading</span></div><div><span style="color: #cccccc;">- </span><span style="color: #ce9178;">item</span></div></div>',
933
+ ),
934
+ ).toBe(false);
935
+ });
936
+
937
+ /*
938
+ * A code view drawn as a table -- a row per line, as the Dashboard's
939
+ * Kubernetes YAML tab and exception stack frames are -- copied in Chromium
940
+ * or Safari, which write the cells' white-space:pre on each of them.
941
+ */
942
+ it("leaves lines copied out of a code view drawn as a table to their plain text", () => {
943
+ expect(isRichClipboardHtml(CHROME_CODE_VIEW_TABLE_COPY_HTML)).toBe(false);
944
+ expect(isRichClipboardHtml(WEBKIT_CODE_VIEW_TABLE_COPY_HTML)).toBe(false);
945
+ expect(
946
+ isRichClipboardHtml(
947
+ '<table><tbody><tr><th style="white-space: pre;"> key: value</th></tr></tbody></table>',
948
+ ),
949
+ ).toBe(false);
950
+ });
951
+
952
+ // A table of prose keeps its rows and columns.
953
+ it("still takes a table whose cells wrap their text as a table", () => {
954
+ expect(
955
+ isRichClipboardHtml(
956
+ '<table><tbody><tr><td style="white-space: normal;">Region</td><td>Status</td></tr><tr><td>EU</td><td>Down</td></tr></tbody></table>',
957
+ ),
958
+ ).toBe(true);
959
+ });
960
+ });
961
+
962
+ describe("clipboardToMarkdown", () => {
963
+ it("prefers rich HTML over the plain text beside it", () => {
964
+ expect(
965
+ clipboardToMarkdown(
966
+ clipboard({
967
+ "text/html": "<ul><li>a<ul><li>b</li></ul></li></ul>",
968
+ "text/plain": "a\nb",
969
+ }),
970
+ ),
971
+ ).toBe("- a\n - b");
972
+ });
973
+
974
+ it("takes the plain text, bullets made markdown, when the HTML is plain", () => {
975
+ expect(
976
+ clipboardToMarkdown(
977
+ clipboard({
978
+ "text/html": "<p>•\tService down<br>o\tUsers</p>",
979
+ "text/plain": "•\tService down\no\tUsers",
980
+ }),
981
+ ),
982
+ ).toBe("- Service down\n - Users");
983
+ });
984
+
985
+ /*
986
+ * A textarea holds "\n" line breaks. The editor's source mode compares
987
+ * this result with the clipboard's plain text to decide whether the
988
+ * browser's own paste would insert the same thing; Windows' "\r\n" made
989
+ * every multi-line paste look different, and took it off the undo stack.
990
+ */
991
+ it("writes line breaks as a textarea holds them", () => {
992
+ expect(
993
+ clipboardToMarkdown(clipboard({ "text/plain": "one\r\ntwo\rthree" })),
994
+ ).toBe("one\ntwo\nthree");
995
+ });
996
+
997
+ /*
998
+ * Words copied out of a line keep their space: as HTML it sits at the
999
+ * edge of the document and is trimmed, and "very" pasted before "world"
1000
+ * came out as "**very**world".
1001
+ */
1002
+ it("keeps the space at either edge of a one-line rich paste", () => {
1003
+ expect(
1004
+ clipboardToMarkdown(
1005
+ clipboard({ "text/html": "<b>very</b> ", "text/plain": "very " }),
1006
+ ),
1007
+ ).toBe("**very** ");
1008
+ expect(
1009
+ clipboardToMarkdown(
1010
+ clipboard({ "text/html": " <i>so</i>", "text/plain": "\tso" }),
1011
+ ),
1012
+ ).toBe(" *so*");
1013
+ });
1014
+
1015
+ it("adds no edge spaces to a paste of several lines, or for a trailing newline", () => {
1016
+ expect(
1017
+ clipboardToMarkdown(
1018
+ clipboard({
1019
+ "text/html": "<ul><li>a</li><li>b</li></ul>",
1020
+ "text/plain": " a\nb ",
1021
+ }),
1022
+ ),
1023
+ ).toBe("- a\n- b");
1024
+ expect(
1025
+ clipboardToMarkdown(
1026
+ clipboard({ "text/html": "<b>line</b>", "text/plain": "line\n" }),
1027
+ ),
1028
+ ).toBe("**line**");
1029
+ });
1030
+
1031
+ it("takes plain text alone", () => {
1032
+ expect(clipboardToMarkdown(clipboard({ "text/plain": "just text" }))).toBe(
1033
+ "just text",
1034
+ );
1035
+ });
1036
+
1037
+ it("returns null when there is nothing to paste as text", () => {
1038
+ expect(clipboardToMarkdown(clipboard({}))).toBeNull();
1039
+ expect(clipboardToMarkdown(clipboard({ "text/html": "" }))).toBeNull();
1040
+ });
1041
+
1042
+ /*
1043
+ * "Copy image" in a browser puts the image's <img> tag on the clipboard
1044
+ * beside the picture itself. Uploading the picture beats linking to
1045
+ * somebody else's server.
1046
+ */
1047
+ it("leaves an image-only paste to the image files beside it", () => {
1048
+ const data: { [format: string]: string } = {
1049
+ "text/html": '<img src="https://i.test/a.png">',
1050
+ };
1051
+
1052
+ expect(
1053
+ clipboardToMarkdown(clipboard(data, ["text/html", "Files"])),
1054
+ ).toBeNull();
1055
+ expect(
1056
+ clipboardToMarkdown(clipboard(data), { hasImageFiles: true }),
1057
+ ).toBeNull();
1058
+ expect(clipboardToMarkdown(clipboard(data), { hasImageFiles: false })).toBe(
1059
+ "![](https://i.test/a.png)",
1060
+ );
1061
+ });
1062
+
1063
+ /*
1064
+ * Word and Excel put a picture of the copied text on the clipboard as
1065
+ * well as the text itself. The text is what was meant.
1066
+ */
1067
+ it("keeps rich text even when image files come with it", () => {
1068
+ expect(
1069
+ clipboardToMarkdown(
1070
+ clipboard({ "text/html": "<ul><li>a</li></ul>", "text/plain": "a" }, [
1071
+ "text/html",
1072
+ "text/plain",
1073
+ "Files",
1074
+ ]),
1075
+ ),
1076
+ ).toBe("- a");
1077
+ });
1078
+
1079
+ // A file copied in Finder or Explorer comes with its name as plain text.
1080
+ it("leaves plain text that comes with files to the files", () => {
1081
+ expect(
1082
+ clipboardToMarkdown(
1083
+ clipboard({ "text/plain": "Screenshot.png" }, ["text/plain", "Files"]),
1084
+ ),
1085
+ ).toBeNull();
1086
+ expect(
1087
+ clipboardToMarkdown(clipboard({ "text/plain": "Screenshot.png" }), {
1088
+ hasImageFiles: false,
1089
+ }),
1090
+ ).toBe("Screenshot.png");
1091
+ });
1092
+
1093
+ it("reads a DOMStringList-like list of types", () => {
1094
+ const types: ReadonlyArray<string> = {
1095
+ length: 2,
1096
+ 0: "text/plain",
1097
+ 1: "Files",
1098
+ } as unknown as ReadonlyArray<string>;
1099
+
1100
+ expect(
1101
+ clipboardToMarkdown({
1102
+ getData: (): string => {
1103
+ return "name.png";
1104
+ },
1105
+ types,
1106
+ }),
1107
+ ).toBeNull();
1108
+ });
1109
+
1110
+ it("treats a format the browser refuses to read as empty", () => {
1111
+ expect(
1112
+ clipboardToMarkdown({
1113
+ getData: (format: string): string => {
1114
+ if (format === "text/html") {
1115
+ throw new Error("not allowed");
1116
+ }
1117
+ return "plain";
1118
+ },
1119
+ }),
1120
+ ).toBe("plain");
1121
+ });
1122
+
1123
+ it("uses the text of plain HTML when there is no plain text", () => {
1124
+ expect(
1125
+ clipboardToMarkdown(clipboard({ "text/html": "<p>only html</p>" })),
1126
+ ).toBe("only html");
1127
+ });
1128
+
1129
+ it("gives a code editor's copy as its plain text", () => {
1130
+ expect(
1131
+ clipboardToMarkdown(
1132
+ clipboard({
1133
+ "text/html":
1134
+ '<div style="white-space: pre;"><div><span style="font-weight: bold;"># Heading</span></div></div>',
1135
+ "text/plain": "# Heading",
1136
+ }),
1137
+ ),
1138
+ ).toBe("# Heading");
1139
+ });
1140
+
1141
+ /*
1142
+ * Taken as rich HTML, the four YAML lines became a one-column table: the
1143
+ * first line its header, the others' indentation gone -- the nesting that
1144
+ * is the YAML's meaning.
1145
+ */
1146
+ it("gives lines copied out of a code view drawn as a table as their plain text", () => {
1147
+ for (const html of [
1148
+ CHROME_CODE_VIEW_TABLE_COPY_HTML,
1149
+ WEBKIT_CODE_VIEW_TABLE_COPY_HTML,
1150
+ ]) {
1151
+ expect(
1152
+ clipboardToMarkdown(
1153
+ clipboard({
1154
+ "text/html": html,
1155
+ "text/plain": CODE_VIEW_TABLE_COPY_TEXT,
1156
+ }),
1157
+ ),
1158
+ ).toBe("metadata:\n name: api\n labels:\n app: api");
1159
+ }
1160
+ });
1161
+
1162
+ it("turns both real viewer copies back into the note's markdown", () => {
1163
+ expect(
1164
+ clipboardToMarkdown(
1165
+ clipboard({
1166
+ "text/html": CHROME_VIEWER_COPY_HTML,
1167
+ "text/plain": CHROME_VIEWER_COPY_TEXT,
1168
+ }),
1169
+ ),
1170
+ ).toBe(VIEWER_COPY_SOURCE_MARKDOWN);
1171
+ expect(
1172
+ clipboardToMarkdown(
1173
+ clipboard({
1174
+ "text/html": FIREFOX_VIEWER_COPY_HTML,
1175
+ "text/plain": FIREFOX_VIEWER_COPY_TEXT,
1176
+ }),
1177
+ ),
1178
+ ).toBe(VIEWER_COPY_SOURCE_MARKDOWN);
1179
+ });
1180
+ });