@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,1513 @@
1
+ import { escapeMarkdownInline } from "./MarkdownEscape";
2
+ import { Lexer, Token, Tokens } from "marked";
3
+
4
+ /*
5
+ * MARKDOWN WRITTEN BY SOMEBODY OUTSIDE - an incident form's reporter, who
6
+ * needs no account, only the form's link - made safe to store as an
7
+ * incident's own text.
8
+ *
9
+ * Nobody reads such text over before it is posted: the incident's title and
10
+ * description go straight into its "Incident Created" feed item, which is
11
+ * posted to the project's Slack and Microsoft Teams channels, and the
12
+ * description and Markdown custom field answers are rendered for every
13
+ * responder who opens the incident (the dashboard renders incident text
14
+ * without the viewer's safe mode) and in the owners' and on-call emails.
15
+ * Three things in it act on their own there, before anybody decides to
16
+ * click anything:
17
+ *
18
+ * - CHAT CONTROL SEQUENCES. Slack reads <!channel>, <!here>, <!everyone>,
19
+ * <!subteam^ID>, <@U123> and <#C123> in a bot's message as mentions, so
20
+ * a stranger could make OneUptime's bot notify a whole channel.
21
+ * neutralizeChatControlSequences puts an invisible word joiner (U+2060)
22
+ * between the "<" and the "!", "@" or "#": the text reads as typed, but
23
+ * is no longer a sequence Slack (or slackify, which then escapes the
24
+ * lone "<") recognises. It is applied everywhere in the text, code
25
+ * included: slackify passes code through untouched, so a mention inside
26
+ * a code span would reach Slack as it is. Only what Slack acts on is
27
+ * broken - "<!" and a word, "<@" or "<#" and an id - so an HTML comment
28
+ * (<!--), CDATA, a <!DOCTYPE html> or a PowerShell "<# ... #>" pasted
29
+ * into a report is stored exactly as typed.
30
+ *
31
+ * - IMAGES. ![alt](https://tracker.example/p.png) is fetched from the
32
+ * outsider's server by every responder's browser and mail client that
33
+ * shows the incident: a zero-click beacon of who looked, when, and from
34
+ * where. Each image becomes a plain link to the same address, so nothing
35
+ * is fetched until somebody chooses to follow it: the "!" is escaped,
36
+ * which is the one change that turns an image into a link without
37
+ * rewriting anything else, and an image with no alt text is given its
38
+ * address as the link's text, so the link is not an empty, invisible
39
+ * one. Reference-style images (![alt][ref], ![ref]) are covered: they
40
+ * start with the same "![".
41
+ *
42
+ * - MERMAID DIAGRAMS. A ```mermaid fence is rendered as a diagram, which
43
+ * runs mermaid's renderer (and can load images) in the responder's
44
+ * browser. Its language becomes "text", so it shows as the code the
45
+ * reporter typed.
46
+ *
47
+ * WHAT MAKES IT SAFE DOES NOT DEPEND ON HOW ANY ONE RENDERER READS THE TEXT.
48
+ * The same text is read by marked (the emails), by remark with its GitHub
49
+ * extensions, footnotes included (the dashboard), and by slackify, and they
50
+ * do not agree on everything. "[a]: https://a.example" followed by an
51
+ * indented "![x](...)" line, or a footnote's indented paragraph, is an
52
+ * indented code block to marked and a paragraph - with a live image - to
53
+ * the dashboard; a footnote definition is no more than a link definition to
54
+ * marked. So the guarantee is made on the characters, where every renderer
55
+ * agrees:
56
+ *
57
+ * - Nothing is an image unless it starts with "![" (an entity is only
58
+ * text, and raw HTML is shown as text in the dashboard and escaped in
59
+ * the emails). Every "![" whose "!" is not already escaped, and which
60
+ * something after it could complete - a "](" or "][" before its
61
+ * paragraph can end at a blank line, or, anywhere in the text, a line
62
+ * that could define a link reference ("[label]:" after nothing but
63
+ * indentation, block quote and list markers, a task list item's box or
64
+ * a footnote's label) - is broken:
65
+ * a backslash goes before the "!", or an invisible word joiner between
66
+ * the "!" and the "[". Either way no renderer finds an image there.
67
+ * The one exception is fenced code that every renderer reads as such
68
+ * (see findTrustedCode): no renderer finds an image in it, so it is
69
+ * left byte for byte.
70
+ * - The dashboard draws a diagram only for a fenced code block whose
71
+ * language is "mermaid" - and CommonMark decodes character references
72
+ * in a fence's info string, so ```&#109;ermaid is one too. After the
73
+ * first fence run of every line, every "mermaid" in the info string as
74
+ * the dashboard decodes it is broken: a real fence's language is
75
+ * renamed "text", and any other "mermaid" gets a word joiner before it,
76
+ * so no language reads "mermaid" and no class reads "language-mermaid".
77
+ *
78
+ * A real Markdown lexer (marked) only decides which of those the text gets,
79
+ * so that it still reads as typed: an image it finds gets the backslash (and
80
+ * its address as link text when it had no alt text); a "![" inside what it
81
+ * reads as a code span, a code block or raw HTML - where a backslash would
82
+ * show - gets the invisible joiner; any other "![" gets the backslash, which
83
+ * every renderer turns back into the "!" as typed, in a link's address too.
84
+ * A mermaid fence it finds is renamed; any other "mermaid" after a fence run
85
+ * gets the joiner. The joiner cannot be seen, but it is a character: a copy
86
+ * of the text keeps it. Code with no image syntax that could be completed -
87
+ * "Wow![sic]", Rust's vec![1, 2] in a paragraph of its own, anything inside
88
+ * a fenced block every renderer reads as code - is left byte for byte.
89
+ *
90
+ * The lexer does not say where in the text a token came from, so every place
91
+ * to change is first tagged with a numbered marker the lexer passes through
92
+ * untouched (private use characters, inert to Markdown); a marker that ends
93
+ * up right before an image token, inside a code span, a code block or HTML,
94
+ * or at the start of a code block's language, says what that place is.
95
+ *
96
+ * THE LEXER ONLY READS SHORT TEXT. marked takes time that grows with the
97
+ * square of the text on some shapes - emphasis next to image syntax, a long
98
+ * run of unclosed emphasis - and a description may be 20000 characters of
99
+ * them: seconds of one process's CPU, from anyone holding a form's link.
100
+ * Everything else here is linear, and the lexer is used only for a text of
101
+ * at most LEXED_TEXT_MAX_LENGTH characters. A longer one, or one the lexer
102
+ * fails on, is decided without it (findWithoutLexing): a "![" on an
103
+ * indented line or inside a code span of its own line gets the joiner, any
104
+ * other the backslash - and an image with no alt text still gets its
105
+ * address as link text when its address can be read on its line - while
106
+ * only a fence every renderer reads as one is renamed "text"; every other
107
+ * "mermaid" gets the joiner. Just as safe, and a little less tidy where a
108
+ * backslash lands in code.
109
+ *
110
+ * Links are left alone: a reporter linking the page that is broken is the
111
+ * point of a report, and a link does nothing until somebody clicks it.
112
+ *
113
+ * Pure, with no database or React imports.
114
+ */
115
+
116
+ const WORD_JOINER: string = "\u2060";
117
+
118
+ /*
119
+ * Where a chat control sequence starts, as Slack reads one: "<!" and a word
120
+ * (<!here>, <!channel>, <!everyone>, <!subteam^ID>, <!date^...>), "<@" and
121
+ * a user id, "<#" and a channel id. Not an HTML comment (<!--), CDATA
122
+ * (<![CDATA[), or a document type or other SGML declaration (<!DOCTYPE
123
+ * html>, <!ENTITY ...>): none of them is a Slack sequence, and a reporter
124
+ * pastes them in HTML. Nor a PowerShell block comment, "<#" and a space.
125
+ */
126
+ const CHAT_CONTROL_SEQUENCE_START_PATTERN: RegExp =
127
+ /<(?=[@#][a-z0-9]|!(?![-[]|(?:doctype|entity|element|attlist|notation)(?![a-z0-9])))/gi;
128
+
129
+ export type NeutralizeChatControlSequencesFunction = (
130
+ value: string | undefined | null,
131
+ ) => string;
132
+
133
+ /**
134
+ * The text as typed, with every "<!", "<@" and "<#" that Slack could read
135
+ * as a mention broken by an invisible word joiner, so no chat tool reads a
136
+ * mention in it. Idempotent: a joiner already there is not doubled.
137
+ */
138
+ export const neutralizeChatControlSequences: NeutralizeChatControlSequencesFunction =
139
+ (value: string | undefined | null): string => {
140
+ if (value === undefined || value === null) {
141
+ return "";
142
+ }
143
+
144
+ return String(value).replace(
145
+ CHAT_CONTROL_SEQUENCE_START_PATTERN,
146
+ `<${WORD_JOINER}`,
147
+ );
148
+ };
149
+
150
+ /*
151
+ * Private use characters, which nobody types and Markdown treats as plain
152
+ * text: MARKER_START, a number and MARKER_END tag one place in the probe.
153
+ * A marker only steers which change a place gets, never whether it gets
154
+ * one, so a reporter who does type these characters decides nothing.
155
+ */
156
+ const MARKER_START: string = "\uE000";
157
+ const MARKER_END: string = "\uE001";
158
+ const MARKER_PATTERN: RegExp = /\uE000(\d+)\uE001/g;
159
+ const MARKER_AT_END_PATTERN: RegExp = /\uE000(\d+)\uE001$/;
160
+ const MARKER_AT_START_PATTERN: RegExp = /^\uE000(\d+)\uE001/;
161
+
162
+ /*
163
+ * The longest text the lexer is given (see "THE LEXER ONLY READS SHORT
164
+ * TEXT" above). The worst shapes found take about 20 milliseconds at this
165
+ * length, four times that at twice it, and seconds at the 20000 characters
166
+ * a description may have.
167
+ */
168
+ export const LEXED_TEXT_MAX_LENGTH: number = 1000;
169
+
170
+ /*
171
+ * A fence run: three or more backticks or tildes. The first one in a line
172
+ * is where a fenced code block's info string could begin, whatever comes
173
+ * before it - a block quote or a list item's marker, indentation, or text
174
+ * no renderer reads as a fence at all (which is only broken for nothing).
175
+ */
176
+ const FENCE_RUN_PATTERN: RegExp = /`{3,}|~{3,}/;
177
+
178
+ // A fence run at the very start of a line, and the info string after it.
179
+ const OPENING_FENCE_PATTERN: RegExp = /^(?:(`{3,})[^`]*|(~{3,}).*)$/;
180
+
181
+ // The spaces or tabs between a fence run and its info string.
182
+ const FENCE_INFO_INDENT_PATTERN: RegExp = /^[ \t]*/;
183
+
184
+ /*
185
+ * Raw HTML that starts a block which blank lines do not end (CommonMark's
186
+ * HTML blocks 1 to 5: <script>, <pre>, <style> and <textarea>, comments,
187
+ * processing instructions, declarations and CDATA) - anywhere in a line, to
188
+ * be sure of catching every one.
189
+ */
190
+ const RAW_HTML_BLOCK_START_PATTERN: RegExp =
191
+ /<(?:[!?]|script|pre|style|textarea)/i;
192
+
193
+ const BLANK_LINE_TEXT_PATTERN: RegExp = /^[ \t]*$/;
194
+
195
+ // What marked allows after a closing fence's run: backticks, tildes, spaces.
196
+ const MARKED_CLOSING_FENCE_REST_PATTERN: RegExp = /^[~`]* *$/;
197
+
198
+ const MERMAID: string = "mermaid";
199
+ const DEMOTED_LANGUAGE: string = "text";
200
+
201
+ /*
202
+ * A numeric character reference - decimal or hexadecimal - as CommonMark
203
+ * decodes one in a fence's info string: ```&#109;ermaid is a mermaid fence
204
+ * to the dashboard. More digits are allowed than CommonMark allows, so a
205
+ * reference no renderer decodes can only be broken for nothing. Nothing
206
+ * else needs decoding to find every "mermaid": a named reference never
207
+ * stands for a letter of the English alphabet, and a backslash escape only
208
+ * ever stands for punctuation (reading "\&#109;" as a reference anyway only
209
+ * breaks what was never a diagram).
210
+ */
211
+ const NUMERIC_CHARACTER_REFERENCE_PATTERN: RegExp =
212
+ /^&#(?:[xX]([0-9a-fA-F]{1,32})|([0-9]{1,32}));/;
213
+ const NUMERIC_CHARACTER_REFERENCE_MAX_LENGTH: number = 36;
214
+ const REPLACEMENT_CHARACTER: string = "\uFFFD";
215
+
216
+ /*
217
+ * What can complete an image after its "![": a closing bracket followed by
218
+ * an address, "](", or by a reference label, "][" - with spaces or tabs
219
+ * allowed between, although no renderer here allows them. None can reach
220
+ * past a blank line, where every paragraph ends; and a link reference
221
+ * definition anywhere in the text could complete any "![label]".
222
+ */
223
+ const IMAGE_COMPLETION_PATTERN: RegExp = /\][ \t]*[([]/g;
224
+ const BLANK_LINE_PATTERN: RegExp = /\n[ \t]*(?=\n|$)/g;
225
+
226
+ /*
227
+ * What may come before a link reference definition's "[" on its line:
228
+ * indentation; the markers of block quotes and list items; a task list
229
+ * item's box, which marked takes off "- [ ] [a]: https://..." before it
230
+ * reads the rest as the item's own blocks; footnote definitions (a
231
+ * footnote's content, "[^1]: [a]: https://...", may itself start with
232
+ * one); and a byte order mark, which the dashboard's parser skips at the
233
+ * start of the text. A "]:" anywhere else - a Python slice, a TypeScript
234
+ * index signature after code, "sshd[1]:" in a log - defines nothing.
235
+ */
236
+ const REFERENCE_DEFINITION_PREFIX_PATTERN: RegExp =
237
+ /^(?:[ \t>*+\-.)0-9\uFEFF]|\[[^\]\n]\][ \t]*|\[\^[^\]\n]*\]:)*/;
238
+
239
+ // An image link's text, when the image had no alt text: its address.
240
+ const IMAGE_LINK_LABEL_MAX_LENGTH: number = 80;
241
+ const IMAGE_LINK_FALLBACK_LABEL: string = "image";
242
+
243
+ /*
244
+ * How far past "![](" the address of an image with no alt text is looked
245
+ * for when the lexer does not read the text: an address this long is
246
+ * rare, and the link then simply keeps the text it had.
247
+ */
248
+ const IMAGE_ADDRESS_SCAN_MAX_LENGTH: number = 2048;
249
+
250
+ // A backslash before ASCII punctuation, which marked drops from an address.
251
+ const ESCAPED_PUNCTUATION_PATTERN: RegExp = /\\([!-/:-@[-`{-~])/g;
252
+
253
+ // A line that could be an indented code block's.
254
+ const INDENTED_LINE_PATTERN: RegExp = /^(?: {4}|\t)/;
255
+
256
+ const BACKTICK_RUN_PATTERN: RegExp = /`+/g;
257
+
258
+ const IMAGE_OPENER_PATTERN: RegExp = /!(?=\[)/g;
259
+
260
+ // A "]" that a link, a reference or a link definition goes on from.
261
+ const LINK_TAIL_OPENER_PATTERN: RegExp = /\](?=[([:])/g;
262
+
263
+ enum CandidateKind {
264
+ Image = "image",
265
+ Mermaid = "mermaid",
266
+ }
267
+
268
+ /*
269
+ * The info string after the first fence run of a line, when "mermaid" is in
270
+ * it as the dashboard decodes it.
271
+ */
272
+ interface DiagramInfoString {
273
+ // Where it starts: after the fence run and any spaces or tabs.
274
+ start: number;
275
+ // Where its first word - the language - ends.
276
+ languageEnd: number;
277
+ // Where each "mermaid" in it starts, a reference counting from its "&".
278
+ mermaidWords: Array<number>;
279
+ }
280
+
281
+ interface Candidate {
282
+ kind: CandidateKind;
283
+ /*
284
+ * In the line-ending normalised text: where the "![" starts, or where
285
+ * the info string of a diagram candidate starts.
286
+ */
287
+ position: number;
288
+ info?: DiagramInfoString | undefined;
289
+ }
290
+
291
+ interface Edit {
292
+ position: number;
293
+ deleteCount: number;
294
+ insert: string;
295
+ }
296
+
297
+ /*
298
+ * The fenced code that every renderer reads as fenced code (see
299
+ * findTrustedCode).
300
+ */
301
+ interface TrustedCode {
302
+ // Each run of its lines, as [start, end) offsets, in order.
303
+ ranges: Array<[number, number]>;
304
+ // Where the info string of each such fence's opening line starts.
305
+ openingInfoStarts: Set<number>;
306
+ }
307
+
308
+ interface Line {
309
+ start: number;
310
+ // Where it ends, before its "\n".
311
+ end: number;
312
+ }
313
+
314
+ type SplitLinesFunction = (source: string) => Array<Line>;
315
+
316
+ const splitLines: SplitLinesFunction = (source: string): Array<Line> => {
317
+ const lines: Array<Line> = [];
318
+ let start: number = 0;
319
+
320
+ for (;;) {
321
+ const newline: number = source.indexOf("\n", start);
322
+
323
+ if (newline === -1) {
324
+ lines.push({ start: start, end: source.length });
325
+ return lines;
326
+ }
327
+
328
+ lines.push({ start: start, end: newline });
329
+ start = newline + 1;
330
+ }
331
+ };
332
+
333
+ type IsEscapedFunction = (source: string, position: number) => boolean;
334
+
335
+ // Whether an odd number of backslashes comes right before this character.
336
+ const isEscaped: IsEscapedFunction = (
337
+ source: string,
338
+ position: number,
339
+ ): boolean => {
340
+ let backslashes: number = 0;
341
+
342
+ while (
343
+ position - backslashes - 1 >= 0 &&
344
+ source[position - backslashes - 1] === "\\"
345
+ ) {
346
+ backslashes++;
347
+ }
348
+
349
+ return backslashes % 2 !== 0;
350
+ };
351
+
352
+ type IsInTrustedCodeFunction = (code: TrustedCode, position: number) => boolean;
353
+
354
+ const isInTrustedCode: IsInTrustedCodeFunction = (
355
+ code: TrustedCode,
356
+ position: number,
357
+ ): boolean => {
358
+ let low: number = 0;
359
+ let high: number = code.ranges.length - 1;
360
+
361
+ while (low <= high) {
362
+ const middle: number = (low + high) >> 1;
363
+ const range: [number, number] = code.ranges[middle]!;
364
+
365
+ if (position < range[0]) {
366
+ high = middle - 1;
367
+ } else if (position >= range[1]) {
368
+ low = middle + 1;
369
+ } else {
370
+ return true;
371
+ }
372
+ }
373
+
374
+ return false;
375
+ };
376
+
377
+ type ReadClosingFenceFunction = (
378
+ line: string,
379
+ run: string,
380
+ ) => { byCommonMark: boolean; byMarked: boolean };
381
+
382
+ /*
383
+ * Whether a line closes a fence opened with this run, as CommonMark reads it
384
+ * (up to three spaces, at least as long a run of the same character, then
385
+ * only spaces or tabs) and as marked does (up to three spaces, the same run,
386
+ * then any backticks or tildes and spaces).
387
+ */
388
+ const readClosingFence: ReadClosingFenceFunction = (
389
+ line: string,
390
+ run: string,
391
+ ): { byCommonMark: boolean; byMarked: boolean } => {
392
+ let indent: number = 0;
393
+
394
+ while (indent < line.length && line[indent] === " ") {
395
+ indent++;
396
+ }
397
+
398
+ if (indent > 3) {
399
+ return { byCommonMark: false, byMarked: false };
400
+ }
401
+
402
+ let end: number = indent;
403
+
404
+ while (end < line.length && line[end] === run[0]) {
405
+ end++;
406
+ }
407
+
408
+ return {
409
+ byCommonMark:
410
+ end - indent >= run.length &&
411
+ BLANK_LINE_TEXT_PATTERN.test(line.slice(end)),
412
+ byMarked:
413
+ line.startsWith(run, indent) &&
414
+ MARKED_CLOSING_FENCE_REST_PATTERN.test(line.slice(indent + run.length)),
415
+ };
416
+ };
417
+
418
+ type FindTrustedCodeFunction = (
419
+ source: string,
420
+ lines: Array<Line>,
421
+ ) => TrustedCode;
422
+
423
+ /*
424
+ * The fenced code blocks that every renderer here reads as fenced code, and
425
+ * so as nothing but code: no image and no diagram can be in them.
426
+ *
427
+ * Trusted only as far as this can be sure of: a fence opened at the very
428
+ * start of a line (no indentation, no container) that follows a blank line,
429
+ * the start of the text or the close of another such fence. Nothing else
430
+ * can hold that line - a block quote, a list item or a footnote needs its
431
+ * marker or its indentation on it, and an HTML block of the kinds a blank
432
+ * line ends is over - except a fence or an HTML block that blank lines do
433
+ * not end. So trust stops for good at the first line outside such a fence
434
+ * that holds a fence run anywhere, or the start of such an HTML block
435
+ * anywhere, and at the first line that closes a fence for one renderer but
436
+ * not the other (marked closes "```" with "```~", CommonMark with
437
+ * "```\t"): after it, the renderers could pair the fences that follow
438
+ * differently.
439
+ */
440
+ const findTrustedCode: FindTrustedCodeFunction = (
441
+ source: string,
442
+ lines: Array<Line>,
443
+ ): TrustedCode => {
444
+ const code: TrustedCode = {
445
+ ranges: [],
446
+ openingInfoStarts: new Set<number>(),
447
+ };
448
+
449
+ let isTrusting: boolean = true;
450
+ // The line before was blank, closed a trusted fence, or there was none.
451
+ let mayOpen: boolean = true;
452
+ // The run the trusted fence the scan is in was opened with.
453
+ let openRun: string | null = null;
454
+
455
+ for (const line of lines) {
456
+ const text: string = source.slice(line.start, line.end);
457
+
458
+ if (openRun !== null) {
459
+ const closing: { byCommonMark: boolean; byMarked: boolean } =
460
+ readClosingFence(text, openRun);
461
+
462
+ if (closing.byCommonMark || closing.byMarked) {
463
+ openRun = null;
464
+ mayOpen = true;
465
+ isTrusting = closing.byCommonMark && closing.byMarked;
466
+ continue;
467
+ }
468
+
469
+ const previous: [number, number] | undefined =
470
+ code.ranges[code.ranges.length - 1];
471
+
472
+ if (previous && previous[1] + 1 === line.start) {
473
+ previous[1] = line.end;
474
+ } else {
475
+ code.ranges.push([line.start, line.end]);
476
+ }
477
+
478
+ continue;
479
+ }
480
+
481
+ const opening: RegExpExecArray | null =
482
+ isTrusting && mayOpen ? OPENING_FENCE_PATTERN.exec(text) : null;
483
+
484
+ if (opening) {
485
+ openRun = (opening[1] || opening[2])!;
486
+
487
+ code.openingInfoStarts.add(
488
+ line.start +
489
+ openRun.length +
490
+ FENCE_INFO_INDENT_PATTERN.exec(text.slice(openRun.length))![0].length,
491
+ );
492
+
493
+ continue;
494
+ }
495
+
496
+ if (
497
+ FENCE_RUN_PATTERN.test(text) ||
498
+ RAW_HTML_BLOCK_START_PATTERN.test(text)
499
+ ) {
500
+ isTrusting = false;
501
+ }
502
+
503
+ mayOpen = BLANK_LINE_TEXT_PATTERN.test(text);
504
+ }
505
+
506
+ return code;
507
+ };
508
+
509
+ type HasPossibleReferenceDefinitionFunction = (data: {
510
+ source: string;
511
+ lines: Array<Line>;
512
+ code: TrustedCode;
513
+ }) => boolean;
514
+
515
+ /*
516
+ * Whether any renderer could read a link reference definition in the text,
517
+ * which would complete any "![label]" in it however far away: a "[label]:"
518
+ * outside trusted code whose "[" has nothing but REFERENCE_DEFINITION_PREFIX
519
+ * before it on its line. Generous on purpose - it does not check what
520
+ * follows the colon, or that the line may start a block at all.
521
+ */
522
+ const hasPossibleReferenceDefinition: HasPossibleReferenceDefinitionFunction =
523
+ (data: {
524
+ source: string;
525
+ lines: Array<Line>;
526
+ code: TrustedCode;
527
+ }): boolean => {
528
+ const source: string = data.source;
529
+
530
+ /*
531
+ * The line the last "[" was on, and where what may come before a
532
+ * definition ends on it. Each "[" is after the one before (see below),
533
+ * so both only move forward.
534
+ */
535
+ let lineIndex: number = 0;
536
+ let prefixEndLine: number = -1;
537
+ let prefixEnd: number = 0;
538
+
539
+ for (
540
+ let colon: number = source.indexOf("]:");
541
+ colon !== -1;
542
+ colon = source.indexOf("]:", colon + 1)
543
+ ) {
544
+ if (isEscaped(source, colon)) {
545
+ continue;
546
+ }
547
+
548
+ /*
549
+ * The label's "[": the nearest bracket before, as a label cannot hold
550
+ * one that is not escaped. Each search stops at the "]" of the one
551
+ * before it at the latest, so together they read the text once.
552
+ */
553
+ let open: number = colon - 1;
554
+
555
+ while (
556
+ open >= 0 &&
557
+ !(
558
+ (source[open] === "[" || source[open] === "]") &&
559
+ !isEscaped(source, open)
560
+ )
561
+ ) {
562
+ open--;
563
+ }
564
+
565
+ if (
566
+ open < 0 ||
567
+ source[open] !== "[" ||
568
+ isInTrustedCode(data.code, open)
569
+ ) {
570
+ continue;
571
+ }
572
+
573
+ while (data.lines[lineIndex]!.end < open) {
574
+ lineIndex++;
575
+ }
576
+
577
+ if (prefixEndLine !== lineIndex) {
578
+ const line: Line = data.lines[lineIndex]!;
579
+
580
+ prefixEnd =
581
+ line.start +
582
+ REFERENCE_DEFINITION_PREFIX_PATTERN.exec(
583
+ source.slice(line.start, line.end),
584
+ )![0].length;
585
+ prefixEndLine = lineIndex;
586
+ }
587
+
588
+ if (open <= prefixEnd) {
589
+ return true;
590
+ }
591
+ }
592
+
593
+ return false;
594
+ };
595
+
596
+ type FindMermaidWordsFunction = (
597
+ source: string,
598
+ start: number,
599
+ end: number,
600
+ ) => Array<number>;
601
+
602
+ /*
603
+ * Where each "mermaid" in source[start, end) starts, read as the dashboard
604
+ * reads an info string - with numeric character references decoded, and
605
+ * any letter case. One right after a word joiner is already broken.
606
+ */
607
+ const findMermaidWords: FindMermaidWordsFunction = (
608
+ source: string,
609
+ start: number,
610
+ end: number,
611
+ ): Array<number> => {
612
+ // The decoded characters, and where in the source each one starts.
613
+ const characters: Array<string> = [];
614
+ const starts: Array<number> = [];
615
+
616
+ let position: number = start;
617
+
618
+ while (position < end) {
619
+ const reference: RegExpExecArray | null =
620
+ source[position] === "&"
621
+ ? NUMERIC_CHARACTER_REFERENCE_PATTERN.exec(
622
+ source.slice(
623
+ position,
624
+ Math.min(end, position + NUMERIC_CHARACTER_REFERENCE_MAX_LENGTH),
625
+ ),
626
+ )
627
+ : null;
628
+
629
+ if (reference) {
630
+ const codePoint: number = reference[1]
631
+ ? parseInt(reference[1], 16)
632
+ : parseInt(reference[2]!, 10);
633
+
634
+ characters.push(
635
+ codePoint > 0 &&
636
+ codePoint <= 0x10ffff &&
637
+ !(codePoint >= 0xd800 && codePoint <= 0xdfff)
638
+ ? String.fromCodePoint(codePoint)
639
+ : REPLACEMENT_CHARACTER,
640
+ );
641
+ starts.push(position);
642
+ position += reference[0].length;
643
+ continue;
644
+ }
645
+
646
+ characters.push(source[position]!);
647
+ starts.push(position);
648
+ position++;
649
+ }
650
+
651
+ const words: Array<number> = [];
652
+
653
+ for (let index: number = 0; index + MERMAID.length <= characters.length; ) {
654
+ let length: number = 0;
655
+
656
+ while (
657
+ length < MERMAID.length &&
658
+ characters[index + length]!.toLowerCase() === MERMAID[length]
659
+ ) {
660
+ length++;
661
+ }
662
+
663
+ if (length < MERMAID.length) {
664
+ index++;
665
+ continue;
666
+ }
667
+
668
+ if (index === 0 || characters[index - 1] !== WORD_JOINER) {
669
+ words.push(starts[index]!);
670
+ }
671
+
672
+ index += MERMAID.length;
673
+ }
674
+
675
+ return words;
676
+ };
677
+
678
+ type FindDiagramInfoStringsFunction = (
679
+ source: string,
680
+ lines: Array<Line>,
681
+ ) => Array<DiagramInfoString>;
682
+
683
+ /*
684
+ * Every info string with "mermaid" in it, as the dashboard decodes it: the
685
+ * rest of each line after its first fence run - wherever the run is, as no
686
+ * container before it is trusted to keep it from being a fence.
687
+ */
688
+ const findDiagramInfoStrings: FindDiagramInfoStringsFunction = (
689
+ source: string,
690
+ lines: Array<Line>,
691
+ ): Array<DiagramInfoString> => {
692
+ const infoStrings: Array<DiagramInfoString> = [];
693
+
694
+ for (const line of lines) {
695
+ const text: string = source.slice(line.start, line.end);
696
+ const run: RegExpExecArray | null = FENCE_RUN_PATTERN.exec(text);
697
+
698
+ if (!run) {
699
+ continue;
700
+ }
701
+
702
+ const afterRun: number = run.index + run[0].length;
703
+ const start: number =
704
+ line.start +
705
+ afterRun +
706
+ FENCE_INFO_INDENT_PATTERN.exec(text.slice(afterRun))![0].length;
707
+
708
+ const mermaidWords: Array<number> = findMermaidWords(
709
+ source,
710
+ start,
711
+ line.end,
712
+ );
713
+
714
+ if (mermaidWords.length === 0) {
715
+ continue;
716
+ }
717
+
718
+ let languageEnd: number = start;
719
+
720
+ while (
721
+ languageEnd < line.end &&
722
+ source[languageEnd] !== " " &&
723
+ source[languageEnd] !== "\t"
724
+ ) {
725
+ languageEnd++;
726
+ }
727
+
728
+ infoStrings.push({
729
+ start: start,
730
+ languageEnd: languageEnd,
731
+ mermaidWords: mermaidWords,
732
+ });
733
+ }
734
+
735
+ return infoStrings;
736
+ };
737
+
738
+ type LexFunction = (markdown: string) => Array<Token>;
739
+
740
+ /*
741
+ * The options marked's own parse uses by default (GitHub flavoured, no
742
+ * line-break extension), given afresh each time: the lexer writes into the
743
+ * options object it is handed, and must not see what another caller set up
744
+ * with marked.use().
745
+ */
746
+ const lex: LexFunction = (markdown: string): Array<Token> => {
747
+ return new Lexer({ gfm: true, breaks: false, pedantic: false }).lex(markdown);
748
+ };
749
+
750
+ type GetChildTokensFunction = (token: Token) => Array<Token>;
751
+
752
+ const getChildTokens: GetChildTokensFunction = (token: Token): Array<Token> => {
753
+ if (token.type === "list") {
754
+ return (token as Tokens.List).items;
755
+ }
756
+
757
+ if (token.type === "table") {
758
+ const table: Tokens.Table = token as Tokens.Table;
759
+ const cells: Array<Tokens.TableCell> = [...table.header];
760
+
761
+ for (const row of table.rows) {
762
+ cells.push(...row);
763
+ }
764
+
765
+ return cells.flatMap((cell: Tokens.TableCell): Array<Token> => {
766
+ return cell.tokens || [];
767
+ });
768
+ }
769
+
770
+ const nested: unknown = (token as { tokens?: unknown }).tokens;
771
+
772
+ return Array.isArray(nested) ? (nested as Array<Token>) : [];
773
+ };
774
+
775
+ type WalkTokensFunction = (
776
+ tokens: Array<Token>,
777
+ visit: (token: Token, isLeaf: boolean) => void,
778
+ ) => void;
779
+
780
+ // Every token, depth first, in the order its text appears.
781
+ const walkTokens: WalkTokensFunction = (
782
+ tokens: Array<Token>,
783
+ visit: (token: Token, isLeaf: boolean) => void,
784
+ ): void => {
785
+ for (const token of tokens) {
786
+ const children: Array<Token> = getChildTokens(token);
787
+
788
+ visit(token, children.length === 0);
789
+ walkTokens(children, visit);
790
+ }
791
+ };
792
+
793
+ type GetMatchPositionsFunction = (
794
+ source: string,
795
+ pattern: RegExp,
796
+ ) => Array<number>;
797
+
798
+ // Where each match of a global pattern starts, in order.
799
+ const getMatchPositions: GetMatchPositionsFunction = (
800
+ source: string,
801
+ pattern: RegExp,
802
+ ): Array<number> => {
803
+ const positions: Array<number> = [];
804
+
805
+ for (const match of source.matchAll(pattern)) {
806
+ positions.push(match.index || 0);
807
+ }
808
+
809
+ return positions;
810
+ };
811
+
812
+ type FindCandidatesFunction = (data: {
813
+ source: string;
814
+ lines: Array<Line>;
815
+ code: TrustedCode;
816
+ }) => Array<Candidate>;
817
+
818
+ /*
819
+ * Every place to change, in order: each "![" that could open an image - its
820
+ * "!" not escaped (an even number of backslashes before it), not in trusted
821
+ * code, and something after it that could complete one (see
822
+ * IMAGE_COMPLETION_PATTERN) - and each info string with "mermaid" in it.
823
+ */
824
+ const findCandidates: FindCandidatesFunction = (data: {
825
+ source: string;
826
+ lines: Array<Line>;
827
+ code: TrustedCode;
828
+ }): Array<Candidate> => {
829
+ const source: string = data.source;
830
+ const candidates: Array<Candidate> = [];
831
+
832
+ const mayHaveDefinition: boolean = hasPossibleReferenceDefinition(data);
833
+ const completions: Array<number> = getMatchPositions(
834
+ source,
835
+ IMAGE_COMPLETION_PATTERN,
836
+ );
837
+ const paragraphEnds: Array<number> = [
838
+ ...getMatchPositions(source, BLANK_LINE_PATTERN),
839
+ source.length,
840
+ ];
841
+
842
+ // Both only move forward, as the openers do.
843
+ let nextCompletion: number = 0;
844
+ let nextParagraphEnd: number = 0;
845
+
846
+ for (
847
+ let position: number = source.indexOf("![");
848
+ position !== -1;
849
+ position = source.indexOf("![", position + 1)
850
+ ) {
851
+ if (isEscaped(source, position) || isInTrustedCode(data.code, position)) {
852
+ continue;
853
+ }
854
+
855
+ while (
856
+ nextCompletion < completions.length &&
857
+ completions[nextCompletion]! <= position
858
+ ) {
859
+ nextCompletion++;
860
+ }
861
+
862
+ while (paragraphEnds[nextParagraphEnd]! <= position) {
863
+ nextParagraphEnd++;
864
+ }
865
+
866
+ const isCompletable: boolean =
867
+ mayHaveDefinition ||
868
+ (nextCompletion < completions.length &&
869
+ completions[nextCompletion]! < paragraphEnds[nextParagraphEnd]!);
870
+
871
+ if (isCompletable) {
872
+ candidates.push({ kind: CandidateKind.Image, position: position });
873
+ }
874
+ }
875
+
876
+ for (const info of findDiagramInfoStrings(source, data.lines)) {
877
+ candidates.push({
878
+ kind: CandidateKind.Mermaid,
879
+ position: info.start,
880
+ info: info,
881
+ });
882
+ }
883
+
884
+ /*
885
+ * A diagram candidate before an image one at the same place, so the
886
+ * lexer reads its marker first at the start of a code block's language.
887
+ */
888
+ return candidates.sort((a: Candidate, b: Candidate): number => {
889
+ return (
890
+ a.position - b.position ||
891
+ Number(a.kind === CandidateKind.Image) -
892
+ Number(b.kind === CandidateKind.Image)
893
+ );
894
+ });
895
+ };
896
+
897
+ interface FoundInText {
898
+ // By candidate index: the images found, with the address of each.
899
+ images: Map<number, string>;
900
+ // The candidates in a code span, a code block or raw HTML.
901
+ literal: Set<number>;
902
+ // The candidates that begin a code block's language.
903
+ diagrams: Set<number>;
904
+ }
905
+
906
+ type FindInProbeFunction = (
907
+ source: string,
908
+ candidates: Array<Candidate>,
909
+ ) => FoundInText;
910
+
911
+ /*
912
+ * What the lexer makes of each candidate place: the text is lexed with
913
+ * every one of them tagged by its number.
914
+ */
915
+ const findInProbe: FindInProbeFunction = (
916
+ source: string,
917
+ candidates: Array<Candidate>,
918
+ ): FoundInText => {
919
+ const parts: Array<string> = [];
920
+ let cursor: number = 0;
921
+
922
+ candidates.forEach((candidate: Candidate, index: number): void => {
923
+ parts.push(
924
+ source.slice(cursor, candidate.position),
925
+ `${MARKER_START}${index}${MARKER_END}`,
926
+ );
927
+ cursor = candidate.position;
928
+ });
929
+
930
+ parts.push(source.slice(cursor));
931
+
932
+ const found: FoundInText = {
933
+ images: new Map<number, string>(),
934
+ literal: new Set<number>(),
935
+ diagrams: new Set<number>(),
936
+ };
937
+
938
+ const markLiteral: (text: string | undefined) => void = (
939
+ text: string | undefined,
940
+ ): void => {
941
+ for (const marker of (text || "").matchAll(MARKER_PATTERN)) {
942
+ found.literal.add(Number(marker[1]));
943
+ }
944
+ };
945
+
946
+ let previousLeafRaw: string = "";
947
+
948
+ walkTokens(lex(parts.join("")), (token: Token, isLeaf: boolean): void => {
949
+ if (token.type === "image") {
950
+ /*
951
+ * The marker sits right before the "!", so it ends the text the
952
+ * lexer read just before this image.
953
+ */
954
+ const marker: RegExpExecArray | null =
955
+ MARKER_AT_END_PATTERN.exec(previousLeafRaw);
956
+
957
+ if (marker) {
958
+ found.images.set(Number(marker[1]), (token as Tokens.Image).href);
959
+ }
960
+ }
961
+
962
+ if (token.type === "code") {
963
+ const code: Tokens.Code = token as Tokens.Code;
964
+
965
+ const marker: RegExpExecArray | null = MARKER_AT_START_PATTERN.exec(
966
+ (code.lang || "").trim(),
967
+ );
968
+
969
+ if (marker) {
970
+ found.diagrams.add(Number(marker[1]));
971
+ }
972
+
973
+ // The block's content, not its info string.
974
+ markLiteral(code.text);
975
+ }
976
+
977
+ if (token.type === "codespan" || token.type === "html") {
978
+ markLiteral(token.raw);
979
+ }
980
+
981
+ if (isLeaf) {
982
+ previousLeafRaw = token.raw || "";
983
+ }
984
+ });
985
+
986
+ return found;
987
+ };
988
+
989
+ type GetLineCodeSpansFunction = (
990
+ source: string,
991
+ line: Line,
992
+ ) => Array<[number, number]>;
993
+
994
+ /*
995
+ * The code spans of one line, as [start, end) offsets: a backtick run
996
+ * opens one that the next run of the same length on the line closes, as
997
+ * CommonMark pairs them. (A span that goes on to another line is not seen.)
998
+ */
999
+ const getLineCodeSpans: GetLineCodeSpansFunction = (
1000
+ source: string,
1001
+ line: Line,
1002
+ ): Array<[number, number]> => {
1003
+ const runs: Array<RegExpMatchArray> = Array.from(
1004
+ source.slice(line.start, line.end).matchAll(BACKTICK_RUN_PATTERN),
1005
+ );
1006
+
1007
+ // For each run, the next run of the same length, found from the end.
1008
+ const nextOfSameLength: Array<number> = [];
1009
+ const lastByLength: Map<number, number> = new Map<number, number>();
1010
+
1011
+ for (let index: number = runs.length - 1; index >= 0; index--) {
1012
+ const length: number = runs[index]![0].length;
1013
+
1014
+ nextOfSameLength[index] = lastByLength.get(length) ?? -1;
1015
+ lastByLength.set(length, index);
1016
+ }
1017
+
1018
+ const spans: Array<[number, number]> = [];
1019
+
1020
+ for (let index: number = 0; index < runs.length; ) {
1021
+ const closer: number = nextOfSameLength[index]!;
1022
+
1023
+ if (closer === -1) {
1024
+ index++;
1025
+ continue;
1026
+ }
1027
+
1028
+ spans.push([
1029
+ line.start + (runs[index]!.index || 0),
1030
+ line.start + (runs[closer]!.index || 0) + runs[closer]![0].length,
1031
+ ]);
1032
+ index = closer + 1;
1033
+ }
1034
+
1035
+ return spans;
1036
+ };
1037
+
1038
+ type ReadImageAddressFunction = (
1039
+ source: string,
1040
+ start: number,
1041
+ limit: number,
1042
+ ) => string | null;
1043
+
1044
+ /*
1045
+ * The address of an image whose "![](" ends at start, read no further than
1046
+ * limit: "<...>" or a run without spaces (its parentheses balanced), then
1047
+ * an optional title, then ")". Null when that cannot be read before limit -
1048
+ * the image then simply gets no link text of its own.
1049
+ */
1050
+ const readImageAddress: ReadImageAddressFunction = (
1051
+ source: string,
1052
+ start: number,
1053
+ limit: number,
1054
+ ): string | null => {
1055
+ let position: number = start;
1056
+
1057
+ const skipSpaces: () => void = (): void => {
1058
+ while (
1059
+ position < limit &&
1060
+ (source[position] === " " || source[position] === "\t")
1061
+ ) {
1062
+ position++;
1063
+ }
1064
+ };
1065
+
1066
+ // Where the character next occurs before limit, or -1.
1067
+ const findBeforeLimit: (character: string, from: number) => number = (
1068
+ character: string,
1069
+ from: number,
1070
+ ): number => {
1071
+ for (let index: number = from; index < limit; index++) {
1072
+ if (source[index] === character) {
1073
+ return index;
1074
+ }
1075
+ }
1076
+
1077
+ return -1;
1078
+ };
1079
+
1080
+ skipSpaces();
1081
+
1082
+ let address: string;
1083
+
1084
+ if (source[position] === "<") {
1085
+ const close: number = findBeforeLimit(">", position + 1);
1086
+
1087
+ if (close === -1 || source.slice(position + 1, close).includes("<")) {
1088
+ return null;
1089
+ }
1090
+
1091
+ address = source.slice(position + 1, close);
1092
+ position = close + 1;
1093
+ } else {
1094
+ const addressStart: number = position;
1095
+ let depth: number = 0;
1096
+
1097
+ while (position < limit) {
1098
+ const character: string = source[position]!;
1099
+
1100
+ if (character === " " || character === "\t") {
1101
+ break;
1102
+ }
1103
+
1104
+ if (character === "\\") {
1105
+ position += 2;
1106
+ continue;
1107
+ }
1108
+
1109
+ if (character === "(") {
1110
+ depth++;
1111
+ } else if (character === ")") {
1112
+ if (depth === 0) {
1113
+ break;
1114
+ }
1115
+
1116
+ depth--;
1117
+ }
1118
+
1119
+ position++;
1120
+ }
1121
+
1122
+ if (depth !== 0 || position > limit) {
1123
+ return null;
1124
+ }
1125
+
1126
+ address = source.slice(addressStart, position);
1127
+ }
1128
+
1129
+ skipSpaces();
1130
+
1131
+ const opener: string | undefined = source[position];
1132
+
1133
+ if (opener === '"' || opener === "'" || opener === "(") {
1134
+ const close: number = findBeforeLimit(
1135
+ opener === "(" ? ")" : opener,
1136
+ position + 1,
1137
+ );
1138
+
1139
+ if (close === -1) {
1140
+ return null;
1141
+ }
1142
+
1143
+ position = close + 1;
1144
+ skipSpaces();
1145
+ }
1146
+
1147
+ if (position >= limit || source[position] !== ")") {
1148
+ return null;
1149
+ }
1150
+
1151
+ return address.replace(ESCAPED_PUNCTUATION_PATTERN, "$1");
1152
+ };
1153
+
1154
+ type FindWithoutLexingFunction = (data: {
1155
+ source: string;
1156
+ lines: Array<Line>;
1157
+ candidates: Array<Candidate>;
1158
+ }) => FoundInText;
1159
+
1160
+ /*
1161
+ * What each candidate place is taken to be when the lexer does not read the
1162
+ * text (see "THE LEXER ONLY READS SHORT TEXT" above), in one pass: a "!["
1163
+ * on a line indented as code, or in a code span of its own line, is code;
1164
+ * a "![](" whose address can be read on its line before the next candidate
1165
+ * is an image with that address. A diagram is decided by trusted code
1166
+ * alone (see getEdits).
1167
+ */
1168
+ const findWithoutLexing: FindWithoutLexingFunction = (data: {
1169
+ source: string;
1170
+ lines: Array<Line>;
1171
+ candidates: Array<Candidate>;
1172
+ }): FoundInText => {
1173
+ const found: FoundInText = {
1174
+ images: new Map<number, string>(),
1175
+ literal: new Set<number>(),
1176
+ diagrams: new Set<number>(),
1177
+ };
1178
+
1179
+ const images: Array<number> = [];
1180
+
1181
+ data.candidates.forEach((candidate: Candidate, index: number): void => {
1182
+ if (candidate.kind === CandidateKind.Image) {
1183
+ images.push(index);
1184
+ }
1185
+ });
1186
+
1187
+ /*
1188
+ * The line of the last candidate, its code spans, and the first of them
1189
+ * that does not end before that candidate: all only move forward, as the
1190
+ * candidates do.
1191
+ */
1192
+ let lineIndex: number = 0;
1193
+ let spansOfLine: number = -1;
1194
+ let spans: Array<[number, number]> = [];
1195
+ let spanIndex: number = 0;
1196
+
1197
+ images.forEach((index: number, order: number): void => {
1198
+ const position: number = data.candidates[index]!.position;
1199
+
1200
+ while (data.lines[lineIndex]!.end < position) {
1201
+ lineIndex++;
1202
+ }
1203
+
1204
+ const line: Line = data.lines[lineIndex]!;
1205
+
1206
+ if (spansOfLine !== lineIndex) {
1207
+ spans = getLineCodeSpans(data.source, line);
1208
+ spansOfLine = lineIndex;
1209
+ spanIndex = 0;
1210
+ }
1211
+
1212
+ while (spanIndex < spans.length && spans[spanIndex]![1] <= position) {
1213
+ spanIndex++;
1214
+ }
1215
+
1216
+ const span: [number, number] | undefined = spans[spanIndex];
1217
+
1218
+ if (
1219
+ INDENTED_LINE_PATTERN.test(data.source.slice(line.start, line.end)) ||
1220
+ (span && span[0] < position)
1221
+ ) {
1222
+ found.literal.add(index);
1223
+ return;
1224
+ }
1225
+
1226
+ if (!data.source.startsWith("![](", position)) {
1227
+ return;
1228
+ }
1229
+
1230
+ const next: Candidate | undefined =
1231
+ order + 1 < images.length
1232
+ ? data.candidates[images[order + 1]!]
1233
+ : undefined;
1234
+
1235
+ const address: string | null = readImageAddress(
1236
+ data.source,
1237
+ position + 4,
1238
+ Math.min(
1239
+ line.end,
1240
+ next ? next.position : line.end,
1241
+ position + 4 + IMAGE_ADDRESS_SCAN_MAX_LENGTH,
1242
+ ),
1243
+ );
1244
+
1245
+ if (address !== null) {
1246
+ found.images.set(index, address);
1247
+ }
1248
+ });
1249
+
1250
+ return found;
1251
+ };
1252
+
1253
+ type GetImageLinkLabelFunction = (href: string | undefined) => string;
1254
+
1255
+ /*
1256
+ * The text of the link an image without alt text becomes: its address,
1257
+ * shortened and escaped so it reads as typed, or a plain word when it has
1258
+ * none.
1259
+ */
1260
+ const getImageLinkLabel: GetImageLinkLabelFunction = (
1261
+ href: string | undefined,
1262
+ ): string => {
1263
+ const address: string = (href || "").replace(MARKER_PATTERN, "").trim();
1264
+
1265
+ if (!address) {
1266
+ return IMAGE_LINK_FALLBACK_LABEL;
1267
+ }
1268
+
1269
+ return escapeMarkdownInline(
1270
+ address.length > IMAGE_LINK_LABEL_MAX_LENGTH
1271
+ ? `${address.slice(0, IMAGE_LINK_LABEL_MAX_LENGTH)}...`
1272
+ : address,
1273
+ );
1274
+ };
1275
+
1276
+ type GetEditsFunction = (data: {
1277
+ source: string;
1278
+ candidate: Candidate;
1279
+ index: number;
1280
+ found: FoundInText;
1281
+ code: TrustedCode;
1282
+ }) => Array<Edit>;
1283
+
1284
+ // What changes one candidate place into something that does nothing.
1285
+ const getEdits: GetEditsFunction = (data: {
1286
+ source: string;
1287
+ candidate: Candidate;
1288
+ index: number;
1289
+ found: FoundInText;
1290
+ code: TrustedCode;
1291
+ }): Array<Edit> => {
1292
+ const position: number = data.candidate.position;
1293
+
1294
+ if (data.candidate.kind === CandidateKind.Mermaid) {
1295
+ const info: DiagramInfoString = data.candidate.info!;
1296
+
1297
+ /*
1298
+ * A fence the lexer found, or one every renderer reads as a fence, is
1299
+ * given the language "text" when its language holds "mermaid"; every
1300
+ * other "mermaid" is broken.
1301
+ */
1302
+ const isRenamed: boolean =
1303
+ (data.found.diagrams.has(data.index) ||
1304
+ data.code.openingInfoStarts.has(info.start)) &&
1305
+ info.mermaidWords[0]! < info.languageEnd;
1306
+
1307
+ const edits: Array<Edit> = isRenamed
1308
+ ? [
1309
+ {
1310
+ position: info.start,
1311
+ deleteCount: info.languageEnd - info.start,
1312
+ insert: DEMOTED_LANGUAGE,
1313
+ },
1314
+ ]
1315
+ : [];
1316
+
1317
+ for (const word of info.mermaidWords) {
1318
+ if (!isRenamed || word >= info.languageEnd) {
1319
+ edits.push({ position: word, deleteCount: 0, insert: WORD_JOINER });
1320
+ }
1321
+ }
1322
+
1323
+ return edits;
1324
+ }
1325
+
1326
+ const isImage: boolean = data.found.images.has(data.index);
1327
+
1328
+ // In code or HTML a backslash would show; the joiner cannot be seen.
1329
+ if (!isImage && data.found.literal.has(data.index)) {
1330
+ return [{ position: position + 1, deleteCount: 0, insert: WORD_JOINER }];
1331
+ }
1332
+
1333
+ const edits: Array<Edit> = [
1334
+ { position: position, deleteCount: 0, insert: "\\" },
1335
+ ];
1336
+
1337
+ /*
1338
+ * "![]" - an image with no alt text, whose link would have no text to
1339
+ * see or click. Only for an image found, whose address is known.
1340
+ */
1341
+ if (isImage && data.source.startsWith("![]", position)) {
1342
+ edits.push({
1343
+ position: position + 2,
1344
+ deleteCount: 0,
1345
+ insert: getImageLinkLabel(data.found.images.get(data.index)),
1346
+ });
1347
+ }
1348
+
1349
+ return edits;
1350
+ };
1351
+
1352
+ type ApplyEditsFunction = (source: string, edits: Array<Edit>) => string;
1353
+
1354
+ /*
1355
+ * The text with every edit made, in one pass from the start. An edit that
1356
+ * falls inside text an earlier one replaced is dropped: that text is gone.
1357
+ * At the same place a replacement comes first, and so wins.
1358
+ */
1359
+ const applyEdits: ApplyEditsFunction = (
1360
+ source: string,
1361
+ edits: Array<Edit>,
1362
+ ): string => {
1363
+ const ordered: Array<Edit> = [...edits].sort((a: Edit, b: Edit): number => {
1364
+ return a.position - b.position || b.deleteCount - a.deleteCount;
1365
+ });
1366
+
1367
+ const parts: Array<string> = [];
1368
+ let cursor: number = 0;
1369
+
1370
+ for (const edit of ordered) {
1371
+ if (edit.position < cursor) {
1372
+ continue;
1373
+ }
1374
+
1375
+ parts.push(source.slice(cursor, edit.position), edit.insert);
1376
+ cursor = edit.position + edit.deleteCount;
1377
+ }
1378
+
1379
+ parts.push(source.slice(cursor));
1380
+
1381
+ return parts.join("");
1382
+ };
1383
+
1384
+ export type NeutralizeMarkdownImagesAndDiagramsFunction = (
1385
+ markdown: string | undefined | null,
1386
+ ) => string;
1387
+
1388
+ /**
1389
+ * The Markdown with every image turned into a link to the same address and
1390
+ * every mermaid diagram into a plain code block, whatever renderer reads it
1391
+ * (see above); everything else reads exactly as written. Text with neither
1392
+ * comes back unchanged; otherwise its line endings come back as "\n".
1393
+ * Linear in the text's length.
1394
+ */
1395
+ export const neutralizeMarkdownImagesAndDiagrams: NeutralizeMarkdownImagesAndDiagramsFunction =
1396
+ (markdown: string | undefined | null): string => {
1397
+ if (markdown === undefined || markdown === null) {
1398
+ return "";
1399
+ }
1400
+
1401
+ const original: string = String(markdown);
1402
+
1403
+ // As marked reads it, so a position here is a position in what it lexed.
1404
+ const source: string = original.replace(/\r\n|\r/g, "\n");
1405
+
1406
+ const lines: Array<Line> = splitLines(source);
1407
+ const code: TrustedCode = findTrustedCode(source, lines);
1408
+
1409
+ const candidates: Array<Candidate> = findCandidates({
1410
+ source: source,
1411
+ lines: lines,
1412
+ code: code,
1413
+ });
1414
+
1415
+ // Nothing that could be an image or a diagram.
1416
+ if (candidates.length === 0) {
1417
+ return original;
1418
+ }
1419
+
1420
+ let found: FoundInText | null = null;
1421
+
1422
+ if (source.length <= LEXED_TEXT_MAX_LENGTH) {
1423
+ try {
1424
+ found = findInProbe(source, candidates);
1425
+ } catch {
1426
+ // Not read at all: decided as a longer text is.
1427
+ found = null;
1428
+ }
1429
+ }
1430
+
1431
+ if (!found) {
1432
+ found = findWithoutLexing({
1433
+ source: source,
1434
+ lines: lines,
1435
+ candidates: candidates,
1436
+ });
1437
+ }
1438
+
1439
+ const foundInText: FoundInText = found;
1440
+
1441
+ return applyEdits(
1442
+ source,
1443
+ candidates.flatMap((candidate: Candidate, index: number): Array<Edit> => {
1444
+ return getEdits({
1445
+ source: source,
1446
+ candidate: candidate,
1447
+ index: index,
1448
+ found: foundInText,
1449
+ code: code,
1450
+ });
1451
+ }),
1452
+ );
1453
+ };
1454
+
1455
+ export type NeutralizeUntrustedMarkdownFunction = (
1456
+ markdown: string | undefined | null,
1457
+ ) => string;
1458
+
1459
+ /**
1460
+ * Both of the above, for Markdown an outsider wrote: no image or diagram
1461
+ * that acts on its own, and no chat mention.
1462
+ */
1463
+ export const neutralizeUntrustedMarkdown: NeutralizeUntrustedMarkdownFunction =
1464
+ (markdown: string | undefined | null): string => {
1465
+ return neutralizeChatControlSequences(
1466
+ neutralizeMarkdownImagesAndDiagrams(markdown),
1467
+ );
1468
+ };
1469
+
1470
+ export type NeutralizeUntrustedPlainTextFunction = (
1471
+ value: string | undefined | null,
1472
+ ) => string;
1473
+
1474
+ /**
1475
+ * Plain text an outsider wrote that other code places into Markdown as it
1476
+ * is - an incident's title, which episode titles, feed items, chat
1477
+ * messages and note templates take up raw. Its chat control sequences are
1478
+ * broken as above, and so, with the same invisible word joiner, is every
1479
+ * "![", every "]" that a link or a link definition would go on from, and
1480
+ * every "mermaid" after a fence run: wherever the text lands - even beside
1481
+ * other Markdown - no renderer finds a mention, an image or a diagram in it,
1482
+ * or a reference that completes one. It reads exactly as typed - in
1483
+ * Markdown, and as plain text in an email subject or a text message.
1484
+ * Idempotent.
1485
+ */
1486
+ export const neutralizeUntrustedPlainText: NeutralizeUntrustedPlainTextFunction =
1487
+ (value: string | undefined | null): string => {
1488
+ if (value === undefined || value === null) {
1489
+ return "";
1490
+ }
1491
+
1492
+ /*
1493
+ * Also "]" before "(", "[" or ":": joined to other Markdown - an episode
1494
+ * template puts the title and the description side by side - a title
1495
+ * could otherwise define the link reference an image in the description
1496
+ * reads ("[a]: https://tracker.example/p.png"), or complete one opened
1497
+ * there.
1498
+ */
1499
+ const text: string = neutralizeChatControlSequences(value)
1500
+ .replace(IMAGE_OPENER_PATTERN, `!${WORD_JOINER}`)
1501
+ .replace(LINK_TAIL_OPENER_PATTERN, `]${WORD_JOINER}`);
1502
+
1503
+ return applyEdits(
1504
+ text,
1505
+ findDiagramInfoStrings(text, splitLines(text)).flatMap(
1506
+ (info: DiagramInfoString): Array<Edit> => {
1507
+ return info.mermaidWords.map((word: number): Edit => {
1508
+ return { position: word, deleteCount: 0, insert: WORD_JOINER };
1509
+ });
1510
+ },
1511
+ ),
1512
+ );
1513
+ };