@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.
- package/Models/AnalyticsModels/Span.ts +14 -0
- package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
- package/Models/DatabaseModels/Index.ts +10 -0
- package/Models/DatabaseModels/Monitor.ts +76 -0
- package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
- package/Models/DatabaseModels/NetworkDevice.ts +176 -1
- package/Models/DatabaseModels/NetworkSite.ts +201 -2
- package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
- package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
- package/Models/DatabaseModels/TelemetryException.ts +119 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
- package/Server/API/EnterpriseLicenseAPI.ts +391 -64
- package/Server/API/LlmProviderAPI.ts +137 -22
- package/Server/EnvironmentConfig.ts +14 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
- package/Server/Infrastructure/QueueWorker.ts +38 -8
- package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
- package/Server/Middleware/ProjectAuthorization.ts +11 -0
- package/Server/Middleware/SCIMAuthorization.ts +12 -0
- package/Server/Middleware/TelemetryIngest.ts +11 -0
- package/Server/Services/AIBillingService.ts +101 -27
- package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
- package/Server/Services/EnterpriseLicenseService.ts +55 -0
- package/Server/Services/Index.ts +10 -0
- package/Server/Services/MonitorService.ts +143 -21
- package/Server/Services/MonitorStatusTimelineService.ts +150 -8
- package/Server/Services/MonitorTemplateService.ts +217 -1
- package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
- package/Server/Services/NetworkAlertPolicyService.ts +944 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +9 -10
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
- package/Server/Services/NetworkDeviceService.ts +1032 -73
- package/Server/Services/NetworkSiteService.ts +1502 -129
- package/Server/Services/NetworkSiteTypeService.ts +1216 -0
- package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
- package/Server/Services/NotificationService.ts +118 -28
- package/Server/Services/ProjectService.ts +105 -48
- package/Server/Services/StatusPagePrivateUserService.ts +103 -3
- package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
- package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
- package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
- package/Server/Services/UserNotificationSettingService.ts +62 -25
- package/Server/Services/UserService.ts +95 -0
- package/Server/Types/Database/QueryHelper.ts +2 -2
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
- package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
- package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
- package/Server/Utils/DataSource/HttpFetch.ts +9 -2
- package/Server/Utils/EmailRollup/EmailRollupConstants.ts +98 -0
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +872 -0
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
- package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
- package/Server/Utils/LLM/LLMService.ts +78 -0
- package/Server/Utils/LogRedaction.ts +8 -0
- package/Server/Utils/Logger.ts +79 -1
- package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
- package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +49 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +43 -0
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
- package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
- package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
- package/Server/Utils/OutboundUserAgent.ts +152 -0
- package/Server/Utils/StartServer.ts +51 -19
- package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
- package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
- package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
- package/Server/Utils/Telemetry.ts +198 -51
- package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
- package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +134 -33
- package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
- package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +18 -9
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
- package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
- package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
- package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
- package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
- package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +41 -5
- package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
- package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
- package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
- package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
- package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
- package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
- package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
- package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
- package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
- package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
- package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
- package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
- package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
- package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
- package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
- package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
- package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
- package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
- package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
- package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
- package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +47 -4
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
- package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
- package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
- package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
- package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
- package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
- package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
- package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
- package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
- package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
- package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
- package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
- package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
- package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
- package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
- package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
- package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +102 -1
- package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
- package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
- package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
- package/Tests/Server/Utils/Captcha.test.ts +422 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
- package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +752 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
- package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
- package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
- package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
- package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
- package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
- package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
- package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
- package/Tests/Server/Utils/Telemetry.test.ts +456 -66
- package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
- package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
- package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
- package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
- package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
- package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
- package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
- package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
- package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
- package/Tests/UI/Components/SideMenuItem.test.tsx +226 -4
- package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
- package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
- package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
- package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
- package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
- package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
- package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
- package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
- package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
- package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
- package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
- package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
- package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
- package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
- package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
- package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
- package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
- package/Types/AI/ExceptionAIClassification.ts +10 -24
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
- package/Types/Exception/ApiException.ts +10 -0
- package/Types/Exception/BadDataException.ts +11 -0
- package/Types/Exception/BadRequestException.ts +11 -0
- package/Types/Exception/Exception.ts +65 -0
- package/Types/Exception/ForbiddenException.ts +10 -0
- package/Types/Exception/NotAuthenticatedException.ts +10 -0
- package/Types/Exception/NotAuthorizedException.ts +10 -0
- package/Types/Exception/NotFoundException.ts +11 -0
- package/Types/Exception/PayloadTooLargeException.ts +11 -0
- package/Types/Exception/PaymentRequiredException.ts +10 -0
- package/Types/Exception/ServiceUnavailableException.ts +10 -0
- package/Types/Exception/SsoAuthorizationException.ts +10 -0
- package/Types/Exception/TenantNotFoundException.ts +11 -0
- package/Types/Exception/TimeoutException.ts +10 -0
- package/Types/Exception/TooManyRequestsException.ts +10 -0
- package/Types/Exception/UnableToReachServer.ts +10 -0
- package/Types/Exception/WebsiteRequestException.ts +10 -0
- package/Types/Monitor/CriteriaFilter.ts +60 -2
- package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
- package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
- package/Types/Monitor/MonitorMetricType.ts +71 -0
- package/Types/Monitor/MonitorStep.ts +76 -0
- package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
- package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
- package/Types/Monitor/MonitorType.ts +47 -1
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
- package/Types/Monitor/SqlConnectionConfig.ts +31 -0
- package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
- package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
- package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
- package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
- package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
- package/Types/Permission.ts +90 -0
- package/Types/Probe/ProbeMonitorResponse.ts +16 -0
- package/Types/Telemetry/ErrorClass.ts +274 -0
- package/Types/Telemetry/UnitOfWork.ts +59 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
- package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
- package/UI/Components/Modal/Modal.tsx +2 -8
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
- package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
- package/UI/Components/SideMenu/SideMenu.tsx +123 -5
- package/UI/Components/SideMenu/SideMenuItem.tsx +76 -84
- package/UI/Components/SideMenu/SideMenuSection.tsx +55 -23
- package/UI/Components/SideOver/SideOver.tsx +21 -20
- package/UI/Utils/PageScrollLock.ts +79 -3
- package/UI/Utils/PermissionGate.ts +61 -0
- package/UI/Utils/SensitiveUrlToken.ts +112 -0
- package/UI/Utils/TestLLMProvider.ts +11 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
- package/Utils/Monitor/MonitorMetricType.ts +153 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +23 -3
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
- package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
- package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
- package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
- package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
- package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
- package/build/dist/Models/AnalyticsModels/Span.js +14 -0
- package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +10 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +180 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/LlmProviderAPI.js +108 -13
- package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +12 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/QueueWorker.js +33 -5
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
- package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +11 -0
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIBillingService.js +70 -16
- package/build/dist/Server/Services/AIBillingService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +10 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +119 -21
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +10 -9
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
- package/build/dist/Server/Services/NotificationService.js +80 -17
- package/build/dist/Server/Services/NotificationService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +66 -30
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js +46 -20
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +90 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +91 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +691 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
- package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +8 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Logger.js +63 -1
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +37 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
- package/build/dist/Server/Utils/StartServer.js +38 -14
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +162 -46
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
- package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
- package/build/dist/Types/Exception/ApiException.js +9 -0
- package/build/dist/Types/Exception/ApiException.js.map +1 -1
- package/build/dist/Types/Exception/BadDataException.js +10 -0
- package/build/dist/Types/Exception/BadDataException.js.map +1 -1
- package/build/dist/Types/Exception/BadRequestException.js +10 -0
- package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
- package/build/dist/Types/Exception/Exception.js +56 -0
- package/build/dist/Types/Exception/Exception.js.map +1 -1
- package/build/dist/Types/Exception/ForbiddenException.js +9 -0
- package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
- package/build/dist/Types/Exception/NotFoundException.js +10 -0
- package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
- package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
- package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
- package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
- package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
- package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
- package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
- package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
- package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
- package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/TimeoutException.js +9 -0
- package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
- package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
- package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
- package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
- package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
- package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +54 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +45 -1
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
- package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
- package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
- package/build/dist/Types/Permission.js +80 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
- package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +2 -7
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -7
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +67 -5
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js +49 -53
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js +25 -7
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Utils/PageScrollLock.js +31 -3
- package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
- package/build/dist/UI/Utils/PermissionGate.js +42 -1
- package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
- package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
- package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
- package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
- package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +8 -3
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
- 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
|
+
});
|