@oneuptime/common 12.0.32 → 12.0.33

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 (597) hide show
  1. package/Models/AnalyticsModels/Span.ts +14 -0
  2. package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
  3. package/Models/DatabaseModels/Index.ts +10 -0
  4. package/Models/DatabaseModels/Monitor.ts +76 -0
  5. package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
  6. package/Models/DatabaseModels/NetworkDevice.ts +176 -1
  7. package/Models/DatabaseModels/NetworkSite.ts +201 -2
  8. package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
  9. package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
  10. package/Models/DatabaseModels/TelemetryException.ts +119 -0
  11. package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
  12. package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
  13. package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
  14. package/Server/API/EnterpriseLicenseAPI.ts +391 -64
  15. package/Server/API/LlmProviderAPI.ts +137 -22
  16. package/Server/EnvironmentConfig.ts +14 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
  24. package/Server/Infrastructure/QueueWorker.ts +38 -8
  25. package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
  26. package/Server/Middleware/ProjectAuthorization.ts +11 -0
  27. package/Server/Middleware/SCIMAuthorization.ts +12 -0
  28. package/Server/Middleware/TelemetryIngest.ts +11 -0
  29. package/Server/Services/AIBillingService.ts +101 -27
  30. package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
  31. package/Server/Services/EnterpriseLicenseService.ts +55 -0
  32. package/Server/Services/Index.ts +10 -0
  33. package/Server/Services/MonitorService.ts +143 -21
  34. package/Server/Services/MonitorStatusTimelineService.ts +150 -8
  35. package/Server/Services/MonitorTemplateService.ts +217 -1
  36. package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
  37. package/Server/Services/NetworkAlertPolicyService.ts +944 -0
  38. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +9 -10
  39. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
  40. package/Server/Services/NetworkDeviceService.ts +1032 -73
  41. package/Server/Services/NetworkSiteService.ts +1502 -129
  42. package/Server/Services/NetworkSiteTypeService.ts +1216 -0
  43. package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
  44. package/Server/Services/NotificationService.ts +118 -28
  45. package/Server/Services/ProjectService.ts +105 -48
  46. package/Server/Services/StatusPagePrivateUserService.ts +103 -3
  47. package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
  48. package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
  49. package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
  50. package/Server/Services/UserNotificationSettingService.ts +62 -25
  51. package/Server/Services/UserService.ts +95 -0
  52. package/Server/Types/Database/QueryHelper.ts +2 -2
  53. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
  54. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
  55. package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
  56. package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
  57. package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
  58. package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
  59. package/Server/Utils/DataSource/HttpFetch.ts +9 -2
  60. package/Server/Utils/EmailRollup/EmailRollupConstants.ts +98 -0
  61. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +872 -0
  62. package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
  63. package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
  64. package/Server/Utils/LLM/LLMService.ts +78 -0
  65. package/Server/Utils/LogRedaction.ts +8 -0
  66. package/Server/Utils/Logger.ts +79 -1
  67. package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
  68. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
  69. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
  70. package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
  71. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +49 -0
  72. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
  73. package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
  74. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +43 -0
  75. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
  76. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
  77. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
  78. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
  79. package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
  80. package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
  81. package/Server/Utils/OutboundUserAgent.ts +152 -0
  82. package/Server/Utils/StartServer.ts +51 -19
  83. package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
  84. package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
  85. package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
  86. package/Server/Utils/Telemetry.ts +198 -51
  87. package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
  88. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +134 -33
  89. package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
  90. package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
  91. package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
  92. package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
  93. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +18 -9
  94. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
  95. package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
  96. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
  97. package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
  98. package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
  99. package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
  100. package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
  101. package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
  102. package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +41 -5
  103. package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
  104. package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
  105. package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
  106. package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
  107. package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
  108. package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
  109. package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
  110. package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
  111. package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
  112. package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
  113. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
  114. package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
  115. package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
  116. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
  117. package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
  118. package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
  119. package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
  120. package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
  121. package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
  122. package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
  123. package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
  124. package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
  125. package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
  126. package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
  127. package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
  128. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +47 -4
  129. package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
  130. package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
  131. package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
  132. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
  133. package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
  134. package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
  135. package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
  136. package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
  137. package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
  138. package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
  139. package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
  140. package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
  141. package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
  142. package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
  143. package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
  144. package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
  145. package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
  146. package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
  147. package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
  148. package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
  149. package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +102 -1
  150. package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
  151. package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
  152. package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
  153. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
  154. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
  155. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
  156. package/Tests/Server/Utils/Captcha.test.ts +422 -0
  157. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
  158. package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
  159. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
  160. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
  161. package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
  162. package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +752 -0
  163. package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
  164. package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
  165. package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
  166. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
  167. package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
  168. package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
  169. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
  170. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
  171. package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
  172. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
  173. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
  174. package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
  175. package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
  176. package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
  177. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
  178. package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
  179. package/Tests/Server/Utils/Telemetry.test.ts +456 -66
  180. package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
  181. package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
  182. package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
  183. package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
  184. package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
  185. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
  186. package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
  187. package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
  188. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
  189. package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
  190. package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
  191. package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
  192. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
  193. package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
  194. package/Tests/UI/Components/SideMenuItem.test.tsx +226 -4
  195. package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
  196. package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
  197. package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
  198. package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
  199. package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
  200. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
  201. package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
  202. package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
  203. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
  204. package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
  205. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
  206. package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
  207. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
  208. package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
  209. package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
  210. package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
  211. package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
  212. package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
  213. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
  214. package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
  215. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
  216. package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
  217. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
  218. package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
  219. package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
  220. package/Types/AI/ExceptionAIClassification.ts +10 -24
  221. package/Types/Email/EmailTemplateType.ts +2 -0
  222. package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
  223. package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
  224. package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
  225. package/Types/Exception/ApiException.ts +10 -0
  226. package/Types/Exception/BadDataException.ts +11 -0
  227. package/Types/Exception/BadRequestException.ts +11 -0
  228. package/Types/Exception/Exception.ts +65 -0
  229. package/Types/Exception/ForbiddenException.ts +10 -0
  230. package/Types/Exception/NotAuthenticatedException.ts +10 -0
  231. package/Types/Exception/NotAuthorizedException.ts +10 -0
  232. package/Types/Exception/NotFoundException.ts +11 -0
  233. package/Types/Exception/PayloadTooLargeException.ts +11 -0
  234. package/Types/Exception/PaymentRequiredException.ts +10 -0
  235. package/Types/Exception/ServiceUnavailableException.ts +10 -0
  236. package/Types/Exception/SsoAuthorizationException.ts +10 -0
  237. package/Types/Exception/TenantNotFoundException.ts +11 -0
  238. package/Types/Exception/TimeoutException.ts +10 -0
  239. package/Types/Exception/TooManyRequestsException.ts +10 -0
  240. package/Types/Exception/UnableToReachServer.ts +10 -0
  241. package/Types/Exception/WebsiteRequestException.ts +10 -0
  242. package/Types/Monitor/CriteriaFilter.ts +60 -2
  243. package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
  244. package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
  245. package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
  246. package/Types/Monitor/MonitorMetricType.ts +71 -0
  247. package/Types/Monitor/MonitorStep.ts +76 -0
  248. package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
  249. package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
  250. package/Types/Monitor/MonitorType.ts +47 -1
  251. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
  252. package/Types/Monitor/SqlConnectionConfig.ts +31 -0
  253. package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
  254. package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
  255. package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
  256. package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
  257. package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
  258. package/Types/Permission.ts +90 -0
  259. package/Types/Probe/ProbeMonitorResponse.ts +16 -0
  260. package/Types/Telemetry/ErrorClass.ts +274 -0
  261. package/Types/Telemetry/UnitOfWork.ts +59 -0
  262. package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
  263. package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
  264. package/UI/Components/Modal/Modal.tsx +2 -8
  265. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
  266. package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
  267. package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
  268. package/UI/Components/SideMenu/SideMenu.tsx +123 -5
  269. package/UI/Components/SideMenu/SideMenuItem.tsx +76 -84
  270. package/UI/Components/SideMenu/SideMenuSection.tsx +55 -23
  271. package/UI/Components/SideOver/SideOver.tsx +21 -20
  272. package/UI/Utils/PageScrollLock.ts +79 -3
  273. package/UI/Utils/PermissionGate.ts +61 -0
  274. package/UI/Utils/SensitiveUrlToken.ts +112 -0
  275. package/UI/Utils/TestLLMProvider.ts +11 -0
  276. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
  277. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
  278. package/Utils/Monitor/MonitorMetricType.ts +153 -1
  279. package/Utils/Monitor/NetworkTopologyUtil.ts +23 -3
  280. package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
  281. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
  282. package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
  283. package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
  284. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
  285. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
  286. package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
  287. package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
  288. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
  289. package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
  290. package/build/dist/Models/AnalyticsModels/Span.js +14 -0
  291. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  292. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
  293. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
  294. package/build/dist/Models/DatabaseModels/Index.js +10 -0
  295. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  296. package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
  297. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  298. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
  299. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
  300. package/build/dist/Models/DatabaseModels/NetworkDevice.js +180 -1
  301. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  302. package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
  303. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  304. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
  305. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
  306. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
  307. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
  308. package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
  309. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  310. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
  311. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
  312. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
  313. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
  314. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
  315. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
  316. package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
  317. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
  318. package/build/dist/Server/API/LlmProviderAPI.js +108 -13
  319. package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
  320. package/build/dist/Server/EnvironmentConfig.js +12 -0
  321. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  322. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
  323. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
  324. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
  325. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
  326. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
  327. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
  328. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
  329. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
  330. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
  331. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
  332. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
  333. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
  334. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
  335. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  336. package/build/dist/Server/Infrastructure/QueueWorker.js +33 -5
  337. package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
  338. package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
  339. package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
  340. package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
  341. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  342. package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
  343. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
  344. package/build/dist/Server/Middleware/TelemetryIngest.js +11 -0
  345. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  346. package/build/dist/Server/Services/AIBillingService.js +70 -16
  347. package/build/dist/Server/Services/AIBillingService.js.map +1 -1
  348. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
  349. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
  350. package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
  351. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  352. package/build/dist/Server/Services/Index.js +10 -0
  353. package/build/dist/Server/Services/Index.js.map +1 -1
  354. package/build/dist/Server/Services/MonitorService.js +119 -21
  355. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  356. package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
  357. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  358. package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
  359. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  360. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
  361. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
  362. package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
  363. package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
  364. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +10 -9
  365. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  366. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
  367. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  368. package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
  369. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  370. package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
  371. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  372. package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
  373. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
  374. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
  375. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
  376. package/build/dist/Server/Services/NotificationService.js +80 -17
  377. package/build/dist/Server/Services/NotificationService.js.map +1 -1
  378. package/build/dist/Server/Services/ProjectService.js +66 -30
  379. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  380. package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
  381. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  382. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
  383. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
  384. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
  385. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
  386. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
  387. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
  388. package/build/dist/Server/Services/UserNotificationSettingService.js +46 -20
  389. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  390. package/build/dist/Server/Services/UserService.js +90 -0
  391. package/build/dist/Server/Services/UserService.js.map +1 -1
  392. package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
  393. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  394. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
  395. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  396. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
  397. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
  398. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
  399. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
  400. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
  401. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
  402. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
  403. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
  404. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
  405. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
  406. package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
  407. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  408. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +91 -0
  409. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
  410. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +691 -0
  411. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
  412. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
  413. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
  414. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
  415. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
  416. package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
  417. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  418. package/build/dist/Server/Utils/LogRedaction.js +8 -0
  419. package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
  420. package/build/dist/Server/Utils/Logger.js +63 -1
  421. package/build/dist/Server/Utils/Logger.js.map +1 -1
  422. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
  423. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
  424. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  425. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  426. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
  427. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  428. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
  429. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
  430. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +37 -0
  431. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  432. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
  433. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  434. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
  435. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  436. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +32 -0
  437. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  438. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
  439. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  440. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
  441. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  442. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
  443. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  444. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
  445. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  446. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
  447. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
  448. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
  449. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
  450. package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
  451. package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
  452. package/build/dist/Server/Utils/StartServer.js +38 -14
  453. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  454. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
  455. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
  456. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
  457. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
  458. package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
  459. package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
  460. package/build/dist/Server/Utils/Telemetry.js +162 -46
  461. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  462. package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
  463. package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
  464. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  465. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  466. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
  467. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
  468. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
  469. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
  470. package/build/dist/Types/Exception/ApiException.js +9 -0
  471. package/build/dist/Types/Exception/ApiException.js.map +1 -1
  472. package/build/dist/Types/Exception/BadDataException.js +10 -0
  473. package/build/dist/Types/Exception/BadDataException.js.map +1 -1
  474. package/build/dist/Types/Exception/BadRequestException.js +10 -0
  475. package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
  476. package/build/dist/Types/Exception/Exception.js +56 -0
  477. package/build/dist/Types/Exception/Exception.js.map +1 -1
  478. package/build/dist/Types/Exception/ForbiddenException.js +9 -0
  479. package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
  480. package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
  481. package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
  482. package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
  483. package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
  484. package/build/dist/Types/Exception/NotFoundException.js +10 -0
  485. package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
  486. package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
  487. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
  488. package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
  489. package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
  490. package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
  491. package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
  492. package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
  493. package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
  494. package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
  495. package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
  496. package/build/dist/Types/Exception/TimeoutException.js +9 -0
  497. package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
  498. package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
  499. package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
  500. package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
  501. package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
  502. package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
  503. package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
  504. package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
  505. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  506. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
  507. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
  508. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
  509. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
  510. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
  511. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  512. package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
  513. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  514. package/build/dist/Types/Monitor/MonitorStep.js +54 -0
  515. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  516. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
  517. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
  518. package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
  519. package/build/dist/Types/Monitor/MonitorType.js +45 -1
  520. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  521. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
  522. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  523. package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
  524. package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
  525. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
  526. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
  527. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
  528. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
  529. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
  530. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
  531. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
  532. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
  533. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
  534. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
  535. package/build/dist/Types/Permission.js +80 -0
  536. package/build/dist/Types/Permission.js.map +1 -1
  537. package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
  538. package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
  539. package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
  540. package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
  541. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +2 -7
  542. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
  543. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
  544. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  545. package/build/dist/UI/Components/Modal/Modal.js +2 -7
  546. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  547. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
  548. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  549. package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
  550. package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
  551. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
  552. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
  553. package/build/dist/UI/Components/SideMenu/SideMenu.js +67 -5
  554. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  555. package/build/dist/UI/Components/SideMenu/SideMenuItem.js +49 -53
  556. package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
  557. package/build/dist/UI/Components/SideMenu/SideMenuSection.js +25 -7
  558. package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
  559. package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
  560. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  561. package/build/dist/UI/Utils/PageScrollLock.js +31 -3
  562. package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
  563. package/build/dist/UI/Utils/PermissionGate.js +42 -1
  564. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  565. package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
  566. package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
  567. package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
  568. package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
  569. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
  570. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
  571. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
  572. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  573. package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
  574. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  575. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +8 -3
  576. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  577. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
  578. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
  579. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
  580. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  581. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
  582. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
  583. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
  584. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
  585. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
  586. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  587. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
  588. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  589. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
  590. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
  591. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
  592. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
  593. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
  594. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
  595. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
  596. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
  597. package/package.json +2 -2
@@ -4,8 +4,25 @@ import {
4
4
  } from "../../../../Server/Utils/AI/Chat/ObservabilityChatPrompt";
5
5
  import AIChatPageContextType, {
6
6
  AIChatPageContext,
7
+ AIChatPageContextHelper,
7
8
  } from "../../../../Types/AI/AIChatPageContext";
8
9
  import AIChatPermissionMode from "../../../../Types/AI/AIChatPermissionMode";
10
+ /*
11
+ * Toolbox/Index MUST be imported before any individual tool module. The
12
+ * toolbox sits in an import cycle (tool -> service -> ... -> AIToolbox), so
13
+ * entering through a tool module first re-enters Index before its tools array
14
+ * is assigned and leaves undefined holes in it. Production always enters
15
+ * through Index, which is the order reproduced here.
16
+ */
17
+ import AIToolbox from "../../../../Server/Utils/AI/Toolbox/Index";
18
+ import {
19
+ QueryIncidentsTool,
20
+ SearchIncidentsTool,
21
+ } from "../../../../Server/Utils/AI/Toolbox/IncidentTools";
22
+ import { QueryAlertsTool } from "../../../../Server/Utils/AI/Toolbox/AlertTools";
23
+ import { QueryMonitorsTool } from "../../../../Server/Utils/AI/Toolbox/MonitorTools";
24
+ import { ObservabilityTool } from "../../../../Server/Utils/AI/Toolbox/ToolTypes";
25
+ import { JSONObject } from "../../../../Types/JSON";
9
26
  import { describe, expect, test } from "@jest/globals";
10
27
 
11
28
  const ENTITY_ID: string = "0f10509d-6656-4a08-b957-235fd4e8c52e";
@@ -102,6 +119,58 @@ describe("buildPageContextSection", () => {
102
119
  },
103
120
  );
104
121
 
122
+ /*
123
+ * Regression for #3552. The incidents list ships a suggested prompt card
124
+ * asking "which incidents are currently active or unresolved, and what
125
+ * state is each in?" — and the model replied that it had no tool for that
126
+ * and could only act on one incident once given an incidentId. It was not
127
+ * hallucinating: this guidance summarised the tool as "query_incidents
128
+ * (recent incidents, or one by incidentId)", a NARROWER capability claim
129
+ * than query_incidents' own schema, injected on that exact page. The model
130
+ * paraphrased the parenthetical back as a denial. Page guidance must name
131
+ * the affordance the page's own suggested prompts depend on.
132
+ */
133
+ test('incidents list guidance offers state="active" for unresolved incidents', () => {
134
+ const section: string = buildPageContextSection({
135
+ type: AIChatPageContextType.IncidentsList,
136
+ });
137
+
138
+ expect(section).toContain('state="active"');
139
+ expect(section).toContain("unresolved");
140
+ // The exact phrasing the model quoted back as "I have no such tool".
141
+ expect(section).not.toContain("(recent incidents, or one by incidentId)");
142
+ });
143
+
144
+ /*
145
+ * The alerts list carries the same "what is firing right now?" suggested
146
+ * prompt, and query_alerts has the same state="active" affordance. Its
147
+ * guidance used to stop dead at the tool name ("answered with
148
+ * query_alerts."), which is the same under-claim one page over.
149
+ */
150
+ test('alerts list guidance offers state="active" for unresolved alerts', () => {
151
+ const section: string = buildPageContextSection({
152
+ type: AIChatPageContextType.AlertsList,
153
+ });
154
+
155
+ expect(section).toContain('state="active"');
156
+ expect(section).toContain("unresolved");
157
+ expect(section).not.toContain("answered with query_alerts.");
158
+ });
159
+
160
+ /*
161
+ * "What is down right now?" on the monitors list is query_monitors'
162
+ * problemsOnly flag. Naming only the tool left the model to guess that a
163
+ * plain listing was the best it could do.
164
+ */
165
+ test("monitors list guidance offers problemsOnly for what is down now", () => {
166
+ const section: string = buildPageContextSection({
167
+ type: AIChatPageContextType.MonitorsList,
168
+ });
169
+
170
+ expect(section).toContain("problemsOnly");
171
+ expect(section).not.toContain("answered with query_monitors.");
172
+ });
173
+
105
174
  test("every section reminds the model that context is not evidence", () => {
106
175
  const section: string = buildPageContextSection({
107
176
  type: AIChatPageContextType.Incident,
@@ -168,6 +237,26 @@ describe("buildObservabilityChatSystemPrompt with page context", () => {
168
237
  expect(prompt).toContain("## Hard rules");
169
238
  expect(prompt).toContain("Cite your sources.");
170
239
  });
240
+
241
+ /*
242
+ * buildPageContextSection passing is worthless if the section never makes
243
+ * it into the prompt: the assembled string is what actually reaches the
244
+ * model. #3552 was reported by a user sitting on the incidents list, so
245
+ * that context is asserted end to end.
246
+ */
247
+ test('an incidents list context carries state="active" into the prompt', () => {
248
+ const prompt: string = buildObservabilityChatSystemPrompt({
249
+ currentTime: new Date("2026-07-16T00:00:00Z"),
250
+ permissionMode: AIChatPermissionMode.ReadOnly,
251
+ pageContext: {
252
+ type: AIChatPageContextType.IncidentsList,
253
+ },
254
+ });
255
+
256
+ expect(prompt).toContain("## Current page context");
257
+ expect(prompt).toContain('state="active"');
258
+ expect(prompt).not.toContain("(recent incidents, or one by incidentId)");
259
+ });
171
260
  });
172
261
 
173
262
  /*
@@ -344,3 +433,167 @@ describe("buildObservabilityChatSystemPrompt — action guidance per mode", () =
344
433
  },
345
434
  );
346
435
  });
436
+
437
+ /*
438
+ * The page guidance is a SUMMARY of tools the model also receives in full.
439
+ * When the summary claims LESS than the schema, the model believes the
440
+ * summary — that is #3552. These tests assert both halves at once: that the
441
+ * tool really does take the argument, and that the page whose suggested
442
+ * prompts depend on it says so. Adding an area page means adding a row here,
443
+ * or deciding explicitly that the page has no "what is wrong right now?"
444
+ * affordance to advertise.
445
+ *
446
+ * A type alias rather than an interface on purpose: jest's object-form
447
+ * test.each is typed against Record<string, unknown>, which an interface does
448
+ * not satisfy (it has no implicit index signature).
449
+ */
450
+ type AreaAffordanceCase = {
451
+ type: AIChatPageContextType;
452
+ tool: ObservabilityTool;
453
+ // The tool argument that answers "what is wrong RIGHT NOW?" on this page.
454
+ argument: string;
455
+ // The enum value the model must pass, or null when the argument is a flag.
456
+ enumValue: string | null;
457
+ // The literal text the page guidance must use to name the affordance.
458
+ guidancePhrase: string;
459
+ };
460
+
461
+ function getSchemaProperty(
462
+ tool: ObservabilityTool,
463
+ argument: string,
464
+ ): JSONObject | undefined {
465
+ const properties: JSONObject =
466
+ (tool.inputSchema["properties"] as JSONObject | undefined) || {};
467
+
468
+ return properties[argument] as JSONObject | undefined;
469
+ }
470
+
471
+ describe("page guidance stays in sync with the tool schemas it summarises", () => {
472
+ test.each<AreaAffordanceCase>([
473
+ {
474
+ type: AIChatPageContextType.IncidentsList,
475
+ tool: QueryIncidentsTool,
476
+ argument: "state",
477
+ enumValue: "active",
478
+ guidancePhrase: 'state="active"',
479
+ },
480
+ {
481
+ type: AIChatPageContextType.AlertsList,
482
+ tool: QueryAlertsTool,
483
+ argument: "state",
484
+ enumValue: "active",
485
+ guidancePhrase: 'state="active"',
486
+ },
487
+ {
488
+ type: AIChatPageContextType.MonitorsList,
489
+ tool: QueryMonitorsTool,
490
+ argument: "problemsOnly",
491
+ enumValue: null,
492
+ guidancePhrase: "problemsOnly",
493
+ },
494
+ ])(
495
+ "$type guidance names the $argument affordance its tool really has",
496
+ (testCase: AreaAffordanceCase) => {
497
+ // Half one: the tool's own schema documents the affordance.
498
+ const property: JSONObject | undefined = getSchemaProperty(
499
+ testCase.tool,
500
+ testCase.argument,
501
+ );
502
+
503
+ expect(property).toBeDefined();
504
+
505
+ if (testCase.enumValue) {
506
+ const allowedValues: Array<string> =
507
+ (property?.["enum"] as Array<string> | undefined) || [];
508
+
509
+ expect(allowedValues).toContain(testCase.enumValue);
510
+ }
511
+
512
+ // Half two: the page the user is standing on is told about it.
513
+ const section: string = buildPageContextSection({ type: testCase.type });
514
+
515
+ expect(section).toContain(testCase.tool.name);
516
+ expect(section).toContain(testCase.guidancePhrase);
517
+ },
518
+ );
519
+
520
+ /*
521
+ * The incidents list owns the historical question too, and search_incidents
522
+ * is the only tool that searches incident text. Dropping it here would push
523
+ * "have we seen this before?" onto query_incidents, which cannot search at
524
+ * all. This one is a drift guard: it holds before and after the fix.
525
+ */
526
+ test("the incidents list still routes free-text history to search_incidents", () => {
527
+ const section: string = buildPageContextSection({
528
+ type: AIChatPageContextType.IncidentsList,
529
+ });
530
+
531
+ expect(getSchemaProperty(SearchIncidentsTool, "searchText")).toBeDefined();
532
+ expect(section).toContain(SearchIncidentsTool.name);
533
+ });
534
+ });
535
+
536
+ /*
537
+ * The other direction of the same drift: guidance naming a tool the model was
538
+ * never given. Extracting tool names from prose is safe here because this
539
+ * prompt keeps a strict convention — tool names are snake_case, tool
540
+ * ARGUMENTS are camelCase (incidentId, problemsOnly, createdWithinHours), and
541
+ * everything else is plain English or a UUID. So a snake_case token in the
542
+ * guidance is always a capability claim, and every one of them is checked
543
+ * against the toolbox the runner actually offers. A fresh regex per call
544
+ * keeps the global flag's lastIndex out of the picture.
545
+ */
546
+ function extractToolNameTokens(text: string): Array<string> {
547
+ const tokens: Array<string> =
548
+ text.match(/[a-z][a-z0-9]*(?:_[a-z0-9]+)+/g) || [];
549
+
550
+ return Array.from(new Set(tokens));
551
+ }
552
+
553
+ const TOOLBOX_TOOL_NAMES: Set<string> = new Set(
554
+ AIToolbox.getTools().map((tool: ObservabilityTool): string => {
555
+ return tool.name;
556
+ }),
557
+ );
558
+
559
+ function buildSectionForType(type: AIChatPageContextType): string {
560
+ if (!AIChatPageContextHelper.isEntityType(type)) {
561
+ return buildPageContextSection({ type: type });
562
+ }
563
+
564
+ return buildPageContextSection({
565
+ type: type,
566
+ entityId: type === AIChatPageContextType.Trace ? TRACE_ID : ENTITY_ID,
567
+ });
568
+ }
569
+
570
+ describe("page guidance only names tools that exist in the toolbox", () => {
571
+ /*
572
+ * Driven off the enum rather than a hand-written list, so a new page type
573
+ * fails here until someone decides what it routes to.
574
+ */
575
+ test.each<[AIChatPageContextType]>(
576
+ Object.values(AIChatPageContextType).map(
577
+ (type: AIChatPageContextType): [AIChatPageContextType] => {
578
+ return [type];
579
+ },
580
+ ),
581
+ )(
582
+ "%s names at least one tool and every tool it names is real",
583
+ (type: AIChatPageContextType) => {
584
+ const section: string = buildSectionForType(type);
585
+ const mentionedTools: Array<string> = extractToolNameTokens(section);
586
+
587
+ // Guidance that routes the model nowhere is guidance it cannot use.
588
+ expect(mentionedTools.length).toBeGreaterThan(0);
589
+
590
+ const notInToolbox: Array<string> = mentionedTools.filter(
591
+ (name: string): boolean => {
592
+ return !TOOLBOX_TOOL_NAMES.has(name);
593
+ },
594
+ );
595
+
596
+ expect(notInToolbox).toEqual([]);
597
+ },
598
+ );
599
+ });
@@ -0,0 +1,422 @@
1
+ import { describe, expect, it, jest, beforeEach } from "@jest/globals";
2
+
3
+ /*
4
+ * Captcha verification, which is a gate rather than a feature: everything it
5
+ * protects (signup, password reset, the public forms) is reachable by anyone on
6
+ * the internet, so the only behaviour that matters is what it does when
7
+ * something is wrong.
8
+ *
9
+ * Three ways it could fail open, none of them visible from the outside — the
10
+ * page looks identical whether the check ran or not:
11
+ *
12
+ * 1. Enabled with no secret key. There is nothing to verify against, and
13
+ * "cannot verify" must mean "reject", not "allow".
14
+ * 2. The provider is unreachable, times out, or answers with something other
15
+ * than success. An hCaptcha outage must not become an open door.
16
+ * 3. A blank or whitespace-only token passed off as a solved challenge.
17
+ *
18
+ * `CaptchaEnabled` and `CaptchaSecretKey` are read from the environment at
19
+ * module load, so each configuration below gets a freshly required copy of the
20
+ * module. axios is mocked throughout: these assertions are about the decision,
21
+ * and a test that reached hcaptcha.com would be neither hermetic nor honest.
22
+ */
23
+
24
+ const SITEVERIFY_URL: string = "https://hcaptcha.com/siteverify";
25
+
26
+ interface CaptchaModule {
27
+ default: {
28
+ isCaptchaEnabled: () => boolean;
29
+ verifyCaptcha: (options: {
30
+ token: string | null | undefined;
31
+ remoteIp?: string | null;
32
+ }) => Promise<void>;
33
+ };
34
+ }
35
+
36
+ interface PostCall {
37
+ url: string;
38
+ body: string;
39
+ }
40
+
41
+ interface LoadedCaptcha {
42
+ captcha: CaptchaModule["default"];
43
+ posts: Array<PostCall>;
44
+ setResponse: (response: unknown) => void;
45
+ setRejection: (error: Error | null) => void;
46
+ }
47
+
48
+ /*
49
+ * Load Captcha against one environment configuration, with axios stubbed. The
50
+ * real EnvironmentConfig is spread in first so only the two captcha values
51
+ * differ from production — mocking the module wholesale would quietly blank
52
+ * every other setting the import graph reads.
53
+ */
54
+ function loadCaptcha(config: {
55
+ captchaEnabled: boolean;
56
+ captchaSecretKey: string;
57
+ }): LoadedCaptcha {
58
+ const posts: Array<PostCall> = [];
59
+ let response: unknown = { data: { success: true } };
60
+ let rejection: Error | null = null;
61
+
62
+ let loaded: CaptchaModule["default"] | null = null;
63
+
64
+ jest.isolateModules((): void => {
65
+ jest.doMock("../../../Server/EnvironmentConfig", (): unknown => {
66
+ return {
67
+ ...(jest.requireActual("../../../Server/EnvironmentConfig") as Record<
68
+ string,
69
+ unknown
70
+ >),
71
+ CaptchaEnabled: config.captchaEnabled,
72
+ CaptchaSecretKey: config.captchaSecretKey,
73
+ };
74
+ });
75
+
76
+ jest.doMock("axios", (): unknown => {
77
+ const post: unknown = (url: string, body: string): Promise<unknown> => {
78
+ posts.push({ url, body });
79
+
80
+ if (rejection) {
81
+ return Promise.reject(rejection);
82
+ }
83
+
84
+ return Promise.resolve(response);
85
+ };
86
+
87
+ return {
88
+ __esModule: true,
89
+ default: {
90
+ post,
91
+ isAxiosError: (): boolean => {
92
+ return false;
93
+ },
94
+ },
95
+ post,
96
+ isAxiosError: (): boolean => {
97
+ return false;
98
+ },
99
+ };
100
+ });
101
+
102
+ /*
103
+ * requireActual, not require: it loads Captcha itself unmocked while its
104
+ * own imports - the two doMock calls above - still resolve through this
105
+ * isolated registry, which is exactly the split these tests need.
106
+ */
107
+ loaded = (
108
+ jest.requireActual("../../../Server/Utils/Captcha") as CaptchaModule
109
+ ).default;
110
+ });
111
+
112
+ return {
113
+ captcha: loaded!,
114
+ posts,
115
+ setResponse: (next: unknown): void => {
116
+ response = next;
117
+ },
118
+ setRejection: (next: Error | null): void => {
119
+ rejection = next;
120
+ },
121
+ };
122
+ }
123
+
124
+ beforeEach((): void => {
125
+ jest.resetModules();
126
+ });
127
+
128
+ /*
129
+ * Assert a rejection is a BadDataException carrying `message`.
130
+ *
131
+ * By constructor NAME, not identity. Each configuration above is loaded through
132
+ * jest.isolateModules, which gives the module under test its own registry — so
133
+ * the BadDataException it throws is a different class object from the one this
134
+ * file would import, and `toThrow(BadDataException)` fails on two constructors
135
+ * that print the same name. The name and the message are what the API surface
136
+ * actually depends on.
137
+ */
138
+ async function expectBadDataRejection(
139
+ work: Promise<void>,
140
+ message: string | RegExp,
141
+ ): Promise<void> {
142
+ let thrown: unknown = null;
143
+
144
+ try {
145
+ await work;
146
+ } catch (err) {
147
+ thrown = err;
148
+ }
149
+
150
+ expect(thrown).toBeInstanceOf(Error);
151
+ expect((thrown as Error).constructor.name).toBe("BadDataException");
152
+
153
+ if (message instanceof RegExp) {
154
+ expect((thrown as Error).message).toMatch(message);
155
+ } else {
156
+ expect((thrown as Error).message).toBe(message);
157
+ }
158
+ }
159
+
160
+ const GENERIC_ERROR_MESSAGE: string =
161
+ "Captcha verification failed. Please try again.";
162
+
163
+ describe("CaptchaUtil.isCaptchaEnabled", () => {
164
+ it("is on only when the feature flag and a secret key agree", () => {
165
+ expect(
166
+ loadCaptcha({
167
+ captchaEnabled: true,
168
+ captchaSecretKey: "a-secret",
169
+ }).captcha.isCaptchaEnabled(),
170
+ ).toBe(true);
171
+ });
172
+
173
+ it("is off when the flag is off", () => {
174
+ expect(
175
+ loadCaptcha({
176
+ captchaEnabled: false,
177
+ captchaSecretKey: "a-secret",
178
+ }).captcha.isCaptchaEnabled(),
179
+ ).toBe(false);
180
+ });
181
+
182
+ it("is off when the flag is on but no secret key is configured", () => {
183
+ /*
184
+ * A half-configured deployment must report itself as off, so the UI does
185
+ * not render a widget whose answer can never be checked.
186
+ */
187
+ expect(
188
+ loadCaptcha({
189
+ captchaEnabled: true,
190
+ captchaSecretKey: "",
191
+ }).captcha.isCaptchaEnabled(),
192
+ ).toBe(false);
193
+ });
194
+ });
195
+
196
+ describe("CaptchaUtil.verifyCaptcha when captcha is switched off", () => {
197
+ it("lets the request through without calling the provider", async () => {
198
+ const loaded: LoadedCaptcha = loadCaptcha({
199
+ captchaEnabled: false,
200
+ captchaSecretKey: "a-secret",
201
+ });
202
+
203
+ await expect(
204
+ loaded.captcha.verifyCaptcha({ token: null }),
205
+ ).resolves.toBeUndefined();
206
+
207
+ // No outbound call at all — an off switch must not cost a round trip.
208
+ expect(loaded.posts).toHaveLength(0);
209
+ });
210
+ });
211
+
212
+ describe("CaptchaUtil.verifyCaptcha when captcha is on", () => {
213
+ it("resolves when the provider says the challenge was solved", async () => {
214
+ const loaded: LoadedCaptcha = loadCaptcha({
215
+ captchaEnabled: true,
216
+ captchaSecretKey: "a-secret",
217
+ });
218
+
219
+ await expect(
220
+ loaded.captcha.verifyCaptcha({ token: "solved-token" }),
221
+ ).resolves.toBeUndefined();
222
+
223
+ expect(loaded.posts).toHaveLength(1);
224
+ expect(loaded.posts[0]!.url).toBe(SITEVERIFY_URL);
225
+ });
226
+
227
+ it("sends the secret and the token the visitor supplied", async () => {
228
+ const loaded: LoadedCaptcha = loadCaptcha({
229
+ captchaEnabled: true,
230
+ captchaSecretKey: "a-secret",
231
+ });
232
+
233
+ await loaded.captcha.verifyCaptcha({ token: "solved-token" });
234
+
235
+ const body: URLSearchParams = new URLSearchParams(loaded.posts[0]!.body);
236
+
237
+ expect(body.get("secret")).toBe("a-secret");
238
+ expect(body.get("response")).toBe("solved-token");
239
+ });
240
+
241
+ it("forwards the caller's IP when one is known", async () => {
242
+ const loaded: LoadedCaptcha = loadCaptcha({
243
+ captchaEnabled: true,
244
+ captchaSecretKey: "a-secret",
245
+ });
246
+
247
+ await loaded.captcha.verifyCaptcha({
248
+ token: "solved-token",
249
+ remoteIp: "203.0.113.7",
250
+ });
251
+
252
+ expect(new URLSearchParams(loaded.posts[0]!.body).get("remoteip")).toBe(
253
+ "203.0.113.7",
254
+ );
255
+ });
256
+
257
+ it("omits remoteip rather than sending an empty one", async () => {
258
+ /*
259
+ * hCaptcha scores a blank remoteip differently from an absent one, so a
260
+ * request with no known client IP must leave the field off entirely.
261
+ */
262
+ const loaded: LoadedCaptcha = loadCaptcha({
263
+ captchaEnabled: true,
264
+ captchaSecretKey: "a-secret",
265
+ });
266
+
267
+ await loaded.captcha.verifyCaptcha({ token: "solved-token", remoteIp: "" });
268
+
269
+ expect(new URLSearchParams(loaded.posts[0]!.body).has("remoteip")).toBe(
270
+ false,
271
+ );
272
+ });
273
+
274
+ it("trims the token before sending it", async () => {
275
+ const loaded: LoadedCaptcha = loadCaptcha({
276
+ captchaEnabled: true,
277
+ captchaSecretKey: "a-secret",
278
+ });
279
+
280
+ await loaded.captcha.verifyCaptcha({ token: " solved-token " });
281
+
282
+ expect(new URLSearchParams(loaded.posts[0]!.body).get("response")).toBe(
283
+ "solved-token",
284
+ );
285
+ });
286
+ });
287
+
288
+ describe("CaptchaUtil.verifyCaptcha fails closed", () => {
289
+ it("rejects when enabled with no secret key, and never calls the provider", async () => {
290
+ /*
291
+ * The misconfiguration that would otherwise fail OPEN: no key means no
292
+ * verification is possible, and "cannot verify" has to mean "reject".
293
+ */
294
+ const loaded: LoadedCaptcha = loadCaptcha({
295
+ captchaEnabled: true,
296
+ captchaSecretKey: "",
297
+ });
298
+
299
+ await expectBadDataRejection(
300
+ loaded.captcha.verifyCaptcha({ token: "solved-token" }),
301
+ GENERIC_ERROR_MESSAGE,
302
+ );
303
+
304
+ expect(loaded.posts).toHaveLength(0);
305
+ });
306
+
307
+ it.each([
308
+ ["null", null],
309
+ ["undefined", undefined],
310
+ ["empty", ""],
311
+ ["whitespace only", " "],
312
+ ])(
313
+ "rejects a %s token without calling the provider",
314
+ async (_label: string, token: string | null | undefined) => {
315
+ const loaded: LoadedCaptcha = loadCaptcha({
316
+ captchaEnabled: true,
317
+ captchaSecretKey: "a-secret",
318
+ });
319
+
320
+ await expectBadDataRejection(
321
+ loaded.captcha.verifyCaptcha({ token }),
322
+ /complete the verification challenge/i,
323
+ );
324
+
325
+ expect(loaded.posts).toHaveLength(0);
326
+ },
327
+ );
328
+
329
+ it("names the missing challenge, since that one is the visitor's to fix", async () => {
330
+ const loaded: LoadedCaptcha = loadCaptcha({
331
+ captchaEnabled: true,
332
+ captchaSecretKey: "a-secret",
333
+ });
334
+
335
+ await expectBadDataRejection(
336
+ loaded.captcha.verifyCaptcha({ token: "" }),
337
+ /complete the verification challenge/i,
338
+ );
339
+ });
340
+
341
+ it("rejects when the provider answers success: false", async () => {
342
+ const loaded: LoadedCaptcha = loadCaptcha({
343
+ captchaEnabled: true,
344
+ captchaSecretKey: "a-secret",
345
+ });
346
+
347
+ loaded.setResponse({
348
+ data: { success: false, "error-codes": ["invalid-input-response"] },
349
+ });
350
+
351
+ await expectBadDataRejection(
352
+ loaded.captcha.verifyCaptcha({ token: "forged-token" }),
353
+ GENERIC_ERROR_MESSAGE,
354
+ );
355
+ });
356
+
357
+ it("rejects when the provider answers with no success field at all", async () => {
358
+ // A shape change at the provider must not read as a pass.
359
+ const loaded: LoadedCaptcha = loadCaptcha({
360
+ captchaEnabled: true,
361
+ captchaSecretKey: "a-secret",
362
+ });
363
+
364
+ loaded.setResponse({ data: {} });
365
+
366
+ await expectBadDataRejection(
367
+ loaded.captcha.verifyCaptcha({ token: "some-token" }),
368
+ GENERIC_ERROR_MESSAGE,
369
+ );
370
+ });
371
+
372
+ it("rejects when the provider answers with no body", async () => {
373
+ const loaded: LoadedCaptcha = loadCaptcha({
374
+ captchaEnabled: true,
375
+ captchaSecretKey: "a-secret",
376
+ });
377
+
378
+ loaded.setResponse({ data: null });
379
+
380
+ await expectBadDataRejection(
381
+ loaded.captcha.verifyCaptcha({ token: "some-token" }),
382
+ GENERIC_ERROR_MESSAGE,
383
+ );
384
+ });
385
+
386
+ it("rejects when the provider is unreachable", async () => {
387
+ /*
388
+ * An hCaptcha outage is the moment a fail-open bug would be exploited, and
389
+ * the moment nobody is watching for one.
390
+ */
391
+ const loaded: LoadedCaptcha = loadCaptcha({
392
+ captchaEnabled: true,
393
+ captchaSecretKey: "a-secret",
394
+ });
395
+
396
+ loaded.setRejection(new Error("connect ETIMEDOUT"));
397
+
398
+ await expectBadDataRejection(
399
+ loaded.captcha.verifyCaptcha({ token: "some-token" }),
400
+ GENERIC_ERROR_MESSAGE,
401
+ );
402
+ });
403
+
404
+ it("does not leak the provider's error text to the visitor", async () => {
405
+ /*
406
+ * The message reaches an anonymous caller, so it says only that
407
+ * verification failed — not which secret, provider or error code was
408
+ * involved.
409
+ */
410
+ const loaded: LoadedCaptcha = loadCaptcha({
411
+ captchaEnabled: true,
412
+ captchaSecretKey: "a-secret",
413
+ });
414
+
415
+ loaded.setRejection(new Error("secret a-secret rejected by upstream"));
416
+
417
+ await expectBadDataRejection(
418
+ loaded.captcha.verifyCaptcha({ token: "some-token" }),
419
+ GENERIC_ERROR_MESSAGE,
420
+ );
421
+ });
422
+ });