@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,1124 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import vm from "vm";
5
+ import yaml from "js-yaml";
6
+ import {
7
+ DEFAULT_IOT_INGESTION_METHOD,
8
+ IOT_EXAMPLE_DEVICE_ID,
9
+ IOT_EXAMPLE_FLEET_NAME,
10
+ IOT_EXAMPLE_GATEWAY_FLEET_NAME,
11
+ IOT_INGESTION_METHODS,
12
+ IOT_METRIC_CONVENTIONS,
13
+ IOT_MQTT_TOPIC_PREFIX,
14
+ IoTIngestionMethod,
15
+ IoTMetricConvention,
16
+ getIoTMqttWebSocketUrl,
17
+ getIoTSetupGuide,
18
+ resolveIoTIngestionMethod,
19
+ } from "../../../../App/FeatureSet/Dashboard/src/Pages/IoT/Utils/DocumentationMarkdown";
20
+ import {
21
+ SETUP_GUIDE_API_KEY_PLACEHOLDER,
22
+ SETUP_GUIDE_URL_PLACEHOLDER,
23
+ SetupGuideContent,
24
+ SetupGuideLink,
25
+ SetupGuideOption,
26
+ SetupGuideStep,
27
+ SetupGuideTopic,
28
+ getSetupGuideMarkdown,
29
+ } from "../../../../App/FeatureSet/Dashboard/src/Components/SetupGuide/SetupGuide";
30
+ import {
31
+ MQTT_DEVICE_UP_METRIC_NAME,
32
+ MQTT_MAX_METRICS_PER_PUBLISH,
33
+ MQTT_MAX_PAYLOAD_BYTES,
34
+ MQTT_TOPIC_PREFIX,
35
+ MqttMetricPoint,
36
+ MqttPublishParseResult,
37
+ buildOtlpMetricsBody,
38
+ parseMqttPublish,
39
+ } from "../../../../App/FeatureSet/Telemetry/Utils/MqttTelemetryMapper";
40
+ import { IOT_SNAPSHOT_METRIC_NAMES } from "../../../Server/Utils/Telemetry/IoTSnapshotScan";
41
+ import {
42
+ IoTMetricDefinition,
43
+ getAllIoTMetrics,
44
+ } from "../../../Types/Monitor/IotMetricCatalog";
45
+ import ColumnLength from "../../../Types/Database/ColumnLength";
46
+ import ExceptionCode from "../../../Types/Exception/ExceptionCode";
47
+ import TelemetryIngestSurface, {
48
+ BROWSER_ALLOWED_INGEST_SURFACES,
49
+ } from "../../../Types/Telemetry/TelemetryIngestSurface";
50
+ import { JSONArray, JSONObject } from "../../../Types/JSON";
51
+
52
+ /*
53
+ * The IoT guide asks how the devices send data — an OpenTelemetry SDK on
54
+ * the device, a Collector on a gateway, or MQTT — and shows only that
55
+ * path. These tests pin, for every option:
56
+ *
57
+ * - the endpoint step 1 shows (the OTLP endpoint, or the MQTT WebSocket
58
+ * URL with the key as the password) and the URL and key in every
59
+ * snippet;
60
+ * - that an option shows its own instructions and none of another's —
61
+ * MQTT topics only on MQTT, environment variables only on the SDK;
62
+ * - that the examples work against the real ingest: the Node.js example
63
+ * is run against a stand-in client and everything it publishes goes
64
+ * through the MQTT ingest's own parser, and the metric names, limits,
65
+ * ports and paths the guide quotes are read from the code that
66
+ * enforces them.
67
+ */
68
+
69
+ type YamlMap = Record<string, any>;
70
+
71
+ const REPO_ROOT: string = path.resolve(__dirname, "../../../../..");
72
+
73
+ const readRepoFile: (relativePath: string) => string = (
74
+ relativePath: string,
75
+ ): string => {
76
+ return fs.readFileSync(path.join(REPO_ROOT, relativePath), "utf8");
77
+ };
78
+
79
+ const squash: (text: string) => string = (text: string): string => {
80
+ return text.replace(/\s+/g, " ");
81
+ };
82
+
83
+ const URL: string = "https://oneuptime.example.com";
84
+ const KEY: string = "tik_secret_123";
85
+
86
+ const METHOD_KEYS: Array<IoTIngestionMethod> = IOT_INGESTION_METHODS.map(
87
+ (option: SetupGuideOption<IoTIngestionMethod>): IoTIngestionMethod => {
88
+ return option.key;
89
+ },
90
+ );
91
+
92
+ const OTLP_METHODS: Array<IoTIngestionMethod> = [
93
+ "opentelemetry-sdk",
94
+ "opentelemetry-collector",
95
+ ];
96
+
97
+ const EXAMPLE_TOPIC: string = `${IOT_MQTT_TOPIC_PREFIX}/${IOT_EXAMPLE_FLEET_NAME}/${IOT_EXAMPLE_DEVICE_ID}`;
98
+
99
+ const guideFor: (
100
+ method: IoTIngestionMethod,
101
+ overrides?: { apiKey?: string; oneuptimeUrl?: string },
102
+ ) => SetupGuideContent = (
103
+ method: IoTIngestionMethod,
104
+ overrides?: { apiKey?: string; oneuptimeUrl?: string },
105
+ ): SetupGuideContent => {
106
+ return getIoTSetupGuide({
107
+ oneuptimeUrl: overrides?.oneuptimeUrl ?? URL,
108
+ apiKey: overrides?.apiKey ?? KEY,
109
+ method: method,
110
+ });
111
+ };
112
+
113
+ const stepTitled: (
114
+ guide: SetupGuideContent,
115
+ title: string,
116
+ ) => SetupGuideStep = (
117
+ guide: SetupGuideContent,
118
+ title: string,
119
+ ): SetupGuideStep => {
120
+ const step: SetupGuideStep | undefined = guide.steps.find(
121
+ (candidate: SetupGuideStep): boolean => {
122
+ return candidate.title === title;
123
+ },
124
+ );
125
+ if (!step) {
126
+ throw new Error(`No step titled "${title}"`);
127
+ }
128
+ return step;
129
+ };
130
+
131
+ const topicTitles: (
132
+ topics: Array<SetupGuideTopic> | undefined,
133
+ ) => Array<string> = (
134
+ topics: Array<SetupGuideTopic> | undefined,
135
+ ): Array<string> => {
136
+ return (topics || []).map((topic: SetupGuideTopic): string => {
137
+ return topic.title;
138
+ });
139
+ };
140
+
141
+ const topicTitled: (
142
+ topics: Array<SetupGuideTopic> | undefined,
143
+ title: string,
144
+ ) => SetupGuideTopic | undefined = (
145
+ topics: Array<SetupGuideTopic> | undefined,
146
+ title: string,
147
+ ): SetupGuideTopic | undefined => {
148
+ return (topics || []).find((topic: SetupGuideTopic): boolean => {
149
+ return topic.title === title;
150
+ });
151
+ };
152
+
153
+ const codeBlocksOf: (markdown: string, language: string) => Array<string> = (
154
+ markdown: string,
155
+ language: string,
156
+ ): Array<string> => {
157
+ return Array.from(
158
+ markdown.matchAll(
159
+ new RegExp(`\`\`\`${language}\\n([\\s\\S]*?)\`\`\``, "g"),
160
+ ),
161
+ ).map((match: RegExpMatchArray): string => {
162
+ return match[1] || "";
163
+ });
164
+ };
165
+
166
+ // One publish through the MQTT ingest's own parser.
167
+ const publish: (topic: string, payload: string) => MqttPublishParseResult = (
168
+ topic: string,
169
+ payload: string,
170
+ ): MqttPublishParseResult => {
171
+ return parseMqttPublish({
172
+ topic: topic,
173
+ payload: Buffer.from(payload, "utf8"),
174
+ nowMs: Date.parse("2026-01-01T00:00:00.000Z"),
175
+ });
176
+ };
177
+
178
+ const pointsOf: (result: MqttPublishParseResult) => Record<string, number> = (
179
+ result: MqttPublishParseResult,
180
+ ): Record<string, number> => {
181
+ expect(result.error).toBeUndefined();
182
+ const values: Record<string, number> = {};
183
+ for (const point of result.payload?.points || []) {
184
+ values[point.name] = point.value;
185
+ }
186
+ return values;
187
+ };
188
+
189
+ /*
190
+ * Commands and settings only one option uses. An option's guide must carry
191
+ * its own and none of the others'.
192
+ */
193
+ const OPTION_SIGNATURES: Record<IoTIngestionMethod, Array<string>> = {
194
+ "opentelemetry-sdk": [
195
+ "export OTEL_EXPORTER_OTLP_HEADERS=",
196
+ "OTEL_RESOURCE_ATTRIBUTES=iot.fleet.name",
197
+ "OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf",
198
+ ],
199
+ "opentelemetry-collector": [
200
+ "processors: [resource, batch]",
201
+ "docker run -d",
202
+ "otelcol-contrib --config config.yaml",
203
+ "encoding: json",
204
+ ],
205
+ mqtt: [
206
+ "mqtt.connect(",
207
+ "mosquitto_pub",
208
+ "MQTT_INGEST_PORT",
209
+ "Device Registry",
210
+ `${EXAMPLE_TOPIC}/telemetry`,
211
+ ],
212
+ };
213
+
214
+ describe("the ingestion option picker", () => {
215
+ test("offers the SDK, a gateway Collector and MQTT, SDK first", () => {
216
+ expect(METHOD_KEYS).toEqual([
217
+ "opentelemetry-sdk",
218
+ "opentelemetry-collector",
219
+ "mqtt",
220
+ ]);
221
+ expect(DEFAULT_IOT_INGESTION_METHOD).toBe("opentelemetry-sdk");
222
+ expect(
223
+ IOT_INGESTION_METHODS.map(
224
+ (option: SetupGuideOption<IoTIngestionMethod>): string => {
225
+ return option.label;
226
+ },
227
+ ),
228
+ ).toEqual(["OpenTelemetry SDK", "OpenTelemetry Collector", "MQTT"]);
229
+ });
230
+
231
+ test("every option has a one-line description", () => {
232
+ for (const option of IOT_INGESTION_METHODS) {
233
+ expect((option.description || "").length).toBeGreaterThan(0);
234
+ expect(option.description).not.toContain("\n");
235
+ }
236
+ });
237
+
238
+ test("an unknown or retired option resolves to the SDK", () => {
239
+ // "opentelemetry" was the single OpenTelemetry option before the split.
240
+ for (const value of [undefined, null, "", "opentelemetry", "MQTT"]) {
241
+ expect(resolveIoTIngestionMethod(value)).toBe("opentelemetry-sdk");
242
+ }
243
+ for (const method of METHOD_KEYS) {
244
+ expect(resolveIoTIngestionMethod(method)).toBe(method);
245
+ }
246
+ });
247
+ });
248
+
249
+ describe.each(METHOD_KEYS)("the %s guide", (method: IoTIngestionMethod) => {
250
+ const guide: SetupGuideContent = guideFor(method);
251
+ const markdown: string = getSetupGuideMarkdown(guide);
252
+ const isMqtt: boolean = method === "mqtt";
253
+
254
+ test("step 1 shows the endpoint the snippets send to", () => {
255
+ if (isMqtt) {
256
+ expect(guide.keyStep?.endpointLabel).toBe("MQTT WebSocket URL");
257
+ expect(guide.keyStep?.endpointValue).toBe(
258
+ "wss://oneuptime.example.com/mqtt",
259
+ );
260
+ expect(guide.keyStep?.endpointHint).toContain("MQTT password");
261
+ expect(guide.keyStep?.description).toContain("password");
262
+ } else {
263
+ expect(guide.keyStep?.endpointLabel).toBe("OTLP Endpoint");
264
+ expect(guide.keyStep?.endpointValue).toBe(`${URL}/otlp`);
265
+ expect(guide.keyStep?.endpointHint).toBeUndefined();
266
+ expect(guide.keyStep?.description).toContain("x-oneuptime-token");
267
+ }
268
+ // Rendered as plain text next to the key picker.
269
+ for (const text of [
270
+ guide.keyStep?.description,
271
+ guide.keyStep?.endpointHint || "",
272
+ ]) {
273
+ expect(text).not.toMatch(/[`*[\]]/);
274
+ }
275
+ });
276
+
277
+ test("has the option's own short steps", () => {
278
+ const titles: Array<string> = guide.steps.map(
279
+ (step: SetupGuideStep): string => {
280
+ return step.title;
281
+ },
282
+ );
283
+ const expected: Record<IoTIngestionMethod, Array<string>> = {
284
+ "opentelemetry-sdk": [
285
+ "Point the SDK at OneUptime",
286
+ "Record readings as iot_* metrics",
287
+ "Check the fleet appears",
288
+ ],
289
+ "opentelemetry-collector": [
290
+ "Save the gateway's collector config",
291
+ "Run the collector on the gateway",
292
+ "Check the fleet appears",
293
+ ],
294
+ mqtt: ["Publish a reading", "Check the fleet appears"],
295
+ };
296
+ expect(titles).toEqual(expected[method]);
297
+ });
298
+
299
+ test("every step has a one-sentence plain-text description", () => {
300
+ for (const step of guide.steps) {
301
+ expect(step.description).toBeTruthy();
302
+ expect(step.description).not.toMatch(/[`*[\]]/);
303
+ expect(step.description).not.toContain("\n");
304
+ expect(step.description).toMatch(/\.$/);
305
+ }
306
+ });
307
+
308
+ test("the prerequisites are two to four one-liners", () => {
309
+ const prerequisites: Array<string> = guide.prerequisites || [];
310
+ expect(prerequisites.length).toBeGreaterThanOrEqual(2);
311
+ expect(prerequisites.length).toBeLessThanOrEqual(4);
312
+ for (const line of prerequisites) {
313
+ expect(line).not.toContain("\n");
314
+ }
315
+ expect(prerequisites.join("\n")).toMatch(/network access/i);
316
+ });
317
+
318
+ test("shows its own instructions and none of another option's", () => {
319
+ for (const signature of OPTION_SIGNATURES[method]) {
320
+ expect(markdown).toContain(signature);
321
+ }
322
+ for (const other of METHOD_KEYS) {
323
+ if (other === method) {
324
+ continue;
325
+ }
326
+ for (const signature of OPTION_SIGNATURES[other]) {
327
+ expect({
328
+ other,
329
+ signature,
330
+ present: markdown.includes(signature),
331
+ }).toEqual({ other, signature, present: false });
332
+ }
333
+ }
334
+ });
335
+
336
+ test("MQTT topics appear only in the MQTT guide, the OTLP header only in the OTLP ones", () => {
337
+ expect(markdown.includes(`${IOT_MQTT_TOPIC_PREFIX}/<fleet>`)).toBe(isMqtt);
338
+ expect(markdown.includes("x-oneuptime-token")).toBe(!isMqtt);
339
+ expect(markdown.includes("/otlp")).toBe(!isMqtt);
340
+ });
341
+
342
+ test("has the model and metric conventions, and the option's own topics", () => {
343
+ const titles: Array<string> = topicTitles(guide.advanced);
344
+ expect(titles.slice(0, 2)).toEqual([
345
+ "How OneUptime models IoT",
346
+ "Metric conventions",
347
+ ]);
348
+ expect(titles.includes("How the gateway config works")).toBe(
349
+ method === "opentelemetry-collector",
350
+ );
351
+ for (const mqttOnly of [
352
+ "Give each device its own credential",
353
+ "Detect offline devices with a Last Will",
354
+ "MQTT topics and payloads",
355
+ "Raw MQTT over TCP (self-hosted)",
356
+ ]) {
357
+ expect(titles.includes(mqttOnly)).toBe(isMqtt);
358
+ }
359
+ });
360
+
361
+ test("every Advanced topic has a plain one-line summary", () => {
362
+ for (const topic of guide.advanced || []) {
363
+ expect(topic.summary).toBeTruthy();
364
+ // Summaries render as plain text, so no markdown.
365
+ expect(topic.summary).not.toMatch(/[`*[\]]/);
366
+ expect(topic.summary).not.toContain("\n");
367
+ }
368
+ });
369
+
370
+ test("troubleshooting is titled by symptom and matches the option", () => {
371
+ const titles: Array<string> = topicTitles(guide.troubleshooting);
372
+ expect(titles[0]).toBe("The fleet does not appear");
373
+ expect(titles).toContain("Devices are missing from the inventory");
374
+ expect(titles).toContain("Readings do not show on the fleet's charts");
375
+ expect(titles.includes("HTTP 401 or 422 from the exporter")).toBe(!isMqtt);
376
+ expect(
377
+ titles.includes(
378
+ 'The connection is refused with "bad username or password"',
379
+ ),
380
+ ).toBe(isMqtt);
381
+ expect(
382
+ titles.includes("Devices flip to offline while they are running"),
383
+ ).toBe(isMqtt);
384
+ });
385
+
386
+ test("links to documentation that exists", () => {
387
+ const urls: Array<string> = (guide.links || []).map(
388
+ (link: SetupGuideLink): string => {
389
+ return link.url;
390
+ },
391
+ );
392
+ expect(urls).toEqual([
393
+ "/docs/telemetry/iot-devices",
394
+ "/docs/monitor/iot-device-monitor",
395
+ ]);
396
+ for (const url of urls) {
397
+ expect(
398
+ fs.existsSync(
399
+ path.join(
400
+ REPO_ROOT,
401
+ "packages/App/FeatureSet/Docs/Content/en",
402
+ `${url.replace(/^\/docs\//, "")}.md`,
403
+ ),
404
+ ),
405
+ ).toBe(true);
406
+ }
407
+ });
408
+
409
+ test("every code fence is closed", () => {
410
+ expect((markdown.match(/```/g) || []).length % 2).toBe(0);
411
+ });
412
+
413
+ test("the verify step lists the fleet, its devices and its metrics", () => {
414
+ const verify: string =
415
+ stepTitled(guide, "Check the fleet appears").markdown || "";
416
+ expect(verify).toContain("open the **IoT** section");
417
+ expect(verify).toContain("fleet's **Devices** tab");
418
+ expect(verify).toContain("Open **Metrics** under the fleet");
419
+ if (isMqtt) {
420
+ expect(verify).toContain("return code 4");
421
+ } else {
422
+ expect(verify).toContain("HTTP `401` or `422`");
423
+ }
424
+ });
425
+ });
426
+
427
+ describe("the OpenTelemetry SDK option", () => {
428
+ const guide: SetupGuideContent = guideFor("opentelemetry-sdk");
429
+ const configure: string =
430
+ stepTitled(guide, "Point the SDK at OneUptime").markdown || "";
431
+ const exports: Array<string> = (codeBlocksOf(configure, "bash")[0] || "")
432
+ .trim()
433
+ .split("\n");
434
+
435
+ test("sets the endpoint, protocol, key and IoT resource attributes", () => {
436
+ expect(exports).toEqual([
437
+ `export OTEL_EXPORTER_OTLP_ENDPOINT=${URL}/otlp`,
438
+ "export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf",
439
+ `export OTEL_EXPORTER_OTLP_HEADERS=x-oneuptime-token=${KEY}`,
440
+ `export OTEL_RESOURCE_ATTRIBUTES=iot.fleet.name=${IOT_EXAMPLE_FLEET_NAME},device.id=${IOT_EXAMPLE_DEVICE_ID},service.name=iot/${IOT_EXAMPLE_FLEET_NAME}`,
441
+ ]);
442
+ });
443
+
444
+ test("names the fleet's service after the fleet", () => {
445
+ const attributes: Record<string, string> = {};
446
+ for (const pair of exports[3]!
447
+ .replace("export OTEL_RESOURCE_ATTRIBUTES=", "")
448
+ .split(",")) {
449
+ const [key, value] = pair.split("=");
450
+ attributes[key!] = value!;
451
+ }
452
+ expect(attributes["service.name"]).toBe(
453
+ `iot/${attributes["iot.fleet.name"]}`,
454
+ );
455
+ });
456
+
457
+ test("quotes values the shell would otherwise mangle", () => {
458
+ const placeholder: string =
459
+ codeBlocksOf(
460
+ stepTitled(
461
+ guideFor("opentelemetry-sdk", {
462
+ apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER,
463
+ oneuptimeUrl: SETUP_GUIDE_URL_PLACEHOLDER,
464
+ }),
465
+ "Point the SDK at OneUptime",
466
+ ).markdown || "",
467
+ "bash",
468
+ )[0] || "";
469
+ // < and > are redirections in an unquoted shell word.
470
+ expect(placeholder).toContain(
471
+ `export OTEL_EXPORTER_OTLP_ENDPOINT='${SETUP_GUIDE_URL_PLACEHOLDER}/otlp'`,
472
+ );
473
+ expect(placeholder).toContain(
474
+ `export OTEL_EXPORTER_OTLP_HEADERS='x-oneuptime-token=${SETUP_GUIDE_API_KEY_PLACEHOLDER}'`,
475
+ );
476
+ });
477
+
478
+ test("puts device.id on every datapoint, where the inventory reads it", () => {
479
+ const record: string =
480
+ stepTitled(guide, "Record readings as iot_* metrics").markdown || "";
481
+ expect(record).toContain(
482
+ "The device inventory is keyed on the datapoint's `device.id`, not the resource's",
483
+ );
484
+ for (const name of [
485
+ "iot_device_up",
486
+ "iot_battery_percent",
487
+ "iot_temperature_celsius",
488
+ ]) {
489
+ expect(record).toContain(`| \`${name}\` |`);
490
+ expect(IOT_SNAPSHOT_METRIC_NAMES.has(name)).toBe(true);
491
+ }
492
+ expect(record).toContain(`\`device.id=${IOT_EXAMPLE_DEVICE_ID}\``);
493
+ });
494
+
495
+ test("the OTLP endpoint is one ingest serves", () => {
496
+ // SDKs append /v1/metrics to OTEL_EXPORTER_OTLP_ENDPOINT.
497
+ expect(
498
+ readRepoFile("packages/App/FeatureSet/Telemetry/API/OTelIngest.ts"),
499
+ ).toContain('"/otlp/v1/metrics"');
500
+ });
501
+ });
502
+
503
+ describe("the gateway Collector option", () => {
504
+ const guide: SetupGuideContent = guideFor("opentelemetry-collector");
505
+ const configStep: string =
506
+ stepTitled(guide, "Save the gateway's collector config").markdown || "";
507
+ const config: YamlMap = yaml.load(
508
+ codeBlocksOf(configStep, "yaml")[0] || "",
509
+ ) as YamlMap;
510
+ const run: SetupGuideStep = stepTitled(
511
+ guide,
512
+ "Run the collector on the gateway",
513
+ );
514
+
515
+ test("receives OTLP from devices on the standard ports", () => {
516
+ expect(config["receivers"]["otlp"]["protocols"]).toEqual({
517
+ grpc: { endpoint: "0.0.0.0:4317" },
518
+ http: { endpoint: "0.0.0.0:4318" },
519
+ });
520
+ });
521
+
522
+ test("stamps one fleet, and the matching service, on everything it forwards", () => {
523
+ const attributes: Array<YamlMap> =
524
+ config["processors"]["resource"]["attributes"];
525
+ const byKey: Record<string, YamlMap> = {};
526
+ for (const attribute of attributes) {
527
+ expect(attribute["action"]).toBe("upsert");
528
+ byKey[attribute["key"]] = attribute;
529
+ }
530
+ expect(byKey["iot.fleet.name"]?.["value"]).toBe(
531
+ IOT_EXAMPLE_GATEWAY_FLEET_NAME,
532
+ );
533
+ expect(byKey["service.name"]?.["value"]).toBe(
534
+ `iot/${IOT_EXAMPLE_GATEWAY_FLEET_NAME}`,
535
+ );
536
+ });
537
+
538
+ test("exports to OneUptime with the key", () => {
539
+ expect(config["exporters"]["otlphttp"]).toEqual({
540
+ endpoint: `${URL}/otlp`,
541
+ headers: { "x-oneuptime-token": KEY },
542
+ });
543
+ expect(config["service"]["pipelines"]).toEqual({
544
+ metrics: {
545
+ receivers: ["otlp"],
546
+ processors: ["resource", "batch"],
547
+ exporters: ["otlphttp"],
548
+ },
549
+ });
550
+ });
551
+
552
+ test("keeps the exporter's default protobuf encoding", () => {
553
+ // OtlpIngestDocsClaims.test.ts: no example may set the JSON encoder.
554
+ expect(config["exporters"]["otlphttp"]["encoding"]).toBeUndefined();
555
+ const topic: string =
556
+ topicTitled(guide.advanced, "How the gateway config works")?.markdown ||
557
+ "";
558
+ expect(topic).toContain(
559
+ "Both the default protobuf encoding and `encoding: json` are accepted.",
560
+ );
561
+ });
562
+
563
+ test("runs the collector with Docker or an existing binary", () => {
564
+ expect(
565
+ (run.variants || []).map((variant: { label: string }): string => {
566
+ return variant.label;
567
+ }),
568
+ ).toEqual(["Docker", "otelcol-contrib binary"]);
569
+
570
+ const docker: string = run.variants![0]!.markdown;
571
+ expect(docker).toContain("-p 4317:4317");
572
+ expect(docker).toContain("-p 4318:4318");
573
+ expect(docker).toContain(
574
+ "-v $(pwd)/config.yaml:/etc/otelcol-contrib/config.yaml:ro",
575
+ );
576
+ expect(docker).toContain("--config /etc/otelcol-contrib/config.yaml");
577
+
578
+ for (const variant of run.variants || []) {
579
+ expect(variant.markdown).toContain(
580
+ "OTEL_EXPORTER_OTLP_ENDPOINT=http://<gateway-host>:4318",
581
+ );
582
+ }
583
+ });
584
+ });
585
+
586
+ /*
587
+ * The MQTT guide against the MQTT ingest itself: the Node.js example runs
588
+ * against a stand-in client, and every topic and payload it — or any other
589
+ * snippet — publishes goes through the parser the broker uses.
590
+ */
591
+ describe("the MQTT option works against the real MQTT ingest", () => {
592
+ const guide: SetupGuideContent = guideFor("mqtt");
593
+ const markdown: string = getSetupGuideMarkdown(guide);
594
+ const publishStep: string =
595
+ stepTitled(guide, "Publish a reading").markdown || "";
596
+
597
+ interface RecordedPublish {
598
+ topic: string;
599
+ payload: string;
600
+ }
601
+
602
+ interface ExampleRun {
603
+ url: string;
604
+ options: YamlMap;
605
+ publishes: Array<RecordedPublish>;
606
+ }
607
+
608
+ const runNodeExample: () => ExampleRun = (): ExampleRun => {
609
+ const code: string = codeBlocksOf(publishStep, "javascript")[0] || "";
610
+ const run: ExampleRun = { url: "", options: {}, publishes: [] };
611
+ const handlers: Record<string, () => void> = {};
612
+
613
+ const client: YamlMap = {
614
+ on: (event: string, handler: () => void): void => {
615
+ handlers[event] = handler;
616
+ },
617
+ publish: (topic: string, payload: string): void => {
618
+ run.publishes.push({ topic: topic, payload: payload });
619
+ },
620
+ };
621
+
622
+ vm.runInNewContext(code, {
623
+ require: (name: string): YamlMap => {
624
+ expect(name).toBe("mqtt");
625
+ return {
626
+ connect: (url: string, options: YamlMap): YamlMap => {
627
+ run.url = url;
628
+ run.options = options;
629
+ return client;
630
+ },
631
+ };
632
+ },
633
+ });
634
+
635
+ expect(handlers["connect"]).toBeDefined();
636
+ handlers["connect"]!();
637
+ return run;
638
+ };
639
+
640
+ test("the guide's topic prefix is the one the broker accepts", () => {
641
+ expect(IOT_MQTT_TOPIC_PREFIX).toBe(MQTT_TOPIC_PREFIX);
642
+ });
643
+
644
+ test("the Node.js example connects to the WebSocket URL with the key as the password", () => {
645
+ const run: ExampleRun = runNodeExample();
646
+ expect(run.url).toBe(getIoTMqttWebSocketUrl(URL));
647
+ expect(run.options["password"]).toBe(KEY);
648
+ /*
649
+ * A UUID username is taken as a device credential id; the example's
650
+ * username must not look like one, or the key would be checked as a
651
+ * device secret.
652
+ */
653
+ expect(run.options["username"]).toBe("oneuptime");
654
+ expect(run.options["username"]).not.toMatch(
655
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
656
+ );
657
+ });
658
+
659
+ test("its Last Will marks the device down", () => {
660
+ const run: ExampleRun = runNodeExample();
661
+ const will: YamlMap = run.options["will"];
662
+ expect(will["topic"]).toBe(`${EXAMPLE_TOPIC}/status`);
663
+ expect(pointsOf(publish(will["topic"], will["payload"]))).toEqual({
664
+ [MQTT_DEVICE_UP_METRIC_NAME]: 0,
665
+ });
666
+ });
667
+
668
+ test("everything it publishes is accepted", () => {
669
+ const run: ExampleRun = runNodeExample();
670
+ expect(
671
+ run.publishes.map((recorded: RecordedPublish): string => {
672
+ return recorded.topic;
673
+ }),
674
+ ).toEqual([`${EXAMPLE_TOPIC}/status`, `${EXAMPLE_TOPIC}/telemetry`]);
675
+
676
+ expect(
677
+ pointsOf(publish(run.publishes[0]!.topic, run.publishes[0]!.payload)),
678
+ ).toEqual({ [MQTT_DEVICE_UP_METRIC_NAME]: 1 });
679
+
680
+ expect(
681
+ pointsOf(publish(run.publishes[1]!.topic, run.publishes[1]!.payload)),
682
+ ).toEqual({ iot_device_up: 1, iot_temperature_celsius: 21.5 });
683
+ });
684
+
685
+ test("the topic sets the fleet, its service and the device, as the model says", () => {
686
+ const result: MqttPublishParseResult = publish(
687
+ `${EXAMPLE_TOPIC}/telemetry`,
688
+ '{"metrics":{"iot_battery_percent":87}}',
689
+ );
690
+ const body: JSONObject = buildOtlpMetricsBody(result.payload!);
691
+ const resourceMetric: JSONObject = (
692
+ body["resourceMetrics"] as JSONArray
693
+ )[0] as JSONObject;
694
+ const resourceAttributes: JSONArray = (
695
+ resourceMetric["resource"] as JSONObject
696
+ )["attributes"] as JSONArray;
697
+ expect(resourceAttributes).toEqual([
698
+ { key: "iot.fleet.name", value: { stringValue: IOT_EXAMPLE_FLEET_NAME } },
699
+ {
700
+ key: "service.name",
701
+ value: { stringValue: `iot/${IOT_EXAMPLE_FLEET_NAME}` },
702
+ },
703
+ ]);
704
+ expect(JSON.stringify(body)).toContain(
705
+ JSON.stringify({
706
+ key: "device.id",
707
+ value: { stringValue: IOT_EXAMPLE_DEVICE_ID },
708
+ }),
709
+ );
710
+
711
+ const model: string =
712
+ topicTitled(guide.advanced, "How OneUptime models IoT")?.markdown || "";
713
+ expect(model).toContain("with MQTT the topic sets both");
714
+ expect(model).toContain("It becomes the `iot.fleet.name` of the readings");
715
+ expect(model).toContain("It becomes the `device.id` of every reading");
716
+ });
717
+
718
+ test("the documented topic and payload are accepted", () => {
719
+ const text: string = codeBlocksOf(publishStep, "text")[0] || "";
720
+ expect(text).toContain(
721
+ `Topic: ${IOT_MQTT_TOPIC_PREFIX}/<fleet>/<device>/telemetry`,
722
+ );
723
+ const payload: string = text.match(/Payload: (\{.*\})/)![1]!;
724
+ expect(pointsOf(publish(`${EXAMPLE_TOPIC}/telemetry`, payload))).toEqual({
725
+ iot_device_up: 1,
726
+ iot_battery_percent: 87,
727
+ iot_temperature_celsius: 21.5,
728
+ });
729
+ });
730
+
731
+ test("the raw TCP example publishes the documented payload with the key", () => {
732
+ const topic: string =
733
+ topicTitled(guide.advanced, "Raw MQTT over TCP (self-hosted)")
734
+ ?.markdown || "";
735
+ const command: string = codeBlocksOf(topic, "bash")[0] || "";
736
+ expect(command).toContain("-p 1883");
737
+ expect(command).toContain(`-P ${KEY}`);
738
+ const target: string = command.match(/-t "([^"]+)"/)![1]!;
739
+ const payload: string = command.match(/-m '([^']+)'/)![1]!;
740
+ expect(pointsOf(publish(target, payload))).toEqual({
741
+ iot_device_up: 1,
742
+ iot_battery_percent: 87,
743
+ iot_temperature_celsius: 21.5,
744
+ });
745
+ });
746
+
747
+ test("every topic any snippet names is one the broker accepts", () => {
748
+ const topics: Array<string> = Array.from(
749
+ new Set(
750
+ Array.from(
751
+ markdown.matchAll(/oneuptime\/[a-z0-9-]+\/[a-z0-9-]+\/[a-z/]+/g),
752
+ ).map((match: RegExpMatchArray): string => {
753
+ return match[0];
754
+ }),
755
+ ),
756
+ );
757
+ expect(topics.sort()).toEqual(
758
+ [`${EXAMPLE_TOPIC}/status`, `${EXAMPLE_TOPIC}/telemetry`].sort(),
759
+ );
760
+ for (const topic of topics) {
761
+ const payload: string = topic.endsWith("/status")
762
+ ? "online"
763
+ : '{"metrics":{"iot_device_up":1}}';
764
+ expect(publish(topic, payload).error).toBeUndefined();
765
+ }
766
+ });
767
+
768
+ test("the topics table matches what each topic accepts", () => {
769
+ const table: string =
770
+ topicTitled(guide.advanced, "MQTT topics and payloads")?.markdown || "";
771
+
772
+ // A flat object whose numeric fields are the metrics.
773
+ expect(table).toContain(
774
+ "a flat object whose numeric fields are the metrics",
775
+ );
776
+ expect(
777
+ pointsOf(
778
+ publish(
779
+ `${EXAMPLE_TOPIC}/telemetry`,
780
+ '{"iot_temperature_celsius":21.5}',
781
+ ),
782
+ ),
783
+ ).toEqual({ iot_temperature_celsius: 21.5 });
784
+
785
+ // A single value, bare or wrapped.
786
+ expect(table).toContain('a bare number (`23.4`) or `{"value":23.4}`');
787
+ for (const payload of ["23.4", '{"value":23.4}']) {
788
+ expect(
789
+ pointsOf(
790
+ publish(`${EXAMPLE_TOPIC}/metrics/iot_temperature_celsius`, payload),
791
+ ),
792
+ ).toEqual({ iot_temperature_celsius: 23.4 });
793
+ }
794
+
795
+ // The status topic, and the alternatives the Last Will topic lists.
796
+ const lastWill: string =
797
+ topicTitled(guide.advanced, "Detect offline devices with a Last Will")
798
+ ?.markdown || "";
799
+ for (const [payload, up] of [
800
+ ["online", 1],
801
+ ["offline", 0],
802
+ ["1", 1],
803
+ ["0", 0],
804
+ ["true", 1],
805
+ ["false", 0],
806
+ ["up", 1],
807
+ ["down", 0],
808
+ ] as Array<[string, number]>) {
809
+ expect(pointsOf(publish(`${EXAMPLE_TOPIC}/status`, payload))).toEqual({
810
+ [MQTT_DEVICE_UP_METRIC_NAME]: up,
811
+ });
812
+ if (!["online", "offline"].includes(payload)) {
813
+ expect(lastWill).toContain(`\`${payload}\``);
814
+ }
815
+ }
816
+ });
817
+
818
+ test("attributes are stamped on every datapoint and a timestamp is honoured", () => {
819
+ const result: MqttPublishParseResult = publish(
820
+ `${EXAMPLE_TOPIC}/telemetry`,
821
+ JSON.stringify({
822
+ metrics: { iot_battery_percent: 87, iot_temperature_celsius: 21.5 },
823
+ attributes: { "iot.device.type": "temp-sensor" },
824
+ timestamp: 1767225600,
825
+ }),
826
+ );
827
+ expect(result.error).toBeUndefined();
828
+ expect(result.payload?.timestampMs).toBe(1767225600000);
829
+ for (const point of result.payload!.points) {
830
+ expect((point as MqttMetricPoint).attributes).toEqual({
831
+ "iot.device.type": "temp-sensor",
832
+ });
833
+ }
834
+ });
835
+
836
+ test("the segment rules are the parser's", () => {
837
+ const table: string =
838
+ topicTitled(guide.advanced, "MQTT topics and payloads")?.markdown || "";
839
+ expect(table).toContain(
840
+ "must not contain `/`, `+` or `#` or start with `$`, and are limited to 100 characters",
841
+ );
842
+ expect(ColumnLength.ShortText).toBe(100);
843
+
844
+ const reading: string = '{"metrics":{"iot_device_up":1}}';
845
+ for (const fleet of ["bad+fleet", "bad#fleet", "$fleet", "x".repeat(101)]) {
846
+ expect(
847
+ publish(`${IOT_MQTT_TOPIC_PREFIX}/${fleet}/device/telemetry`, reading)
848
+ .error,
849
+ ).toBeDefined();
850
+ }
851
+ expect(
852
+ publish(
853
+ `${IOT_MQTT_TOPIC_PREFIX}/${"x".repeat(100)}/device/telemetry`,
854
+ reading,
855
+ ).error,
856
+ ).toBeUndefined();
857
+ });
858
+
859
+ test("the size limits are the parser's", () => {
860
+ const table: string =
861
+ topicTitled(guide.advanced, "MQTT topics and payloads")?.markdown || "";
862
+ expect(table).toContain("capped at 128 KB and 100 metrics");
863
+ expect(MQTT_MAX_PAYLOAD_BYTES).toBe(128 * 1024);
864
+ expect(MQTT_MAX_METRICS_PER_PUBLISH).toBe(100);
865
+
866
+ const tooMany: Record<string, number> = {};
867
+ for (let index: number = 0; index <= 100; index++) {
868
+ tooMany[`metric_${index}`] = index;
869
+ }
870
+ expect(
871
+ publish(
872
+ `${EXAMPLE_TOPIC}/telemetry`,
873
+ JSON.stringify({ metrics: tooMany }),
874
+ ).error,
875
+ ).toBeDefined();
876
+ });
877
+ });
878
+
879
+ describe("the MQTT endpoint facts match the server", () => {
880
+ const guide: SetupGuideContent = guideFor("mqtt");
881
+ const markdown: string = getSetupGuideMarkdown(guide);
882
+ const telemetryConfig: string = squash(
883
+ readRepoFile("packages/App/FeatureSet/Telemetry/Config.ts"),
884
+ );
885
+ const mqttServer: string = squash(
886
+ readRepoFile("packages/App/FeatureSet/Telemetry/MqttServer.ts"),
887
+ );
888
+
889
+ test("the WebSocket URL is the instance URL on ws(s) at /mqtt", () => {
890
+ expect(getIoTMqttWebSocketUrl("https://oneuptime.example.com")).toBe(
891
+ "wss://oneuptime.example.com/mqtt",
892
+ );
893
+ expect(getIoTMqttWebSocketUrl("http://localhost:8080")).toBe(
894
+ "ws://localhost:8080/mqtt",
895
+ );
896
+ expect(getIoTMqttWebSocketUrl(SETUP_GUIDE_URL_PLACEHOLDER)).toBe(
897
+ `${SETUP_GUIDE_URL_PLACEHOLDER}/mqtt`,
898
+ );
899
+ expect(telemetryConfig).toContain(
900
+ 'export const MQTT_WEBSOCKET_PATH: string = "/mqtt";',
901
+ );
902
+ });
903
+
904
+ test("the ingress closes idle WebSocket connections after 300 seconds", () => {
905
+ const nginx: string = readRepoFile("packages/Nginx/default.conf.template");
906
+ const start: number = nginx.indexOf("location /mqtt {");
907
+ expect(start).toBeGreaterThan(-1);
908
+ // The block ends where the next location begins (${...} has braces too).
909
+ const end: number = nginx.indexOf("location ", start + 1);
910
+ const block: string = nginx.slice(start, end === -1 ? undefined : end);
911
+ expect(block).toContain("proxy_read_timeout 300s;");
912
+ expect(markdown).toContain(
913
+ "idle WebSocket connections are closed after 300 seconds",
914
+ );
915
+ expect(markdown).toContain("under 5 minutes");
916
+ });
917
+
918
+ test("raw TCP listens on MQTT_INGEST_PORT, 1883 by default, and can be turned off", () => {
919
+ expect(telemetryConfig).toContain(
920
+ 'export const MQTT_INGEST_PORT: number = parseBatchSize( "MQTT_INGEST_PORT", 1883, );',
921
+ );
922
+ expect(telemetryConfig).toContain(
923
+ 'process.env["MQTT_INGEST_ENABLED"] !== "false"',
924
+ );
925
+ expect(readRepoFile("config.example.env")).toContain(
926
+ "MQTT_INGEST_PORT=1883",
927
+ );
928
+ expect(markdown).toContain("(`MQTT_INGEST_PORT`, default `1883`)");
929
+ expect(markdown).toContain("`MQTT_INGEST_ENABLED=false`");
930
+ });
931
+
932
+ test("bad credentials are refused at CONNECT with return code 4", () => {
933
+ expect(mqttServer).toContain(
934
+ "const CONNACK_BAD_USERNAME_OR_PASSWORD: number = 4;",
935
+ );
936
+ expect(markdown).toContain("return code 4");
937
+ });
938
+
939
+ test("browser keys are refused over MQTT", () => {
940
+ expect(
941
+ BROWSER_ALLOWED_INGEST_SURFACES.has(TelemetryIngestSurface.Mqtt),
942
+ ).toBe(false);
943
+ expect(mqttServer).toContain("surface: TelemetryIngestSurface.Mqtt,");
944
+ expect(markdown).toContain("browser keys are refused over MQTT");
945
+ });
946
+
947
+ test("subscriptions are refused and bad publishes are dropped with a warning", () => {
948
+ expect(mqttServer).toContain("broker.authorizeSubscribe =");
949
+ expect(mqttServer).toContain("MQTT: dropped publish to");
950
+ expect(markdown).toContain("subscriptions are refused");
951
+ expect(markdown).toContain("`MQTT: dropped publish to …`");
952
+ });
953
+
954
+ test("a revoked device credential is cut off within about a minute", () => {
955
+ expect(
956
+ squash(
957
+ readRepoFile(
958
+ "packages/Common/Server/Services/IoTDeviceCredentialService.ts",
959
+ ),
960
+ ),
961
+ ).toContain("const POSITIVE_TTL_MS: number = 60 * 1000;");
962
+ expect(markdown).toContain("cut off within about a minute");
963
+ });
964
+
965
+ test("the fleet's Device Registry tab exists", () => {
966
+ expect(
967
+ readRepoFile(
968
+ "packages/App/FeatureSet/Dashboard/src/Pages/IoT/View/SideMenu.tsx",
969
+ ),
970
+ ).toContain('title: "Device Registry"');
971
+ });
972
+ });
973
+
974
+ describe("the metric conventions", () => {
975
+ const names: Array<string> = IOT_METRIC_CONVENTIONS.map(
976
+ (metric: IoTMetricConvention): string => {
977
+ return metric.name;
978
+ },
979
+ );
980
+
981
+ test("are exactly the metrics the inventory scan reads", () => {
982
+ expect([...names].sort()).toEqual(
983
+ Array.from(IOT_SNAPSHOT_METRIC_NAMES).sort(),
984
+ );
985
+ });
986
+
987
+ test("cover every metric the IoT monitor offers", () => {
988
+ for (const metric of getAllIoTMetrics()) {
989
+ expect(names).toContain((metric as IoTMetricDefinition).metricName);
990
+ }
991
+ });
992
+
993
+ test("include the metric the MQTT status topic maps to", () => {
994
+ expect(names).toContain(MQTT_DEVICE_UP_METRIC_NAME);
995
+ });
996
+
997
+ test.each(METHOD_KEYS)(
998
+ "are listed in full in the %s guide",
999
+ (method: IoTIngestionMethod) => {
1000
+ const topic: string =
1001
+ topicTitled(guideFor(method).advanced, "Metric conventions")
1002
+ ?.markdown || "";
1003
+ for (const metric of IOT_METRIC_CONVENTIONS) {
1004
+ expect(topic).toContain(`| \`${metric.name}\` | ${metric.meaning} |`);
1005
+ }
1006
+ },
1007
+ );
1008
+ });
1009
+
1010
+ describe("the attribute model matches the ingest", () => {
1011
+ const scan: string = readRepoFile(
1012
+ "packages/Common/Server/Utils/Telemetry/IoTSnapshotScan.ts",
1013
+ );
1014
+
1015
+ test("device.id and the classifying attributes are read from each datapoint", () => {
1016
+ for (const key of ["device.id", "iot.device.kind", "iot.device.type"]) {
1017
+ expect(scan).toContain(`getStringAttribute(dpAttributes, "${key}")`);
1018
+ }
1019
+ expect(squash(scan)).toContain('dpAttributes, "iot.device.firmware",');
1020
+
1021
+ const model: string =
1022
+ topicTitled(
1023
+ guideFor("opentelemetry-sdk").advanced,
1024
+ "How OneUptime models IoT",
1025
+ )?.markdown || "";
1026
+ expect(model).toContain("| `device.id` | Each datapoint | Yes |");
1027
+ for (const key of [
1028
+ "iot.device.kind",
1029
+ "iot.device.type",
1030
+ "iot.device.firmware",
1031
+ ]) {
1032
+ expect(model).toContain(`| \`${key}\` | Each datapoint | No |`);
1033
+ }
1034
+ });
1035
+
1036
+ test("the fleet comes from the iot.fleet.name resource attribute", () => {
1037
+ expect(
1038
+ squash(
1039
+ readRepoFile(
1040
+ "packages/App/FeatureSet/Telemetry/Services/OtelIngestBaseService.ts",
1041
+ ),
1042
+ ),
1043
+ ).toContain('this.getStringAttribute(attributes, "iot.fleet.name") ||');
1044
+ const model: string =
1045
+ topicTitled(
1046
+ guideFor("opentelemetry-collector").advanced,
1047
+ "How OneUptime models IoT",
1048
+ )?.markdown || "";
1049
+ expect(model).toContain("| `iot.fleet.name` | Resource | Yes |");
1050
+ });
1051
+ });
1052
+
1053
+ describe("401 and 422 from the exporter", () => {
1054
+ test("mean what ingest answers them for", () => {
1055
+ expect(ExceptionCode.NotAuthenticatedException).toBe(401);
1056
+ expect(ExceptionCode.NotAuthorizedException).toBe(422);
1057
+ const middleware: string = squash(
1058
+ readRepoFile("packages/Common/Server/Middleware/TelemetryIngest.ts"),
1059
+ );
1060
+ expect(middleware).toContain(
1061
+ 'new NotAuthenticatedException( "This telemetry ingestion key expired.", )',
1062
+ );
1063
+ expect(middleware).toContain(
1064
+ 'new NotAuthorizedException( "This telemetry ingestion key has been disabled.", )',
1065
+ );
1066
+
1067
+ for (const method of OTLP_METHODS) {
1068
+ const topic: string =
1069
+ topicTitled(
1070
+ guideFor(method).troubleshooting,
1071
+ "HTTP 401 or 422 from the exporter",
1072
+ )?.markdown || "";
1073
+ expect(topic).toContain(
1074
+ "`401` means the ingestion key is missing, wrong or expired; `422` means it has been disabled",
1075
+ );
1076
+ // Ingest never answers 403 for a key.
1077
+ expect(getSetupGuideMarkdown(guideFor(method))).not.toContain("403");
1078
+ }
1079
+ });
1080
+ });
1081
+
1082
+ describe("before a key is picked", () => {
1083
+ test.each(METHOD_KEYS)(
1084
+ "%s shows the placeholder and says where to pick a key",
1085
+ (method: IoTIngestionMethod) => {
1086
+ const markdown: string = getSetupGuideMarkdown(
1087
+ guideFor(method, { apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER }),
1088
+ );
1089
+ expect(markdown).toContain(SETUP_GUIDE_API_KEY_PLACEHOLDER);
1090
+ expect(markdown).toContain("Pick an ingestion key in step 1");
1091
+ },
1092
+ );
1093
+
1094
+ test.each(METHOD_KEYS)(
1095
+ "%s drops the note and the placeholder once a key is picked",
1096
+ (method: IoTIngestionMethod) => {
1097
+ const markdown: string = getSetupGuideMarkdown(guideFor(method));
1098
+ expect(markdown).not.toContain("Pick an ingestion key in step 1");
1099
+ expect(markdown).not.toContain(SETUP_GUIDE_API_KEY_PLACEHOLDER);
1100
+ },
1101
+ );
1102
+
1103
+ test("the MQTT snippets carry the placeholder as the password", () => {
1104
+ const markdown: string = getSetupGuideMarkdown(
1105
+ guideFor("mqtt", { apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER }),
1106
+ );
1107
+ expect(markdown).toContain(
1108
+ `password: "${SETUP_GUIDE_API_KEY_PLACEHOLDER}"`,
1109
+ );
1110
+ // Quoted, so the shell does not read < and > as redirections.
1111
+ expect(markdown).toContain(`-P '${SETUP_GUIDE_API_KEY_PLACEHOLDER}'`);
1112
+ });
1113
+
1114
+ test("the gateway config carries the placeholder as the token", () => {
1115
+ const markdown: string = getSetupGuideMarkdown(
1116
+ guideFor("opentelemetry-collector", {
1117
+ apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER,
1118
+ }),
1119
+ );
1120
+ expect(markdown).toContain(
1121
+ `"x-oneuptime-token": "${SETUP_GUIDE_API_KEY_PLACEHOLDER}"`,
1122
+ );
1123
+ });
1124
+ });