@oneuptime/common 13.0.5 → 13.0.6
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/AuditLog.ts +81 -1
- package/Models/AnalyticsModels/SecurityEvent.ts +4 -4
- package/Models/DatabaseModels/Alert.ts +62 -0
- package/Models/DatabaseModels/GlobalConfig.ts +1 -1
- package/Models/DatabaseModels/Incident.ts +66 -0
- package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +74 -0
- package/Models/DatabaseModels/IncidentPublicNote.ts +74 -0
- package/Models/DatabaseModels/Index.ts +6 -4
- package/Models/DatabaseModels/NetworkDevice.ts +67 -0
- package/Models/DatabaseModels/NetworkDeviceDiagnostic.ts +746 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +151 -0
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +1 -1
- package/Models/DatabaseModels/Project.ts +41 -0
- package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +74 -0
- package/Models/DatabaseModels/SecurityEventConnection.ts +11 -11
- package/Models/DatabaseModels/ServiceLevelObjective.ts +185 -8
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +746 -43
- package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +575 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +582 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +16 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +16 -0
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +75 -0
- package/Models/DatabaseModels/ThreatIntelFeed.ts +1 -1
- package/Server/API/BaseAPI.ts +17 -0
- package/Server/API/BillingInvoiceAPI.ts +343 -30
- package/Server/API/BillingPaymentMethodAPI.ts +126 -5
- package/Server/API/DashboardAPI.ts +96 -2
- package/Server/API/SecurityEventConnectionAPI.ts +141 -11
- package/Server/API/StatusPageAPI.ts +308 -199
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.ts +83 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.ts +36 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.ts +516 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.ts +98 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.ts +97 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
- package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +138 -67
- package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +213 -84
- package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +112 -35
- package/Server/Services/AlertLabelRuleEngineService.ts +299 -217
- package/Server/Services/AlertOwnerRuleEngineService.ts +572 -396
- package/Server/Services/AlertPrivacyRuleEngineService.ts +116 -40
- package/Server/Services/AlertService.ts +111 -4
- package/Server/Services/AuditLogService.ts +612 -59
- package/Server/Services/BillingInvoiceService.ts +112 -102
- package/Server/Services/BillingService.ts +539 -11
- package/Server/Services/CephClusterLabelRuleEngineService.ts +170 -109
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +233 -115
- package/Server/Services/CloudResourceLabelRuleEngineService.ts +163 -100
- package/Server/Services/CloudResourceOwnerRuleEngineService.ts +236 -115
- package/Server/Services/DashboardLabelRuleEngineService.ts +145 -84
- package/Server/Services/DashboardOwnerRuleEngineService.ts +213 -95
- package/Server/Services/DatabaseService.ts +171 -21
- package/Server/Services/DockerHostLabelRuleEngineService.ts +171 -110
- package/Server/Services/DockerHostOwnerRuleEngineService.ts +233 -115
- package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +181 -112
- package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +243 -118
- package/Server/Services/HostLabelRuleEngineService.ts +167 -106
- package/Server/Services/HostOwnerRuleEngineService.ts +229 -111
- package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +141 -67
- package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +272 -72
- package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +112 -35
- package/Server/Services/IncidentEpisodePublicNoteService.ts +24 -0
- package/Server/Services/IncidentLabelRuleEngineService.ts +279 -204
- package/Server/Services/IncidentOwnerRuleEngineService.ts +595 -425
- package/Server/Services/IncidentPrivacyRuleEngineService.ts +117 -44
- package/Server/Services/IncidentPublicNoteService.ts +24 -0
- package/Server/Services/IncidentService.ts +114 -3
- package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +147 -83
- package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +221 -100
- package/Server/Services/Index.ts +6 -4
- package/Server/Services/IoTFleetLabelRuleEngineService.ts +145 -84
- package/Server/Services/IoTFleetOwnerRuleEngineService.ts +213 -95
- package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +181 -112
- package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +243 -118
- package/Server/Services/LabelService.ts +23 -28
- package/Server/Services/MonitorLabelRuleEngineService.ts +152 -92
- package/Server/Services/MonitorOwnerRuleEngineService.ts +220 -104
- package/Server/Services/MonitorProbeService.ts +20 -2
- package/Server/Services/MonitorService.ts +11 -9
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +376 -5
- package/Server/Services/NetworkDeviceDiagnosticService.ts +417 -0
- package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +147 -83
- package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +218 -97
- package/Server/Services/NetworkDeviceService.ts +39 -2
- package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +151 -80
- package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +222 -97
- package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +154 -83
- package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +225 -100
- package/Server/Services/PodmanHostLabelRuleEngineService.ts +171 -110
- package/Server/Services/PodmanHostOwnerRuleEngineService.ts +235 -115
- package/Server/Services/ProjectService.ts +111 -10
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +174 -110
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +239 -116
- package/Server/Services/RumApplicationLabelRuleEngineService.ts +137 -73
- package/Server/Services/RumApplicationOwnerRuleEngineService.ts +200 -83
- package/Server/Services/RunbookLabelRuleEngineService.ts +146 -84
- package/Server/Services/RunbookOwnerRuleEngineService.ts +216 -95
- package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +324 -230
- package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +613 -428
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +24 -0
- package/Server/Services/ScheduledMaintenanceService.ts +43 -14
- package/Server/Services/SecurityEventConnectionService.ts +56 -4
- package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +143 -74
- package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +206 -85
- package/Server/Services/ServiceLabelRuleEngineService.ts +172 -110
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +1057 -18
- package/Server/Services/ServiceLevelObjectiveFeedService.ts +108 -0
- package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +793 -97
- package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +1069 -0
- package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +240 -1
- package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +257 -1
- package/Server/Services/ServiceLevelObjectiveService.ts +1356 -56
- package/Server/Services/ServiceOwnerRuleEngineService.ts +238 -116
- package/Server/Services/StatusPageAnnouncementService.ts +13 -0
- package/Server/Services/StatusPageLabelRuleEngineService.ts +146 -85
- package/Server/Services/StatusPageOwnerRuleEngineService.ts +210 -99
- package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +28 -232
- package/Server/Services/StatusPageSubscriberService.ts +6 -0
- package/Server/Services/TelemetryUsageBillingService.ts +38 -7
- package/Server/Services/ThreatIntelFeedService.ts +1 -1
- package/Server/Services/VMwareVCenterLabelRuleEngineService.ts +173 -110
- package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +238 -116
- package/Server/Services/WorkflowLabelRuleEngineService.ts +145 -84
- package/Server/Services/WorkflowOwnerRuleEngineService.ts +215 -95
- package/Server/Types/Database/UpdateByID.ts +3 -0
- package/Server/Types/Database/UpdateOneBy.ts +7 -0
- package/Server/Utils/AI/AlertAIContextBuilder.ts +19 -0
- package/Server/Utils/AI/IncidentAIContextBuilder.ts +39 -0
- package/Server/Utils/AI/Toolbox/AlertTools.ts +37 -1
- package/Server/Utils/AI/Toolbox/IncidentTools.ts +22 -1
- package/Server/Utils/AI/Toolbox/SloTools.ts +416 -51
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +151 -13
- package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +17 -4
- package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +155 -8
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +16 -0
- package/Server/Utils/Database/RelationValueUtil.ts +106 -0
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +6 -1
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +22 -27
- package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +3 -1
- package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +50 -20
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +13 -1
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +6 -11
- package/Server/Utils/Rules/MonitorRulePatternValidator.ts +51 -0
- package/Server/Utils/Rules/OwnerRuleAssignment.ts +110 -0
- package/Server/Utils/Rules/RuleRun/RuleApplication.ts +81 -0
- package/Server/Utils/Rules/RuleRun/RuleRunPermission.ts +188 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +803 -0
- package/Server/Utils/Rules/RuleRun/RuleRunner.ts +341 -0
- package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +3 -2
- package/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.ts +6 -4
- package/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.ts +263 -16
- package/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.ts +2101 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.ts +194 -14
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.ts +1 -2
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.ts +38 -7
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.ts +2 -0
- package/Server/Utils/SecurityEvent/Connectors/Types.ts +242 -2
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +1 -1
- package/Server/Utils/SecurityEvent/SecurityEventDedupe.ts +3 -3
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +2 -2
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +217 -56
- package/Server/Utils/Slo/SloFeedUtil.ts +200 -0
- package/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.ts +173 -0
- package/Server/Utils/Slo/SloMetricUtil.ts +327 -0
- package/Server/Utils/Slo/SloOwnerReferenceValidator.ts +208 -0
- package/Server/Utils/Slo/SloRecordReferenceValidator.ts +169 -0
- package/Server/Utils/StatusPage/MonitorRulePatternValidator.ts +6 -43
- package/Server/Utils/StatusPageResource.ts +50 -5
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +664 -15
- package/Tests/App/Dashboard/AddWidgetModal.test.tsx +4 -1
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +307 -0
- package/Tests/App/Dashboard/ArchiveResourceCard.test.tsx +289 -0
- package/Tests/App/Dashboard/AuditLogsTable.test.tsx +598 -0
- package/Tests/App/Dashboard/BillingDefaultPaymentMethod.test.tsx +1046 -0
- package/Tests/App/Dashboard/BillingPaidUsageFlow.test.tsx +3 -0
- package/Tests/App/Dashboard/BillingPaymentMethodForm.test.tsx +201 -7
- package/Tests/App/Dashboard/BooleanSeriesCriteriaFilterText.test.ts +82 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +16 -1
- package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +116 -8
- package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +168 -1
- package/Tests/App/Dashboard/ConnectionTestModal.test.tsx +1 -1
- package/Tests/App/Dashboard/ConnectorTestReportView.test.tsx +20 -3
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +1095 -1
- package/Tests/App/Dashboard/CorrelateFilterChips.test.tsx +910 -0
- package/Tests/App/Dashboard/CorrelateGraph.test.tsx +3747 -25
- package/Tests/App/Dashboard/CorrelateGraphHelpers.test.ts +1085 -0
- package/Tests/App/Dashboard/CorrelateInspector.test.tsx +1534 -0
- package/Tests/App/Dashboard/CorrelateNodeCard.test.tsx +965 -0
- package/Tests/App/Dashboard/CorrelateResultSummary.test.tsx +1525 -0
- package/Tests/App/Dashboard/CorrelationGraph.test.ts +1030 -0
- package/Tests/App/Dashboard/CorrelationGraphLayout.test.ts +526 -0
- package/Tests/App/Dashboard/DeviceDiagnostics.test.tsx +787 -0
- package/Tests/App/Dashboard/DeviceLatencyTrend.test.tsx +278 -0
- package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +279 -0
- package/Tests/App/Dashboard/DiscoveryScanEditForm.test.tsx +87 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +443 -8
- package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +340 -0
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +98 -2
- package/Tests/App/Dashboard/ExceptionSegmentedControl.test.tsx +1020 -0
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +268 -47
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1114 -76
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +124 -2
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +279 -176
- package/Tests/App/Dashboard/InvestigationRunDetails.test.tsx +1166 -0
- package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +437 -0
- package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +65 -0
- package/Tests/App/Dashboard/NetworkTopologyLiveView.test.tsx +5 -0
- package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +74 -0
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +125 -5
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +1764 -0
- package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +1000 -64
- package/Tests/App/Dashboard/SecurityEventConnectionsEmptyState.test.tsx +448 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +739 -189
- package/Tests/App/Dashboard/SecurityEventSeverityPill.test.tsx +233 -0
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +282 -0
- package/Tests/App/Dashboard/SloActiveBurnEventsCard.test.tsx +538 -0
- package/Tests/App/Dashboard/SloBulkActionsArchive.test.tsx +252 -0
- package/Tests/App/Dashboard/SloDashboardTemplateWidgets.test.tsx +322 -518
- package/Tests/App/Dashboard/SloElement.test.tsx +194 -0
- package/Tests/App/Dashboard/SloFeed.test.tsx +289 -0
- package/Tests/App/Dashboard/SloHistoryCharts.test.tsx +471 -0
- package/Tests/App/Dashboard/SloHistorySeries.test.tsx +607 -0
- package/Tests/App/Dashboard/SloListWidget.test.tsx +783 -0
- package/Tests/App/Dashboard/SloMetricsPage.test.tsx +346 -0
- package/Tests/App/Dashboard/SloMonitorsPage.test.tsx +661 -0
- package/Tests/App/Dashboard/SloMonitorsSummaryCard.test.tsx +489 -0
- package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +437 -0
- package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +305 -0
- package/Tests/App/Dashboard/SloOverviewData.test.tsx +563 -0
- package/Tests/App/Dashboard/SloOverviewHero.test.tsx +311 -0
- package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +426 -0
- package/Tests/App/Dashboard/SloOverviewSidebarCards.test.tsx +493 -0
- package/Tests/App/Dashboard/SloSettings.test.tsx +633 -0
- package/Tests/App/Dashboard/SloStatusSummaryCards.test.tsx +403 -0
- package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +373 -0
- package/Tests/App/Dashboard/SloWidgetVariableBinding.test.tsx +689 -0
- package/Tests/App/Dashboard/TopologyConnectivitySection.test.tsx +206 -0
- package/Tests/App/Dashboard/TracesEntityNames.test.tsx +47 -15
- package/Tests/App/Dashboard/UseBulkShortenDeviceNames.test.tsx +1312 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +9 -1
- package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +14 -16
- package/Tests/Models/DatabaseModels/AuditLogModelConfiguration.test.ts +442 -0
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +9 -10
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +48 -1
- package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +835 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +3 -2
- package/Tests/Models/DiscoveryScanNetbiosLookupColumn.test.ts +328 -0
- package/Tests/Models/DiscoveryScanShortDeviceNamesColumn.test.ts +335 -0
- package/Tests/Models/NetworkDeviceDiagnosticContract.test.ts +194 -0
- package/Tests/Models/NetworkDeviceDnsNameColumn.test.ts +321 -0
- package/Tests/Models/ProjectDataResidencyColumn.test.ts +154 -0
- package/Tests/Models/SecurityDomainAccessControl.test.ts +181 -50
- package/Tests/Server/API/BaseAPI.test.ts +6 -0
- package/Tests/Server/API/BaseAPIUpdateMiscDataProps.test.ts +217 -0
- package/Tests/Server/API/BillingInvoiceAPI.test.ts +7 -0
- package/Tests/Server/API/BillingInvoiceAPIPaymentStates.test.ts +990 -0
- package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +498 -0
- package/Tests/Server/API/DashboardPublicSloAPI.test.ts +405 -0
- package/Tests/Server/API/SecurityEventConnectionAPI.test.ts +901 -7
- package/Tests/Server/API/SessionReplayAPI.test.ts +116 -0
- package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +857 -0
- package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +1084 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +33 -3
- package/Tests/Server/Infrastructure/Postgres/AddDataResidencyToProjectMigration.test.ts +202 -0
- package/Tests/Server/Infrastructure/Postgres/AddNetbiosLookupToNetworkDeviceDiscoveryScanMigration.test.ts +330 -0
- package/Tests/Server/Infrastructure/Postgres/AddNetworkDeviceDnsNameAndShortDeviceNamesMigration.test.ts +340 -0
- package/Tests/Server/Infrastructure/Postgres/BackfillSloMonitorRulesAndAffectedResourcesMigration.test.ts +343 -0
- package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +801 -0
- package/Tests/Server/Services/AddSubscriberUpdateNotificationStatusMigration.test.ts +307 -0
- package/Tests/Server/Services/AuditLogService.test.ts +1124 -0
- package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +200 -1
- package/Tests/Server/Services/BillingInvoiceServiceMutexRelease.test.ts +254 -0
- package/Tests/Server/Services/BillingService.test.ts +70 -0
- package/Tests/Server/Services/BillingServicePayInvoiceStates.test.ts +723 -0
- package/Tests/Server/Services/BillingServicePaymentMethodReads.test.ts +14 -2
- package/Tests/Server/Services/BillingServiceSubscriptionPaymentMethodSync.test.ts +1634 -0
- package/Tests/Server/Services/DatabaseServiceAuditRelationDiff.test.ts +492 -0
- package/Tests/Server/Services/DatabaseServicePasswordFieldSecrets.test.ts +629 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +431 -0
- package/Tests/Server/Services/IncidentAlertSloReferenceGuard.test.ts +358 -0
- package/Tests/Server/Services/MonitorProbeServicePastDueMonitoring.test.ts +362 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +1460 -1
- package/Tests/Server/Services/NetworkDeviceDiagnosticService.test.ts +962 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +106 -0
- package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +10 -1
- package/Tests/Server/Services/NetworkDeviceServicePastDueMonitoring.test.ts +335 -0
- package/Tests/Server/Services/NetworkDeviceSiteRuleDnsName.test.ts +568 -0
- package/Tests/Server/Services/ProjectDataResidencyPostgres.test.ts +344 -0
- package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +187 -0
- package/Tests/Server/Services/ProjectServiceDataResidency.test.ts +369 -0
- package/Tests/Server/Services/ProjectServiceDataResidencySelfHosted.test.ts +176 -0
- package/Tests/Server/Services/ProjectServicePastDueMonitoring.test.ts +289 -0
- package/Tests/Server/Services/ResourceFeedServices.test.ts +24 -8
- package/Tests/Server/Services/RuleRun/IncidentAlertMaintenanceRuleEnginesRun.test.ts +1396 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupARun.test.ts +917 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +1262 -0
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupARun.test.ts +902 -0
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +1163 -0
- package/Tests/Server/Services/RuleRun/PrivacyRuleEnginesRun.test.ts +843 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +465 -0
- package/Tests/Server/Services/SecurityEventConnectionService.test.ts +525 -4
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +77 -23
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleFeedWrites.test.ts +777 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleOptions.test.ts +1399 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +67 -74
- package/Tests/Server/Services/ServiceLevelObjectiveChildRowTenancy.test.ts +906 -0
- package/Tests/Server/Services/ServiceLevelObjectiveDeleteTenancy.test.ts +1029 -0
- package/Tests/Server/Services/ServiceLevelObjectiveFeedService.test.ts +313 -0
- package/Tests/Server/Services/ServiceLevelObjectiveFeedWrites.test.ts +1214 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMarkdownLink.test.ts +289 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +1455 -430
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleLegacyLabelAdoption.test.ts +634 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +1193 -0
- package/Tests/Server/Services/{SloMonitorLabelRuleHooks.test.ts → ServiceLevelObjectiveMonitorRuleTriggers.test.ts} +135 -41
- package/Tests/Server/Services/ServiceLevelObjectiveOwnerFeedWrites.test.ts +671 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +180 -85
- package/Tests/Server/Services/ServiceLevelObjectiveServiceArchive.test.ts +537 -0
- package/Tests/Server/Services/ServiceLevelObjectiveServiceLegacyMonitorLabelWrite.test.ts +870 -0
- package/Tests/Server/Services/ServiceLevelObjectiveServiceMonitorRuleGuard.test.ts +343 -0
- package/Tests/Server/Services/ServiceLevelObjectiveServiceReEvaluation.test.ts +246 -0
- package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +501 -0
- package/Tests/Server/Services/SloAffectedResourceLinkContract.test.ts +86 -0
- package/Tests/Server/Services/SloAffectedResourceMetricAttributes.test.ts +547 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +10 -4
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +7 -2
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +174 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateServiceVariables.test.ts +40 -0
- package/Tests/Server/Services/SubscriberUpdateNotificationHooks.test.ts +541 -0
- package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +288 -0
- package/Tests/Server/TestingUtils/PastDueMonitoringClaimSql.ts +177 -0
- package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +51 -10
- package/Tests/Server/TestingUtils/__mocks__/Stripe.mock.ts +16 -1
- package/Tests/Server/Types/Database/Permissions/ProjectDataResidencyColumn.test.ts +386 -0
- package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +26 -36
- package/Tests/Server/Utils/AI/SloAffectedResourceAIContext.test.ts +445 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +423 -1
- package/Tests/Server/Utils/AI/SloToolsArchive.test.ts +294 -0
- package/Tests/Server/Utils/AI/SloToolsRuleReadPermissions.test.ts +297 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +255 -10
- package/Tests/Server/Utils/Dashboard/SloTemplatePublicDashboard.test.ts +404 -750
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +45 -0
- package/Tests/Server/Utils/Database/RelationValueUtil.test.ts +157 -0
- package/Tests/Server/Utils/Monitor/Criteria/BooleanSeriesEvaluateOverTime.test.ts +260 -0
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +181 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +147 -30
- package/Tests/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.test.ts +17 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +136 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidatorLoadOrder.test.ts +472 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +48 -2
- package/Tests/Server/Utils/Monitor/SloTemplateMetricEmitterContract.test.ts +435 -475
- package/Tests/Server/Utils/Rules/MonitorRulePatternValidator.test.ts +77 -0
- package/Tests/Server/Utils/Rules/OwnerRuleAssignment.test.ts +177 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +365 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunRegistry.test.ts +173 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunner.test.ts +675 -0
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +8 -8
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorFetchSummary.test.ts +261 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.test.ts +68 -13
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsAuth.test.ts → Connectors/GoogleSecOps/GoogleSecOpsAuth.test.ts} +5 -5
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsClient.test.ts → Connectors/GoogleSecOps/GoogleSecOpsClient.test.ts} +4 -4
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.test.ts +483 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorCuratedAndLateAlerts.test.ts +676 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorFetchEvents.test.ts +1994 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorFixtures.ts +332 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorHttpIntegration.test.ts +680 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorRequestContract.test.ts +1206 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorTestConnection.test.ts +1136 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsCuratedRuleCounts.test.ts +407 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsErrorHandling.test.ts → Connectors/GoogleSecOps/GoogleSecOpsErrorHandling.test.ts} +5 -5
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingAdaptiveCatchUp.test.ts +730 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsClickhouseIntegration.test.ts → Connectors/GoogleSecOps/GoogleSecOpsPollingClickhouseIntegration.test.ts} +130 -35
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingFailureTaxonomy.test.ts +772 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingFixtures.ts +648 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsHttpIntegration.test.ts → Connectors/GoogleSecOps/GoogleSecOpsPollingHttpIntegration.test.ts} +230 -225
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingIntegration.test.ts +1390 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingLoop.test.ts +981 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingNothingImportedRegression.test.ts +290 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsRequestContract.test.ts → Connectors/GoogleSecOps/GoogleSecOpsRequestContract.test.ts} +2 -2
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsResponseParsing.test.ts → Connectors/GoogleSecOps/GoogleSecOpsResponseParsing.test.ts} +5 -5
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsSearchDetections.test.ts → Connectors/GoogleSecOps/GoogleSecOpsSearchDetections.test.ts} +38 -5
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsTesterIntegration.test.ts +421 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.test.ts +1445 -3
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.test.ts +14 -4
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.test.ts +313 -4
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +352 -0
- package/Tests/Server/Utils/Slo/SloFeedUtil.test.ts +326 -0
- package/Tests/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.test.ts +260 -0
- package/Tests/Server/Utils/Slo/SloMetricUtil.test.ts +592 -0
- package/Tests/Server/Utils/Slo/SloRecordReferenceValidator.test.ts +311 -0
- package/Tests/Server/Utils/StatusPageResource.test.ts +91 -3
- package/Tests/Types/Billing/SubscriptionStatus.test.ts +176 -0
- package/Tests/Types/Billing/SubscriptionStatusPastDueMonitoring.test.ts +187 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +53 -7
- package/Tests/Types/Dashboard/SloDashboardTemplate.test.ts +816 -792
- package/Tests/Types/Monitor/CriteriaFilter.test.ts +216 -24
- package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +14 -1
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +14 -1
- package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +14 -1
- package/Tests/Types/Monitor/MonitorStepRetriesParsing.test.ts +201 -0
- package/Tests/Types/Rules/RuleRun.test.ts +315 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +60 -0
- package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +29 -4
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +217 -0
- package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +200 -0
- package/Tests/UI/Components/ActiveFilterChipsLockedFilters.test.tsx +141 -87
- package/Tests/UI/Components/AlertBanner.test.tsx +319 -0
- package/Tests/UI/Components/BulkArchiveActionsCopy.test.tsx +310 -0
- package/Tests/UI/Components/Detail/DetailIdIsUnique.test.tsx +87 -0
- package/Tests/UI/Components/Dropdown/DropdownClearable.test.tsx +393 -0
- package/Tests/UI/Components/Dropdown/DropdownMultiSelectChipAccessibleName.test.tsx +64 -0
- package/Tests/UI/Components/EmptyState/EmptyState.test.tsx +335 -4
- package/Tests/UI/Components/EmptyState/EmptyStateGuideLinks.test.tsx +337 -0
- package/Tests/UI/Components/Forms/ModelFormJsonColumns.test.tsx +21 -20
- package/Tests/UI/Components/LabelRuleImportExport.test.tsx +15 -2
- package/Tests/UI/Components/LockedFilterChip.test.tsx +281 -144
- package/Tests/UI/Components/MoreMenu.test.tsx +133 -0
- package/Tests/UI/Components/MoreMenuMotion.test.tsx +84 -3
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/RuleRun/RuleDetailFields.test.tsx +336 -0
- package/Tests/UI/Components/RuleRun/RuleTable.test.tsx +304 -0
- package/Tests/UI/Components/RuleRun/RunRuleNowModal.test.tsx +231 -0
- package/Tests/UI/Components/RuleRun/RunRulesBulkAction.test.ts +213 -0
- package/Tests/UI/Components/TelemetryActiveFilterChipsLockedFilters.test.tsx +124 -61
- package/Tests/UI/Rum/ReplayEngine.test.ts +154 -0
- package/Tests/UI/Rum/ReplayHeader.test.tsx +234 -123
- package/Tests/UI/Rum/ReplayPinControl.test.tsx +122 -0
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +245 -0
- package/Tests/UI/Rum/ReplayRail.test.tsx +294 -0
- package/Tests/UI/Rum/ReplayScrubber.test.tsx +213 -1
- package/Tests/UI/Rum/ReplayStage.test.tsx +565 -172
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +260 -3
- package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +1391 -0
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +222 -0
- package/Tests/UI/Utils/DashboardStackingLayers.test.ts +8 -1
- package/Tests/UI/Utils/RuleRunClient.test.ts +303 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +1 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentDefaults.test.ts +2 -0
- package/Tests/Utils/Dashboard/Components/DashboardSloListComponent.test.ts +206 -0
- package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +36 -2
- package/Tests/Utils/Dashboard/SloTemplateVariableScoping.test.ts +409 -588
- package/Tests/Utils/Dashboard/SloWidgetSource.test.ts +351 -0
- package/Tests/Utils/Markdown/MarkdownEscape.test.ts +361 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +1425 -118
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +188 -3
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +661 -13
- package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +349 -0
- package/Tests/Utils/NetworkDiscovery/RunImportedDeviceNaming.test.ts +656 -0
- package/Tests/Utils/NetworkDiscovery/ShortDeviceNamePlanner.test.ts +1020 -0
- package/Tests/Utils/NetworkDiscovery/ShortHostnameUtil.test.ts +619 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +317 -0
- package/Tests/Utils/Project/DataResidency.test.ts +198 -0
- package/Tests/Utils/Rules/RuleRunSummary.test.ts +394 -0
- package/Tests/Utils/Slo/SloAffectedResourceMarkdown.test.ts +302 -0
- package/Tests/Utils/Slo/SloBurnRateTemplate.test.ts +468 -0
- package/Tests/Utils/Slo/SloEvaluation.test.ts +20 -4
- package/Tests/Utils/Slo/SloFeedMarkdown.test.ts +1185 -0
- package/Tests/Utils/Slo/SloHealth.test.ts +262 -0
- package/Tests/Utils/Slo/SloHistoryMetricName.test.ts +102 -0
- package/Tests/Utils/Slo/SloListWidgetFormat.test.ts +522 -0
- package/Tests/Utils/Slo/SloMetricType.test.ts +355 -0
- package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +387 -0
- package/Tests/Utils/Slo/SloMonitorStatusSummary.test.ts +210 -0
- package/Tests/Utils/Slo/SloOverviewText.test.ts +226 -0
- package/Tests/Utils/Slo/SloProjection.test.ts +1039 -0
- package/Tests/Utils/Slo/SloWidgetFormat.test.ts +47 -0
- package/Tests/Utils/Telemetry/LockedFilterSearch.test.ts +1 -80
- package/Types/BaseDatabase/EnableAuditLogOn.ts +41 -0
- package/Types/Billing/SubscriptionStatus.ts +39 -4
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +5 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +10 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloListComponent.ts +29 -0
- package/Types/Dashboard/DashboardTemplates.ts +290 -297
- package/Types/Database/EnableAuditLog.ts +23 -1
- package/Types/Email/EmailTemplateType.ts +4 -0
- package/Types/Monitor/CriteriaFilter.ts +55 -8
- package/Types/Monitor/MonitorStep.ts +5 -2
- package/Types/Monitor/MonitorStepDnsMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepDnssecMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepDomainMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepExternalStatusPageMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepRetries.ts +59 -0
- package/Types/Monitor/MonitorStepSnmpMonitor.ts +9 -2
- package/Types/NetworkDevice/NetworkDeviceDiagnosticResult.ts +104 -0
- package/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.ts +47 -0
- package/Types/NetworkDevice/NetworkDeviceDiagnosticType.ts +47 -0
- package/Types/NetworkDevice/NetworkDevicePingMetricNames.ts +20 -0
- package/Types/Permission.ts +127 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +5 -0
- package/Types/Rules/RuleRun.ts +518 -0
- package/Types/Rum/SessionReplayApi.ts +18 -0
- package/Types/SecurityEvent/Connectors/ConnectorDiagnostics.ts +6 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.ts +30 -4
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +108 -1
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.ts +6 -2
- package/Types/ServiceLevelObjective/SloHistoryMetricName.ts +25 -0
- package/Types/ServiceLevelObjective/SloMetricType.ts +49 -0
- package/Types/StatusPage/StatusPageSubscriberNotificationEventType.ts +4 -0
- package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +331 -0
- package/Types/StatusPage/SubscriberNotificationTrigger.ts +12 -0
- package/Types/StatusPage/SubscriberUpdateNotification.ts +89 -0
- package/Types/Telemetry/LockedFilterDetail.ts +7 -28
- package/Types/Telemetry/ServiceType.ts +7 -0
- package/Typings/Index.d.ts +53 -3
- package/UI/Components/AlertBanner/AlertBanner.tsx +85 -27
- package/UI/Components/BulkUpdate/BulkArchiveActions.tsx +21 -2
- package/UI/Components/Detail/Detail.tsx +9 -2
- package/UI/Components/Dropdown/Dropdown.tsx +64 -1
- package/UI/Components/EmptyState/EmptyState.tsx +27 -3
- package/UI/Components/EmptyState/EmptyStateGuideLinks.tsx +124 -0
- package/UI/Components/Forms/ModelForm.tsx +6 -5
- package/UI/Components/LabelRule/LabelRuleTable.tsx +8 -2
- package/UI/Components/LogsViewer/LogsViewer.tsx +2 -6
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +2 -13
- package/UI/Components/LogsViewer/types.ts +2 -2
- package/UI/Components/MoreMenu/MoreMenu.tsx +14 -3
- package/UI/Components/RuleRun/RuleDetailFields.tsx +359 -0
- package/UI/Components/RuleRun/RuleTable.tsx +183 -0
- package/UI/Components/RuleRun/RuleView.tsx +170 -0
- package/UI/Components/RuleRun/RunRuleNowModal.tsx +147 -0
- package/UI/Components/RuleRun/RunRulesBulkAction.ts +103 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +2 -6
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +38 -104
- package/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.tsx +2 -18
- package/UI/Components/TelemetryViewer/types.ts +2 -2
- package/UI/Utils/Rules/RuleRunClient.ts +178 -0
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +8 -0
- package/Utils/Dashboard/Components/DashboardSloComponent.ts +19 -2
- package/Utils/Dashboard/Components/DashboardSloListComponent.ts +126 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/Dashboard/SloWidgetSource.ts +188 -0
- package/Utils/Markdown/MarkdownEscape.ts +63 -0
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +161 -36
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +25 -0
- package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +146 -0
- package/Utils/NetworkDiscovery/RunImportedDeviceNaming.ts +390 -0
- package/Utils/NetworkDiscovery/ShortDeviceNamePlanner.ts +291 -0
- package/Utils/NetworkDiscovery/ShortHostnameUtil.ts +91 -0
- package/Utils/NetworkSite/CidrMatchUtil.ts +37 -12
- package/Utils/Project/DataResidency.ts +63 -0
- package/Utils/Rules/RuleRunSummary.ts +323 -0
- package/Utils/Slo/SloAffectedResourceMarkdown.ts +123 -0
- package/Utils/Slo/SloBurnRateTemplate.ts +373 -0
- package/Utils/Slo/SloFeedMarkdown.ts +1507 -0
- package/Utils/Slo/SloHealth.ts +96 -9
- package/Utils/Slo/SloListWidgetFormat.ts +370 -0
- package/Utils/Slo/SloMetricType.ts +237 -0
- package/Utils/Slo/SloMonitorRuleCriteria.ts +364 -0
- package/Utils/Slo/SloMonitorStatusSummary.ts +210 -0
- package/Utils/Slo/SloOverviewText.ts +265 -0
- package/Utils/Slo/SloProjection.ts +967 -0
- package/Utils/Slo/SloWidgetFormat.ts +12 -2
- package/Utils/Telemetry/LockedFilterSearch.ts +3 -49
- package/build/dist/Models/AnalyticsModels/AuditLog.js +70 -1
- package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/SecurityEvent.js +4 -4
- package/build/dist/Models/DatabaseModels/Alert.js +60 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +64 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +75 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +75 -0
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +6 -4
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +68 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiagnostic.js +772 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiagnostic.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +140 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +42 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +75 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js +11 -11
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +192 -10
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +798 -96
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +596 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +590 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +16 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +16 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +75 -0
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +1 -1
- package/build/dist/Server/API/BaseAPI.js +14 -0
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/BillingInvoiceAPI.js +233 -19
- package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
- package/build/dist/Server/API/BillingPaymentMethodAPI.js +86 -5
- package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +72 -2
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/SecurityEventConnectionAPI.js +102 -10
- package/build/dist/Server/API/SecurityEventConnectionAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +236 -154
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.js +21 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.js +207 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.js +72 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.js +46 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +112 -56
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +167 -68
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +87 -26
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js +270 -203
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +498 -354
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +97 -34
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +91 -8
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AuditLogService.js +408 -44
- package/build/dist/Server/Services/AuditLogService.js.map +1 -1
- package/build/dist/Server/Services/BillingInvoiceService.js +94 -85
- package/build/dist/Server/Services/BillingInvoiceService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +406 -14
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +135 -86
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +189 -100
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +125 -18
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +145 -91
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +191 -101
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js +190 -102
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +112 -56
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +220 -63
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +87 -26
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +258 -192
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +519 -376
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +95 -32
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +90 -5
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +113 -65
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +6 -4
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +145 -91
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +191 -101
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +20 -25
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +123 -77
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +167 -82
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +18 -2
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +11 -9
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +287 -5
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiagnosticService.js +333 -0
- package/build/dist/Server/Services/NetworkDeviceDiagnosticService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +36 -2
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +117 -64
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +173 -83
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +116 -65
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +82 -10
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +111 -63
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +161 -77
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +280 -209
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +521 -376
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +24 -0
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +24 -8
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/SecurityEventConnectionService.js +43 -3
- package/build/dist/Server/Services/SecurityEventConnectionService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +115 -62
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +163 -77
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +769 -18
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveFeedService.js +96 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveFeedService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +614 -87
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +844 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +207 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +221 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +997 -50
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +191 -102
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageAnnouncementService.js +12 -0
- package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +118 -70
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +158 -76
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +19 -215
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +6 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +27 -5
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/ThreatIntelFeedService.js +1 -1
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js +17 -0
- package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js +31 -0
- package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +24 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +21 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +337 -53
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +108 -15
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +2 -2
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +115 -6
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +13 -0
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/Database/RelationValueUtil.js +82 -0
- package/build/dist/Server/Utils/Database/RelationValueUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +10 -6
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +17 -21
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +5 -4
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +50 -10
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +13 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +6 -10
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Rules/MonitorRulePatternValidator.js +34 -0
- package/build/dist/Server/Utils/Rules/MonitorRulePatternValidator.js.map +1 -0
- package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +69 -0
- package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleApplication.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleApplication.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunPermission.js +128 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunPermission.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +746 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunner.js +221 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunner.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +3 -2
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js +6 -4
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.js +174 -14
- package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.js +1417 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js +138 -18
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js +1 -2
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js +23 -18
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js +2 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js +95 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +1 -1
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js +3 -3
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +2 -2
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +118 -40
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/Slo/SloFeedUtil.js +150 -0
- package/build/dist/Server/Utils/Slo/SloFeedUtil.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.js +136 -0
- package/build/dist/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloMetricUtil.js +269 -0
- package/build/dist/Server/Utils/Slo/SloMetricUtil.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloOwnerReferenceValidator.js +134 -0
- package/build/dist/Server/Utils/Slo/SloOwnerReferenceValidator.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloRecordReferenceValidator.js +137 -0
- package/build/dist/Server/Utils/Slo/SloRecordReferenceValidator.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js +6 -26
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageResource.js +31 -5
- package/build/dist/Server/Utils/StatusPageResource.js.map +1 -1
- package/build/dist/Types/Billing/SubscriptionStatus.js +37 -3
- package/build/dist/Types/Billing/SubscriptionStatus.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +5 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +275 -286
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Database/EnableAuditLog.js +19 -1
- package/build/dist/Types/Database/EnableAuditLog.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +4 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +45 -6
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +2 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDnsMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepDnsMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepRetries.js +47 -0
- package/build/dist/Types/Monitor/MonitorStepRetries.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js.map +1 -1
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticResult.js +29 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticResult.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.js +37 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticType.js +42 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticType.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDevicePingMetricNames.js +20 -0
- package/build/dist/Types/NetworkDevice/NetworkDevicePingMetricNames.js.map +1 -0
- package/build/dist/Types/Permission.js +114 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +5 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +267 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js +16 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +65 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js +6 -2
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js.map +1 -1
- package/build/dist/Types/ServiceLevelObjective/SloHistoryMetricName.js +26 -0
- package/build/dist/Types/ServiceLevelObjective/SloHistoryMetricName.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloMetricType.js +45 -0
- package/build/dist/Types/ServiceLevelObjective/SloMetricType.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js +4 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js.map +1 -1
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +295 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTrigger.js +13 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTrigger.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +67 -0
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js.map +1 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js +7 -7
- package/build/dist/Types/Telemetry/ServiceType.js +7 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/AlertBanner/AlertBanner.js +48 -19
- package/build/dist/UI/Components/AlertBanner/AlertBanner.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js +10 -2
- package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +12 -3
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +33 -5
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyState.js +3 -3
- package/build/dist/UI/Components/EmptyState/EmptyState.js.map +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js +47 -0
- package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js.map +1 -0
- package/build/dist/UI/Components/Forms/ModelForm.js +6 -5
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js +6 -2
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +0 -2
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +3 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/RuleRun/RuleDetailFields.js +226 -0
- package/build/dist/UI/Components/RuleRun/RuleDetailFields.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RuleTable.js +97 -0
- package/build/dist/UI/Components/RuleRun/RuleTable.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RuleView.js +83 -0
- package/build/dist/UI/Components/RuleRun/RuleView.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RunRuleNowModal.js +74 -0
- package/build/dist/UI/Components/RuleRun/RunRuleNowModal.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RunRulesBulkAction.js +78 -0
- package/build/dist/UI/Components/RuleRun/RunRulesBulkAction.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +24 -50
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js +0 -4
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Utils/Rules/RuleRunClient.js +98 -0
- package/build/dist/UI/Utils/Rules/RuleRunClient.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +8 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +16 -2
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardSloListComponent.js +94 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/Dashboard/SloWidgetSource.js +125 -0
- package/build/dist/Utils/Dashboard/SloWidgetSource.js.map +1 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js +49 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +112 -34
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +22 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +129 -0
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/RunImportedDeviceNaming.js +255 -0
- package/build/dist/Utils/NetworkDiscovery/RunImportedDeviceNaming.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ShortDeviceNamePlanner.js +184 -0
- package/build/dist/Utils/NetworkDiscovery/ShortDeviceNamePlanner.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ShortHostnameUtil.js +79 -0
- package/build/dist/Utils/NetworkDiscovery/ShortHostnameUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +21 -12
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -1
- package/build/dist/Utils/Project/DataResidency.js +51 -0
- package/build/dist/Utils/Project/DataResidency.js.map +1 -0
- package/build/dist/Utils/Rules/RuleRunSummary.js +197 -0
- package/build/dist/Utils/Rules/RuleRunSummary.js.map +1 -0
- package/build/dist/Utils/Slo/SloAffectedResourceMarkdown.js +51 -0
- package/build/dist/Utils/Slo/SloAffectedResourceMarkdown.js.map +1 -0
- package/build/dist/Utils/Slo/SloBurnRateTemplate.js +228 -0
- package/build/dist/Utils/Slo/SloBurnRateTemplate.js.map +1 -0
- package/build/dist/Utils/Slo/SloFeedMarkdown.js +934 -0
- package/build/dist/Utils/Slo/SloFeedMarkdown.js.map +1 -0
- package/build/dist/Utils/Slo/SloHealth.js +75 -9
- package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
- package/build/dist/Utils/Slo/SloListWidgetFormat.js +217 -0
- package/build/dist/Utils/Slo/SloListWidgetFormat.js.map +1 -0
- package/build/dist/Utils/Slo/SloMetricType.js +212 -0
- package/build/dist/Utils/Slo/SloMetricType.js.map +1 -0
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +216 -0
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -0
- package/build/dist/Utils/Slo/SloMonitorStatusSummary.js +129 -0
- package/build/dist/Utils/Slo/SloMonitorStatusSummary.js.map +1 -0
- package/build/dist/Utils/Slo/SloOverviewText.js +110 -0
- package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -0
- package/build/dist/Utils/Slo/SloProjection.js +448 -0
- package/build/dist/Utils/Slo/SloProjection.js.map +1 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js +4 -2
- package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -1
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js +1 -26
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js.map +1 -1
- package/package.json +1 -1
- package/Models/DatabaseModels/GoogleSecOpsConnection.ts +0 -447
- package/Models/DatabaseModels/GoogleSecOpsConnectionRun.ts +0 -263
- package/Server/API/GoogleSecOpsConnectionAPI.ts +0 -320
- package/Server/Services/GoogleSecOpsConnectionRunService.ts +0 -10
- package/Server/Services/GoogleSecOpsConnectionService.ts +0 -116
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.ts +0 -777
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +0 -1373
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +0 -512
- package/Tests/App/Dashboard/GoogleSecOpsConnectionForm.test.tsx +0 -838
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +0 -441
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +0 -1001
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +0 -657
- package/Tests/Server/Services/GoogleSecOpsDiagnosticsModel.test.ts +0 -153
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.test.ts +0 -784
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +0 -823
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +0 -918
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +0 -738
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +0 -874
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +0 -1297
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsThreePassPoller.test.ts +0 -1577
- package/Tests/UI/Components/LockedFilterActions.test.tsx +0 -396
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +0 -111
- package/UI/Components/TelemetryViewer/components/LockedFilterActions.tsx +0 -205
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +0 -478
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +0 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js +0 -287
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js.map +0 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +0 -231
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +0 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js +0 -9
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js.map +0 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +0 -70
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js +0 -537
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +0 -1034
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +0 -410
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +0 -1
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js +0 -2
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js.map +0 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js +0 -88
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js.map +0 -1
|
@@ -79,13 +79,16 @@ jest.mock("../../../UI/Components/Markdown.tsx/LazyMarkdownViewer", () => {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
/*
|
|
82
|
-
* The feed owns
|
|
83
|
-
*
|
|
84
|
-
* instead of counting raw events, so the mock has to answer
|
|
85
|
-
*
|
|
86
|
-
* case that used to
|
|
82
|
+
* The feed owns "how many steps will this draw?", because several event
|
|
83
|
+
* types only close a step an earlier event opened. The panel and its run
|
|
84
|
+
* details ask it instead of counting raw events, so the mock has to answer
|
|
85
|
+
* too. countActivityStepsMock lets a test make events and steps disagree —
|
|
86
|
+
* the case that used to frame an empty box — and hasRenderableActivityMock
|
|
87
|
+
* follows it by default, exactly as the real predicate does, so the two
|
|
88
|
+
* exports can never contradict each other unless a test says so.
|
|
87
89
|
*/
|
|
88
90
|
const hasRenderableActivityMock: MockFunction = getJestMockFunction();
|
|
91
|
+
const countActivityStepsMock: MockFunction = getJestMockFunction();
|
|
89
92
|
|
|
90
93
|
// Evidence rows render through the chat widgets; their output is not under test.
|
|
91
94
|
jest.mock(
|
|
@@ -115,6 +118,9 @@ jest.mock(
|
|
|
115
118
|
hasRenderableActivity: (events: Array<AIRunEvent>): boolean => {
|
|
116
119
|
return hasRenderableActivityMock(events) as boolean;
|
|
117
120
|
},
|
|
121
|
+
countActivitySteps: (events: Array<AIRunEvent>): number => {
|
|
122
|
+
return countActivityStepsMock(events) as number;
|
|
123
|
+
},
|
|
118
124
|
};
|
|
119
125
|
},
|
|
120
126
|
);
|
|
@@ -126,6 +132,7 @@ import AIRunEvent from "../../../Models/DatabaseModels/AIRunEvent";
|
|
|
126
132
|
import HTTPErrorResponse from "../../../Types/API/HTTPErrorResponse";
|
|
127
133
|
import AIRunCodeFixRecommendation from "../../../Types/AI/AIRunCodeFixRecommendation";
|
|
128
134
|
import AIRunEventType from "../../../Types/AI/AIRunEventType";
|
|
135
|
+
import AIRunHumanVerdict from "../../../Types/AI/AIRunHumanVerdict";
|
|
129
136
|
import AIRunStatus from "../../../Types/AI/AIRunStatus";
|
|
130
137
|
import { JSONArray, JSONObject } from "../../../Types/JSON";
|
|
131
138
|
import ObjectID from "../../../Types/ObjectID";
|
|
@@ -301,6 +308,7 @@ function renderPanel(data?: {
|
|
|
301
308
|
onAnalysisAvailable?: (() => void) | undefined;
|
|
302
309
|
onStatusChange?: ((status: AIRunStatus | null) => void) | undefined;
|
|
303
310
|
onReportSummaryChange?: ((summary: string | null) => void) | undefined;
|
|
311
|
+
onVerdictChange?: ((verdict: AIRunHumanVerdict | null) => void) | undefined;
|
|
304
312
|
}): ReturnType<typeof render> {
|
|
305
313
|
return render(
|
|
306
314
|
<InvestigationPanel
|
|
@@ -309,6 +317,7 @@ function renderPanel(data?: {
|
|
|
309
317
|
onAnalysisAvailable={data?.onAnalysisAvailable}
|
|
310
318
|
onStatusChange={data?.onStatusChange}
|
|
311
319
|
onReportSummaryChange={data?.onReportSummaryChange}
|
|
320
|
+
onVerdictChange={data?.onVerdictChange}
|
|
312
321
|
/>,
|
|
313
322
|
);
|
|
314
323
|
}
|
|
@@ -372,17 +381,59 @@ function lastActivityProps(): ActivityFeedProps {
|
|
|
372
381
|
return calls[calls.length - 1]![0]!;
|
|
373
382
|
}
|
|
374
383
|
|
|
384
|
+
/*
|
|
385
|
+
* A completed run ends with one collapsed section holding its evidence, its
|
|
386
|
+
* activity and what it cost. Its body stays mounted while collapsed, so the
|
|
387
|
+
* role queries below (which skip hidden content) only find what a reader
|
|
388
|
+
* could actually reach; tests open the section before reaching inside it.
|
|
389
|
+
*/
|
|
390
|
+
function runDetails(): HTMLElement {
|
|
391
|
+
return screen.getByTestId("investigation-details");
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function detailsToggle(): HTMLElement {
|
|
395
|
+
return screen.getByTestId("investigation-details-toggle");
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function detailsBody(): HTMLElement {
|
|
399
|
+
const bodyId: string | null = detailsToggle().getAttribute("aria-controls");
|
|
400
|
+
expect(bodyId).toBeTruthy();
|
|
401
|
+
return document.getElementById(bodyId!)!;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function openDetails(): void {
|
|
405
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "false");
|
|
406
|
+
fireEvent.click(detailsToggle());
|
|
407
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "true");
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function detailsTab(name: RegExp): HTMLElement {
|
|
411
|
+
return within(
|
|
412
|
+
screen.getByRole("tablist", { name: "Investigation details" }),
|
|
413
|
+
).getByRole("tab", { name });
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function evidenceList(): HTMLElement {
|
|
417
|
+
return screen.getByRole("list", { name: "Evidence checked" });
|
|
418
|
+
}
|
|
419
|
+
|
|
375
420
|
beforeEach(() => {
|
|
376
421
|
jest.useFakeTimers();
|
|
377
422
|
jest.setSystemTime(new Date(COMPLETED_AT));
|
|
378
423
|
getCommonHeadersMock.mockReturnValue({});
|
|
379
424
|
/*
|
|
380
425
|
* Default to the real component's behaviour for the ordinary event shapes
|
|
381
|
-
* these tests use: every step-opening event draws a step
|
|
426
|
+
* these tests use: every step-opening event draws a step, and there is
|
|
427
|
+
* activity to render exactly when at least one step is drawn.
|
|
382
428
|
*/
|
|
429
|
+
countActivityStepsMock.mockImplementation(
|
|
430
|
+
(events: Array<AIRunEvent>): number => {
|
|
431
|
+
return events.length;
|
|
432
|
+
},
|
|
433
|
+
);
|
|
383
434
|
hasRenderableActivityMock.mockImplementation(
|
|
384
435
|
(events: Array<AIRunEvent>): boolean => {
|
|
385
|
-
return events
|
|
436
|
+
return (countActivityStepsMock(events) as number) > 0;
|
|
386
437
|
},
|
|
387
438
|
);
|
|
388
439
|
getFriendlyMessageMock.mockImplementation((error: unknown): string => {
|
|
@@ -409,6 +460,7 @@ afterEach(() => {
|
|
|
409
460
|
markdownViewerMock.mockReset();
|
|
410
461
|
activityFeedMock.mockReset();
|
|
411
462
|
hasRenderableActivityMock.mockReset();
|
|
463
|
+
countActivityStepsMock.mockReset();
|
|
412
464
|
widgetRendererMock.mockReset();
|
|
413
465
|
});
|
|
414
466
|
|
|
@@ -459,7 +511,7 @@ describe("InvestigationPanel report lifecycle", () => {
|
|
|
459
511
|
expect(getCommonHeadersMock).toHaveBeenCalledTimes(1);
|
|
460
512
|
});
|
|
461
513
|
|
|
462
|
-
test("renders the completed report safely and
|
|
514
|
+
test("renders the completed report safely and folds its activity into a collapsed section", async () => {
|
|
463
515
|
const onAnalysisAvailable: MockFunction = getJestMockFunction();
|
|
464
516
|
postMock.mockResolvedValue(completedResponse() as never);
|
|
465
517
|
|
|
@@ -487,21 +539,29 @@ describe("InvestigationPanel report lifecycle", () => {
|
|
|
487
539
|
expect(
|
|
488
540
|
screen.getByRole("heading", { level: 4, name: "Root cause" }),
|
|
489
541
|
).toBeInTheDocument();
|
|
490
|
-
|
|
542
|
+
/*
|
|
543
|
+
* This report carries no evidence, so the section is only the activity
|
|
544
|
+
* and is named for it. It starts collapsed: the report is the answer.
|
|
545
|
+
*/
|
|
546
|
+
expect(detailsToggle()).toHaveTextContent("Investigation activity");
|
|
547
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "false");
|
|
548
|
+
expect(detailsBody()).not.toBeVisible();
|
|
491
549
|
expect(lastActivityProps()).toEqual(
|
|
492
550
|
expect.objectContaining({
|
|
493
551
|
hideChrome: true,
|
|
494
552
|
showLiveIndicator: false,
|
|
495
|
-
maxVisibleSteps: 10,
|
|
496
553
|
}),
|
|
497
554
|
);
|
|
498
555
|
|
|
499
556
|
const usage: HTMLElement = screen.getByLabelText("Investigation usage");
|
|
557
|
+
expect(usage).toBeVisible();
|
|
500
558
|
expect(usage).toHaveTextContent("2 telemetry queries");
|
|
501
|
-
expect(usage).toHaveTextContent("1,234 tokens");
|
|
502
559
|
expect(usage).toHaveTextContent(
|
|
503
560
|
"Read-only — nothing in your systems was changed",
|
|
504
561
|
);
|
|
562
|
+
expect(screen.getByLabelText("Model and tokens")).toHaveTextContent(
|
|
563
|
+
"1,234 tokens",
|
|
564
|
+
);
|
|
505
565
|
expect(fixButton()).toBeEnabled();
|
|
506
566
|
expect(screen.getByRole("button", { name: "Confirmed" })).toBeEnabled();
|
|
507
567
|
expect(screen.getByRole("button", { name: "Rejected" })).toBeEnabled();
|
|
@@ -531,6 +591,8 @@ describe("InvestigationPanel report lifecycle", () => {
|
|
|
531
591
|
expect(screen.getByText("Preparing investigation report…")).toBeVisible();
|
|
532
592
|
expect(screen.getByText("Preparing the final report")).toBeVisible();
|
|
533
593
|
expect(screen.queryByTestId("investigation-markdown")).toBeNull();
|
|
594
|
+
// The steps can already be checked while the report is being written.
|
|
595
|
+
expect(detailsToggle()).toHaveTextContent("Investigation activity");
|
|
534
596
|
expect(onAnalysisAvailable).not.toHaveBeenCalled();
|
|
535
597
|
|
|
536
598
|
/* Status, run id, events and recommendation remain identical. */
|
|
@@ -678,6 +740,19 @@ describe("InvestigationPanel report lifecycle", () => {
|
|
|
678
740
|
expect(
|
|
679
741
|
screen.getByText("No investigation report was published."),
|
|
680
742
|
).toBeVisible();
|
|
743
|
+
/*
|
|
744
|
+
* No steps were recorded, so the notice does not point at an activity
|
|
745
|
+
* section that is not there, and there is nothing to expand: the run's
|
|
746
|
+
* usage is all that is left to say.
|
|
747
|
+
*/
|
|
748
|
+
expect(
|
|
749
|
+
screen.getByText("The run finished without a final analysis."),
|
|
750
|
+
).toBeVisible();
|
|
751
|
+
expect(screen.queryByText(/Investigation activity/)).toBeNull();
|
|
752
|
+
expect(screen.queryByTestId("investigation-details-toggle")).toBeNull();
|
|
753
|
+
expect(screen.getByLabelText("Investigation usage")).toHaveTextContent(
|
|
754
|
+
"0 telemetry queries",
|
|
755
|
+
);
|
|
681
756
|
expect(fixButton()).toBeDisabled();
|
|
682
757
|
expect(screen.getByRole("button", { name: "Confirmed" })).toBeDisabled();
|
|
683
758
|
expect(screen.getByRole("button", { name: "Rejected" })).toBeDisabled();
|
|
@@ -771,14 +846,16 @@ describe("InvestigationPanel card states", () => {
|
|
|
771
846
|
expect(screen.getByText("Starting investigation…")).toBeVisible();
|
|
772
847
|
});
|
|
773
848
|
|
|
774
|
-
test("puts a copy control
|
|
849
|
+
test("puts a copy control and a verify-first note on the report", async () => {
|
|
775
850
|
postMock.mockResolvedValue(completedResponse() as never);
|
|
776
851
|
|
|
777
852
|
renderPanel();
|
|
778
853
|
await flush();
|
|
779
854
|
|
|
780
855
|
const report: HTMLElement = screen.getByLabelText("Investigation report");
|
|
781
|
-
expect(report).toHaveTextContent(
|
|
856
|
+
expect(report).toHaveTextContent(
|
|
857
|
+
"AI-generated first pass — verify before acting.",
|
|
858
|
+
);
|
|
782
859
|
expect(report).toContainElement(
|
|
783
860
|
screen.getByRole("button", { name: "Copy report" }),
|
|
784
861
|
);
|
|
@@ -813,6 +890,45 @@ describe("InvestigationPanel card states", () => {
|
|
|
813
890
|
},
|
|
814
891
|
);
|
|
815
892
|
|
|
893
|
+
/*
|
|
894
|
+
* A failed run has no report and no collapsed details, so what it ran and
|
|
895
|
+
* the read-only guarantee close its own activity frame instead — a reader
|
|
896
|
+
* deciding whether a half-finished run touched anything finds the answer
|
|
897
|
+
* right under the steps it took.
|
|
898
|
+
*/
|
|
899
|
+
test("ends a failed run's activity with what it ran and that it changed nothing", async () => {
|
|
900
|
+
postMock.mockResolvedValue(
|
|
901
|
+
successfulResponse(
|
|
902
|
+
investigationPayload({
|
|
903
|
+
status: AIRunStatus.Error,
|
|
904
|
+
errorMessage: "The model provider timed out.",
|
|
905
|
+
events: [activityEvent],
|
|
906
|
+
toolCallCount: 3,
|
|
907
|
+
totalTokens: 900,
|
|
908
|
+
}),
|
|
909
|
+
) as never,
|
|
910
|
+
);
|
|
911
|
+
|
|
912
|
+
renderPanel();
|
|
913
|
+
await flush();
|
|
914
|
+
|
|
915
|
+
const activity: HTMLElement = screen.getByRole("region", {
|
|
916
|
+
name: "Investigation activity",
|
|
917
|
+
});
|
|
918
|
+
const usage: HTMLElement = within(activity).getByRole("list", {
|
|
919
|
+
name: "Investigation usage",
|
|
920
|
+
});
|
|
921
|
+
expect(activity.lastElementChild).toBe(usage);
|
|
922
|
+
expect(usage).toBeVisible();
|
|
923
|
+
expect(usage).toHaveTextContent("3 telemetry queries");
|
|
924
|
+
expect(usage).toHaveTextContent("900 tokens");
|
|
925
|
+
expect(usage).toHaveTextContent(
|
|
926
|
+
"Read-only — nothing in your systems was changed",
|
|
927
|
+
);
|
|
928
|
+
expect(screen.queryByTestId("investigation-details")).toBeNull();
|
|
929
|
+
expect(screen.getAllByLabelText("Investigation usage")).toHaveLength(1);
|
|
930
|
+
});
|
|
931
|
+
|
|
816
932
|
/*
|
|
817
933
|
* Events and rendered steps are not the same thing: RunFailed and the
|
|
818
934
|
* completion halves of tool/LLM calls only close a step an earlier event
|
|
@@ -821,7 +937,7 @@ describe("InvestigationPanel card states", () => {
|
|
|
821
937
|
* an empty panel instead of saying what happened.
|
|
822
938
|
*/
|
|
823
939
|
test("explains an empty trail instead of framing a blank panel", async () => {
|
|
824
|
-
|
|
940
|
+
countActivityStepsMock.mockReturnValue(0);
|
|
825
941
|
postMock.mockResolvedValue(
|
|
826
942
|
successfulResponse(
|
|
827
943
|
investigationPayload({
|
|
@@ -841,8 +957,14 @@ describe("InvestigationPanel card states", () => {
|
|
|
841
957
|
).toBeVisible();
|
|
842
958
|
});
|
|
843
959
|
|
|
844
|
-
|
|
845
|
-
|
|
960
|
+
/*
|
|
961
|
+
* The same event/step mismatch on a completed run: with no evidence and no
|
|
962
|
+
* step to draw, a collapsed section would open onto nothing. The run's
|
|
963
|
+
* usage is all there is, so it stands alone — tokens included, since there
|
|
964
|
+
* is no body to hold them.
|
|
965
|
+
*/
|
|
966
|
+
test("offers nothing to expand when a completed run has no evidence and no step would render", async () => {
|
|
967
|
+
countActivityStepsMock.mockReturnValue(0);
|
|
846
968
|
postMock.mockResolvedValue(completedResponse() as never);
|
|
847
969
|
|
|
848
970
|
renderPanel();
|
|
@@ -850,9 +972,17 @@ describe("InvestigationPanel card states", () => {
|
|
|
850
972
|
|
|
851
973
|
expect(screen.getByLabelText("Investigation report")).toBeInTheDocument();
|
|
852
974
|
expect(screen.queryByText("Investigation activity")).toBeNull();
|
|
975
|
+
expect(screen.queryByTestId("investigation-details-toggle")).toBeNull();
|
|
976
|
+
expect(screen.queryByTestId("investigation-activity")).toBeNull();
|
|
977
|
+
|
|
978
|
+
const usage: HTMLElement = screen.getByLabelText("Investigation usage");
|
|
979
|
+
expect(usage).toBeVisible();
|
|
980
|
+
expect(usage).toHaveTextContent("2 telemetry queries");
|
|
981
|
+
expect(usage).toHaveTextContent("1,234 tokens");
|
|
982
|
+
expect(usage).not.toHaveTextContent("step");
|
|
853
983
|
});
|
|
854
984
|
|
|
855
|
-
test("reports a single query without pluralising
|
|
985
|
+
test("reports a single query and step without pluralising them", async () => {
|
|
856
986
|
postMock.mockResolvedValue(
|
|
857
987
|
completedResponse({ toolCallCount: 1, totalTokens: 0 }) as never,
|
|
858
988
|
);
|
|
@@ -862,8 +992,50 @@ describe("InvestigationPanel card states", () => {
|
|
|
862
992
|
|
|
863
993
|
const usage: HTMLElement = screen.getByLabelText("Investigation usage");
|
|
864
994
|
expect(usage).toHaveTextContent("1 telemetry query");
|
|
995
|
+
expect(usage).not.toHaveTextContent("queries");
|
|
996
|
+
expect(usage).toHaveTextContent("1 step");
|
|
997
|
+
expect(usage).not.toHaveTextContent("steps");
|
|
865
998
|
expect(usage).not.toHaveTextContent("tokens");
|
|
866
999
|
});
|
|
1000
|
+
|
|
1001
|
+
/*
|
|
1002
|
+
* The no-report notice used to send every reader to "the activity below",
|
|
1003
|
+
* even when no step had been recorded and there was nothing below to read.
|
|
1004
|
+
*/
|
|
1005
|
+
test("points the no-report notice at the activity only when there is some", async () => {
|
|
1006
|
+
postMock.mockResolvedValue(
|
|
1007
|
+
completedResponse({
|
|
1008
|
+
analysisMarkdown: null,
|
|
1009
|
+
isAnalysisPending: false,
|
|
1010
|
+
}) as never,
|
|
1011
|
+
);
|
|
1012
|
+
|
|
1013
|
+
renderPanel();
|
|
1014
|
+
await flush();
|
|
1015
|
+
|
|
1016
|
+
expect(
|
|
1017
|
+
screen.getByText(
|
|
1018
|
+
"The run finished without a final analysis. Its steps are under Investigation activity below.",
|
|
1019
|
+
),
|
|
1020
|
+
).toBeVisible();
|
|
1021
|
+
|
|
1022
|
+
/*
|
|
1023
|
+
* Evidence only exists beside a report, so the section is the activity
|
|
1024
|
+
* alone: named for it, and without tabs once opened.
|
|
1025
|
+
*/
|
|
1026
|
+
expect(detailsToggle()).toHaveTextContent("Investigation activity");
|
|
1027
|
+
expect(detailsToggle()).not.toHaveTextContent("Evidence");
|
|
1028
|
+
expect(screen.getByLabelText("Investigation usage")).toHaveTextContent(
|
|
1029
|
+
"2 telemetry queries",
|
|
1030
|
+
);
|
|
1031
|
+
|
|
1032
|
+
openDetails();
|
|
1033
|
+
|
|
1034
|
+
expect(screen.queryByRole("tablist")).toBeNull();
|
|
1035
|
+
expect(screen.queryByRole("tabpanel")).toBeNull();
|
|
1036
|
+
expect(screen.queryByLabelText("Evidence checked")).toBeNull();
|
|
1037
|
+
expect(screen.getByTestId("investigation-activity")).toBeVisible();
|
|
1038
|
+
});
|
|
867
1039
|
});
|
|
868
1040
|
|
|
869
1041
|
/*
|
|
@@ -1956,18 +2128,25 @@ describe("InvestigationPanel structured report", () => {
|
|
|
1956
2128
|
renderPanel();
|
|
1957
2129
|
await flush();
|
|
1958
2130
|
|
|
1959
|
-
const evidence: HTMLElement = screen.getByRole("region", {
|
|
1960
|
-
name: "Evidence checked",
|
|
1961
|
-
});
|
|
1962
|
-
expect(within(evidence).getByText("2 queries")).toBeVisible();
|
|
1963
|
-
expect(
|
|
1964
|
-
within(evidence).getByRole("button", { name: /Active incidents/ }),
|
|
1965
|
-
).toHaveAttribute("aria-expanded", "false");
|
|
1966
2131
|
expect(
|
|
1967
2132
|
screen
|
|
1968
2133
|
.getByLabelText("Investigation report")
|
|
1969
|
-
.compareDocumentPosition(
|
|
2134
|
+
.compareDocumentPosition(runDetails()) &
|
|
2135
|
+
Node.DOCUMENT_POSITION_FOLLOWING,
|
|
1970
2136
|
).toBeTruthy();
|
|
2137
|
+
|
|
2138
|
+
openDetails();
|
|
2139
|
+
|
|
2140
|
+
// The tab carries the query count the old list header used to show.
|
|
2141
|
+
expect(detailsTab(/^Evidence checked/)).toHaveTextContent(
|
|
2142
|
+
"Evidence checked2",
|
|
2143
|
+
);
|
|
2144
|
+
const evidence: HTMLElement = evidenceList();
|
|
2145
|
+
expect(runDetails()).toContainElement(evidence);
|
|
2146
|
+
expect(within(evidence).getAllByRole("listitem")).toHaveLength(2);
|
|
2147
|
+
expect(
|
|
2148
|
+
within(evidence).getByRole("button", { name: /Active incidents/ }),
|
|
2149
|
+
).toHaveAttribute("aria-expanded", "false");
|
|
1971
2150
|
// Rendering evidence never re-runs anything by itself.
|
|
1972
2151
|
expect(evidencePosts()).toHaveLength(0);
|
|
1973
2152
|
expect(jest.getTimerCount()).toBe(1);
|
|
@@ -1987,6 +2166,7 @@ describe("InvestigationPanel structured report", () => {
|
|
|
1987
2166
|
|
|
1988
2167
|
renderPanel();
|
|
1989
2168
|
await flush();
|
|
2169
|
+
openDetails();
|
|
1990
2170
|
|
|
1991
2171
|
const toggle: HTMLElement = screen.getByRole("button", {
|
|
1992
2172
|
name: /Active incidents \(7 total\)/,
|
|
@@ -2019,10 +2199,12 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2019
2199
|
|
|
2020
2200
|
renderPanel();
|
|
2021
2201
|
await flush();
|
|
2202
|
+
openDetails();
|
|
2022
2203
|
|
|
2023
|
-
const evidence: HTMLElement =
|
|
2024
|
-
|
|
2025
|
-
|
|
2204
|
+
const evidence: HTMLElement = evidenceList();
|
|
2205
|
+
expect(detailsTab(/^Evidence checked/)).toHaveTextContent(
|
|
2206
|
+
"Evidence checked2",
|
|
2207
|
+
);
|
|
2026
2208
|
expect(evidence).toHaveTextContent("Active incidents (7 total)");
|
|
2027
2209
|
expect(evidence).toHaveTextContent("Logs 17:20 – 18:20 (1 shown)");
|
|
2028
2210
|
expect(within(evidence).queryAllByRole("button")).toHaveLength(0);
|
|
@@ -2045,17 +2227,15 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2045
2227
|
|
|
2046
2228
|
renderPanel();
|
|
2047
2229
|
await flush();
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
),
|
|
2052
|
-
).toHaveLength(0);
|
|
2230
|
+
openDetails();
|
|
2231
|
+
expect(within(evidenceList()).getAllByRole("listitem")).toHaveLength(2);
|
|
2232
|
+
expect(within(evidenceList()).queryAllByRole("button")).toHaveLength(0);
|
|
2053
2233
|
|
|
2054
2234
|
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
2055
2235
|
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
).toHaveLength(2);
|
|
2236
|
+
// Still open on the same list, now with a toggle per query.
|
|
2237
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "true");
|
|
2238
|
+
expect(within(evidenceList()).getAllByRole("button")).toHaveLength(2);
|
|
2059
2239
|
});
|
|
2060
2240
|
|
|
2061
2241
|
test("never shows evidence without the report it belongs to", async () => {
|
|
@@ -2073,6 +2253,13 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2073
2253
|
|
|
2074
2254
|
expect(screen.getByText("Preparing the final report")).toBeVisible();
|
|
2075
2255
|
expect(screen.queryByLabelText("Evidence checked")).toBeNull();
|
|
2256
|
+
|
|
2257
|
+
// The section still offers the run's steps, and only those.
|
|
2258
|
+
expect(detailsToggle()).toHaveTextContent("Investigation activity");
|
|
2259
|
+
openDetails();
|
|
2260
|
+
expect(screen.queryByRole("tablist")).toBeNull();
|
|
2261
|
+
expect(screen.queryByLabelText("Evidence checked")).toBeNull();
|
|
2262
|
+
expect(screen.getByTestId("investigation-activity")).toBeVisible();
|
|
2076
2263
|
});
|
|
2077
2264
|
|
|
2078
2265
|
test("drops evidence when the report disappears on a later poll", async () => {
|
|
@@ -2085,10 +2272,12 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2085
2272
|
renderPanel();
|
|
2086
2273
|
await flush();
|
|
2087
2274
|
expect(screen.getByLabelText("Evidence checked")).toBeInTheDocument();
|
|
2275
|
+
expect(detailsToggle()).toHaveTextContent("Evidence and activity");
|
|
2088
2276
|
|
|
2089
2277
|
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
2090
2278
|
|
|
2091
2279
|
expect(screen.queryByLabelText("Evidence checked")).toBeNull();
|
|
2280
|
+
expect(detailsToggle()).toHaveTextContent("Investigation activity");
|
|
2092
2281
|
expect(
|
|
2093
2282
|
screen.getByText("No investigation report was published."),
|
|
2094
2283
|
).toBeVisible();
|
|
@@ -2110,13 +2299,11 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2110
2299
|
|
|
2111
2300
|
renderPanel();
|
|
2112
2301
|
await flush();
|
|
2302
|
+
openDetails();
|
|
2113
2303
|
|
|
2114
2304
|
// Nothing valid survived, so the legacy list and plain numbers are used.
|
|
2115
|
-
expect(
|
|
2116
|
-
|
|
2117
|
-
"button",
|
|
2118
|
-
),
|
|
2119
|
-
).toHaveLength(0);
|
|
2305
|
+
expect(within(evidenceList()).getAllByRole("listitem")).toHaveLength(2);
|
|
2306
|
+
expect(within(evidenceList()).queryAllByRole("button")).toHaveLength(0);
|
|
2120
2307
|
expect(
|
|
2121
2308
|
lastInlineReferences().renderEventReference!({
|
|
2122
2309
|
kind: "incident",
|
|
@@ -2126,7 +2313,27 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2126
2313
|
).toBeNull();
|
|
2127
2314
|
});
|
|
2128
2315
|
|
|
2129
|
-
|
|
2316
|
+
/*
|
|
2317
|
+
* The report's chips are rendered by the markdown viewer, which is mocked
|
|
2318
|
+
* here, so render the panel's own chip renderer output and click it the
|
|
2319
|
+
* way a reader would.
|
|
2320
|
+
*/
|
|
2321
|
+
function clickCitation(citationId: string, name: string): void {
|
|
2322
|
+
const chip: React.ReactElement | null =
|
|
2323
|
+
lastInlineReferences().renderCitation!(citationId);
|
|
2324
|
+
expect(chip).not.toBeNull();
|
|
2325
|
+
render(chip!);
|
|
2326
|
+
|
|
2327
|
+
const chipButton: HTMLElement = screen.getByRole("button", { name });
|
|
2328
|
+
fireEvent.click(chipButton);
|
|
2329
|
+
}
|
|
2330
|
+
|
|
2331
|
+
/*
|
|
2332
|
+
* The evidence sits in a section that starts collapsed, so a chip that only
|
|
2333
|
+
* highlighted its row would highlight something nobody can see. The chip
|
|
2334
|
+
* has to open the section on the Evidence tab first.
|
|
2335
|
+
*/
|
|
2336
|
+
test("a citation chip opens the collapsed details and expands, scrolls to and highlights its row", async () => {
|
|
2130
2337
|
routePosts({
|
|
2131
2338
|
investigation: (): unknown => {
|
|
2132
2339
|
return Promise.resolve(structuredResponse());
|
|
@@ -2136,6 +2343,8 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2136
2343
|
renderPanel();
|
|
2137
2344
|
await flush();
|
|
2138
2345
|
expect(jest.getTimerCount()).toBe(1);
|
|
2346
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "false");
|
|
2347
|
+
expect(detailsBody()).not.toBeVisible();
|
|
2139
2348
|
|
|
2140
2349
|
const chip: React.ReactElement | null =
|
|
2141
2350
|
lastInlineReferences().renderCitation!("C2");
|
|
@@ -2150,10 +2359,19 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2150
2359
|
fireEvent.click(chipButton);
|
|
2151
2360
|
await flush();
|
|
2152
2361
|
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2362
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "true");
|
|
2363
|
+
expect(detailsBody()).toBeVisible();
|
|
2364
|
+
expect(detailsTab(/^Evidence checked/)).toHaveAttribute(
|
|
2365
|
+
"aria-selected",
|
|
2366
|
+
"true",
|
|
2367
|
+
);
|
|
2368
|
+
|
|
2369
|
+
const toggle: HTMLElement = within(evidenceList()).getByRole("button", {
|
|
2370
|
+
name: /Logs 17:20/,
|
|
2371
|
+
});
|
|
2372
|
+
expect(toggle).toBeVisible();
|
|
2156
2373
|
expect(toggle).toHaveAttribute("aria-expanded", "true");
|
|
2374
|
+
expect(toggle).toHaveFocus();
|
|
2157
2375
|
expect(toggle.closest("li")).toHaveAttribute("data-highlighted", "true");
|
|
2158
2376
|
expect(scrollIntoViewMock).toHaveBeenCalledWith({
|
|
2159
2377
|
block: "nearest",
|
|
@@ -2168,6 +2386,157 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2168
2386
|
|
|
2169
2387
|
expect(toggle.closest("li")).not.toHaveAttribute("data-highlighted");
|
|
2170
2388
|
expect(jest.getTimerCount()).toBe(1);
|
|
2389
|
+
// The highlight fades; the section the reader was taken to stays open.
|
|
2390
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "true");
|
|
2391
|
+
});
|
|
2392
|
+
|
|
2393
|
+
test("a citation chip switches an open section from Activity to Evidence", async () => {
|
|
2394
|
+
routePosts({
|
|
2395
|
+
investigation: (): unknown => {
|
|
2396
|
+
return Promise.resolve(structuredResponse());
|
|
2397
|
+
},
|
|
2398
|
+
});
|
|
2399
|
+
|
|
2400
|
+
renderPanel();
|
|
2401
|
+
await flush();
|
|
2402
|
+
openDetails();
|
|
2403
|
+
fireEvent.click(detailsTab(/^Activity/));
|
|
2404
|
+
expect(screen.getByTestId("investigation-activity")).toBeVisible();
|
|
2405
|
+
expect(screen.queryByRole("list", { name: "Evidence checked" })).toBeNull();
|
|
2406
|
+
|
|
2407
|
+
clickCitation("C1", "Citation C1: Active incidents (7 total)");
|
|
2408
|
+
await flush();
|
|
2409
|
+
|
|
2410
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "true");
|
|
2411
|
+
expect(detailsTab(/^Evidence checked/)).toHaveAttribute(
|
|
2412
|
+
"aria-selected",
|
|
2413
|
+
"true",
|
|
2414
|
+
);
|
|
2415
|
+
expect(detailsTab(/^Activity/)).toHaveAttribute("aria-selected", "false");
|
|
2416
|
+
expect(screen.getByTestId("investigation-activity")).not.toBeVisible();
|
|
2417
|
+
|
|
2418
|
+
const toggle: HTMLElement = within(evidenceList()).getByRole("button", {
|
|
2419
|
+
name: /Active incidents/,
|
|
2420
|
+
});
|
|
2421
|
+
expect(toggle).toBeVisible();
|
|
2422
|
+
expect(toggle).toHaveAttribute("aria-expanded", "true");
|
|
2423
|
+
expect(toggle).toHaveFocus();
|
|
2424
|
+
expect(toggle.closest("li")).toHaveAttribute("data-highlighted", "true");
|
|
2425
|
+
expect(scrollIntoViewMock).toHaveBeenCalledTimes(1);
|
|
2426
|
+
});
|
|
2427
|
+
|
|
2428
|
+
/*
|
|
2429
|
+
* An older API sends no structured evidence, so the report's own list is
|
|
2430
|
+
* shown and its rows have no toggle. The row itself takes focus, or a
|
|
2431
|
+
* keyboard or screen-reader user would be left on the chip.
|
|
2432
|
+
*/
|
|
2433
|
+
test("a citation chip on an older report reveals and focuses its plain row", async () => {
|
|
2434
|
+
postMock.mockResolvedValue(
|
|
2435
|
+
completedResponse({ analysisMarkdown: STRUCTURED_REPORT }) as never,
|
|
2436
|
+
);
|
|
2437
|
+
|
|
2438
|
+
renderPanel();
|
|
2439
|
+
await flush();
|
|
2440
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "false");
|
|
2441
|
+
|
|
2442
|
+
clickCitation("C2", "Citation C2: Logs 17:20 – 18:20 (1 shown)");
|
|
2443
|
+
await flush();
|
|
2444
|
+
|
|
2445
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "true");
|
|
2446
|
+
expect(detailsTab(/^Evidence checked/)).toHaveAttribute(
|
|
2447
|
+
"aria-selected",
|
|
2448
|
+
"true",
|
|
2449
|
+
);
|
|
2450
|
+
|
|
2451
|
+
const row: HTMLElement = within(evidenceList())
|
|
2452
|
+
.getAllByRole("listitem")
|
|
2453
|
+
.find((item: HTMLElement): boolean => {
|
|
2454
|
+
return item.textContent?.includes("Logs 17:20") === true;
|
|
2455
|
+
})!;
|
|
2456
|
+
expect(row).toBeVisible();
|
|
2457
|
+
expect(row).toHaveFocus();
|
|
2458
|
+
expect(row).toHaveAttribute("data-highlighted", "true");
|
|
2459
|
+
expect(scrollIntoViewMock).toHaveBeenCalledTimes(1);
|
|
2460
|
+
// A plain row has nothing to re-run.
|
|
2461
|
+
expect(evidencePosts()).toHaveLength(0);
|
|
2462
|
+
});
|
|
2463
|
+
|
|
2464
|
+
/*
|
|
2465
|
+
* A chip's request lives in the panel, so it outlives the evidence list
|
|
2466
|
+
* when the report briefly disappears between polls. When the list comes
|
|
2467
|
+
* back it must not replay that old request — scrolling the page and
|
|
2468
|
+
* stealing focus with no click behind it.
|
|
2469
|
+
*/
|
|
2470
|
+
test("does not replay a chip when the evidence comes back on a later poll", async () => {
|
|
2471
|
+
let investigationCalls: number = 0;
|
|
2472
|
+
routePosts({
|
|
2473
|
+
investigation: (): unknown => {
|
|
2474
|
+
investigationCalls += 1;
|
|
2475
|
+
return Promise.resolve(
|
|
2476
|
+
investigationCalls === 2
|
|
2477
|
+
? structuredResponse({ analysisMarkdown: null })
|
|
2478
|
+
: structuredResponse(),
|
|
2479
|
+
);
|
|
2480
|
+
},
|
|
2481
|
+
});
|
|
2482
|
+
|
|
2483
|
+
renderPanel();
|
|
2484
|
+
await flush();
|
|
2485
|
+
clickCitation("C2", "Citation C2: Logs 17:20 – 18:20 (1 shown)");
|
|
2486
|
+
await flush();
|
|
2487
|
+
expect(scrollIntoViewMock).toHaveBeenCalledTimes(1);
|
|
2488
|
+
await tick(2000);
|
|
2489
|
+
|
|
2490
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
2491
|
+
expect(screen.queryByLabelText("Evidence checked")).toBeNull();
|
|
2492
|
+
expect(screen.getByTestId("investigation-activity")).toBeVisible();
|
|
2493
|
+
|
|
2494
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
2495
|
+
expect(investigationPostCount()).toBe(3);
|
|
2496
|
+
|
|
2497
|
+
const toggle: HTMLElement = within(evidenceList()).getByRole("button", {
|
|
2498
|
+
name: /Logs 17:20/,
|
|
2499
|
+
});
|
|
2500
|
+
expect(toggle).toBeVisible();
|
|
2501
|
+
expect(toggle).toHaveAttribute("aria-expanded", "false");
|
|
2502
|
+
expect(toggle).not.toHaveFocus();
|
|
2503
|
+
expect(document.querySelector('[data-highlighted="true"]')).toBeNull();
|
|
2504
|
+
expect(scrollIntoViewMock).toHaveBeenCalledTimes(1);
|
|
2505
|
+
expect(evidencePosts()).toHaveLength(1);
|
|
2506
|
+
});
|
|
2507
|
+
|
|
2508
|
+
test("a new run on the same subject starts collapsed, even after a chip opened the last one", async () => {
|
|
2509
|
+
let investigationCalls: number = 0;
|
|
2510
|
+
routePosts({
|
|
2511
|
+
investigation: (): unknown => {
|
|
2512
|
+
investigationCalls += 1;
|
|
2513
|
+
return Promise.resolve(
|
|
2514
|
+
investigationCalls === 1
|
|
2515
|
+
? structuredResponse()
|
|
2516
|
+
: structuredResponse({ runId: NEXT_RUN_ID }),
|
|
2517
|
+
);
|
|
2518
|
+
},
|
|
2519
|
+
});
|
|
2520
|
+
|
|
2521
|
+
renderPanel();
|
|
2522
|
+
await flush();
|
|
2523
|
+
clickCitation("C2", "Citation C2: Logs 17:20 – 18:20 (1 shown)");
|
|
2524
|
+
await flush();
|
|
2525
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "true");
|
|
2526
|
+
|
|
2527
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
2528
|
+
|
|
2529
|
+
expect(investigationPostCount()).toBe(2);
|
|
2530
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "false");
|
|
2531
|
+
expect(detailsBody()).not.toBeVisible();
|
|
2532
|
+
|
|
2533
|
+
openDetails();
|
|
2534
|
+
|
|
2535
|
+
expect(
|
|
2536
|
+
within(evidenceList()).getByRole("button", { name: /Logs 17:20/ }),
|
|
2537
|
+
).toHaveAttribute("aria-expanded", "false");
|
|
2538
|
+
expect(document.querySelector('[data-highlighted="true"]')).toBeNull();
|
|
2539
|
+
expect(scrollIntoViewMock).toHaveBeenCalledTimes(1);
|
|
2171
2540
|
});
|
|
2172
2541
|
|
|
2173
2542
|
test("leaves a citation that is not in the evidence as plain text", async () => {
|
|
@@ -2255,6 +2624,7 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2255
2624
|
|
|
2256
2625
|
const view: ReturnType<typeof render> = renderPanel();
|
|
2257
2626
|
await flush();
|
|
2627
|
+
openDetails();
|
|
2258
2628
|
fireEvent.click(
|
|
2259
2629
|
screen.getByRole("button", { name: /Active incidents \(7 total\)/ }),
|
|
2260
2630
|
);
|
|
@@ -2271,6 +2641,8 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2271
2641
|
);
|
|
2272
2642
|
|
|
2273
2643
|
expect(screen.queryByText(/Previous subject rows/)).toBeNull();
|
|
2644
|
+
// The new subject's details start collapsed like any other.
|
|
2645
|
+
openDetails();
|
|
2274
2646
|
const toggle: HTMLElement = screen.getByRole("button", {
|
|
2275
2647
|
name: /Active incidents \(7 total\)/,
|
|
2276
2648
|
});
|
|
@@ -2315,18 +2687,40 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2315
2687
|
).toBeUndefined();
|
|
2316
2688
|
});
|
|
2317
2689
|
|
|
2318
|
-
|
|
2690
|
+
/*
|
|
2691
|
+
* Collapsed, the header answers "what did it do, and did it touch
|
|
2692
|
+
* anything?". What the run cost and which model wrote the report are for
|
|
2693
|
+
* the reader who opens the details, and the verify-first note belongs on
|
|
2694
|
+
* the report it qualifies.
|
|
2695
|
+
*/
|
|
2696
|
+
test("names the model and its tokens inside the details, not in the collapsed header", async () => {
|
|
2319
2697
|
postMock.mockResolvedValue(structuredResponse() as never);
|
|
2320
2698
|
|
|
2321
2699
|
renderPanel();
|
|
2322
2700
|
await flush();
|
|
2323
2701
|
|
|
2324
2702
|
const usage: HTMLElement = screen.getByLabelText("Investigation usage");
|
|
2325
|
-
expect(usage).
|
|
2326
|
-
expect(usage).toHaveTextContent(
|
|
2703
|
+
expect(usage).toBeVisible();
|
|
2704
|
+
expect(usage).toHaveTextContent("2 telemetry queries");
|
|
2705
|
+
expect(usage).not.toHaveTextContent("tokens");
|
|
2706
|
+
expect(usage).not.toHaveTextContent("gpt-5");
|
|
2707
|
+
|
|
2708
|
+
const cost: HTMLElement = screen.getByLabelText("Model and tokens");
|
|
2709
|
+
expect(detailsBody()).toContainElement(cost);
|
|
2710
|
+
expect(cost).not.toBeVisible();
|
|
2711
|
+
expect(cost).toHaveTextContent("1,234 tokens");
|
|
2712
|
+
expect(cost).toHaveTextContent("Model gpt-5");
|
|
2713
|
+
// Counts and the guarantee are already in the header; no repeats.
|
|
2714
|
+
expect(cost).not.toHaveTextContent("telemetry");
|
|
2715
|
+
expect(cost).not.toHaveTextContent("Read-only");
|
|
2716
|
+
|
|
2717
|
+
openDetails();
|
|
2718
|
+
|
|
2719
|
+
expect(screen.getByRole("list", { name: "Model and tokens" })).toBe(cost);
|
|
2720
|
+
expect(cost).toBeVisible();
|
|
2721
|
+
expect(screen.getByLabelText("Investigation report")).toHaveTextContent(
|
|
2327
2722
|
"AI-generated first pass — verify before acting.",
|
|
2328
2723
|
);
|
|
2329
|
-
expect(usage).toHaveTextContent("2 telemetry queries");
|
|
2330
2724
|
});
|
|
2331
2725
|
|
|
2332
2726
|
test("does not ask to verify a report that does not exist", async () => {
|
|
@@ -2344,8 +2738,10 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2344
2738
|
await flush();
|
|
2345
2739
|
|
|
2346
2740
|
const usage: HTMLElement = screen.getByLabelText("Investigation usage");
|
|
2347
|
-
expect(usage).
|
|
2741
|
+
expect(usage).toHaveTextContent("3 telemetry queries");
|
|
2348
2742
|
expect(usage).not.toHaveTextContent("Model");
|
|
2743
|
+
expect(screen.queryByText(/verify before acting/)).toBeNull();
|
|
2744
|
+
expect(screen.queryByLabelText("Model and tokens")).toBeNull();
|
|
2349
2745
|
});
|
|
2350
2746
|
|
|
2351
2747
|
test("titles the act and rate blocks with headings instead of icon-in-paragraph", async () => {
|
|
@@ -2364,45 +2760,339 @@ describe("InvestigationPanel structured report", () => {
|
|
|
2364
2760
|
});
|
|
2365
2761
|
});
|
|
2366
2762
|
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2763
|
+
/*
|
|
2764
|
+
* "Evidence checked", "Investigation activity" and the usage strip used to be
|
|
2765
|
+
* three stacked boxes under the report. They are now one section that starts
|
|
2766
|
+
* collapsed: the report is the answer, this is its working. Collapsed, it
|
|
2767
|
+
* still has to say what the run did and that it changed nothing, because a
|
|
2768
|
+
* responder asks that before trusting the report at all.
|
|
2769
|
+
*/
|
|
2770
|
+
describe("InvestigationPanel run details", () => {
|
|
2771
|
+
function tabNames(): Array<string> {
|
|
2772
|
+
return within(
|
|
2773
|
+
screen.getByRole("tablist", { name: "Investigation details" }),
|
|
2774
|
+
)
|
|
2775
|
+
.getAllByRole("tab")
|
|
2776
|
+
.map((tab: HTMLElement): string => {
|
|
2777
|
+
return tab.textContent || "";
|
|
2375
2778
|
});
|
|
2376
2779
|
}
|
|
2377
2780
|
|
|
2378
|
-
test("
|
|
2379
|
-
|
|
2380
|
-
postMock.mockResolvedValue(
|
|
2381
|
-
structuredResponse({ analysisTldr: TLDR }) as never,
|
|
2382
|
-
);
|
|
2781
|
+
test("starts collapsed and still says what the run did in its header", async () => {
|
|
2782
|
+
postMock.mockResolvedValue(structuredResponse() as never);
|
|
2383
2783
|
|
|
2384
|
-
renderPanel(
|
|
2784
|
+
renderPanel();
|
|
2385
2785
|
await flush();
|
|
2386
2786
|
|
|
2387
|
-
|
|
2388
|
-
|
|
2787
|
+
const section: HTMLElement = screen.getByRole("region", {
|
|
2788
|
+
name: "Evidence and activity",
|
|
2789
|
+
});
|
|
2790
|
+
expect(section).toBe(runDetails());
|
|
2791
|
+
|
|
2792
|
+
/*
|
|
2793
|
+
* The toggle is named by the title alone: the usage line beside it is
|
|
2794
|
+
* not part of the button, so a screen reader hears a short name.
|
|
2795
|
+
*/
|
|
2796
|
+
const toggle: HTMLElement = within(section).getByRole("button", {
|
|
2797
|
+
name: "Evidence and activity",
|
|
2798
|
+
});
|
|
2799
|
+
expect(toggle).toBe(detailsToggle());
|
|
2800
|
+
expect(
|
|
2801
|
+
within(section).getByRole("heading", {
|
|
2802
|
+
level: 3,
|
|
2803
|
+
name: "Evidence and activity",
|
|
2804
|
+
}),
|
|
2805
|
+
).toContainElement(toggle);
|
|
2806
|
+
expect(toggle).toHaveAttribute("aria-expanded", "false");
|
|
2807
|
+
expect(detailsBody()).not.toBeVisible();
|
|
2808
|
+
expect(section).toContainElement(detailsBody());
|
|
2809
|
+
expect(screen.queryByRole("tablist")).toBeNull();
|
|
2810
|
+
expect(screen.queryByRole("list", { name: "Evidence checked" })).toBeNull();
|
|
2811
|
+
expect(screen.getByTestId("investigation-activity")).not.toBeVisible();
|
|
2812
|
+
|
|
2813
|
+
const usage: HTMLElement = within(section).getByRole("list", {
|
|
2814
|
+
name: "Investigation usage",
|
|
2815
|
+
});
|
|
2816
|
+
expect(usage).toBeVisible();
|
|
2817
|
+
expect(
|
|
2818
|
+
within(usage)
|
|
2819
|
+
.getAllByRole("listitem")
|
|
2820
|
+
.map((item: HTMLElement): string => {
|
|
2821
|
+
return item.textContent || "";
|
|
2822
|
+
}),
|
|
2823
|
+
).toEqual([
|
|
2824
|
+
"2 telemetry queries",
|
|
2825
|
+
"1 step",
|
|
2826
|
+
"Read-only — nothing in your systems was changed",
|
|
2827
|
+
]);
|
|
2389
2828
|
});
|
|
2390
2829
|
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2830
|
+
/*
|
|
2831
|
+
* The run's tool-call count also includes calls that failed and never
|
|
2832
|
+
* became evidence. Inside a section whose Evidence tab lists the queries,
|
|
2833
|
+
* the header has to count the same queries, or the two numbers a reader
|
|
2834
|
+
* sees side by side disagree. Without evidence the run's own count is all
|
|
2835
|
+
* there is.
|
|
2836
|
+
*/
|
|
2837
|
+
test("counts the queries the Evidence tab lists, not the run's raw call count", async () => {
|
|
2838
|
+
postMock
|
|
2839
|
+
.mockResolvedValueOnce(structuredResponse({ toolCallCount: 3 }) as never)
|
|
2840
|
+
.mockResolvedValue(
|
|
2841
|
+
structuredResponse({ toolCallCount: 3, evidence: [] }) as never,
|
|
2842
|
+
);
|
|
2394
2843
|
|
|
2395
|
-
renderPanel(
|
|
2844
|
+
renderPanel();
|
|
2396
2845
|
await flush();
|
|
2397
2846
|
|
|
2398
|
-
expect(
|
|
2847
|
+
expect(screen.getByLabelText("Investigation usage")).toHaveTextContent(
|
|
2848
|
+
"2 telemetry queries",
|
|
2849
|
+
);
|
|
2850
|
+
openDetails();
|
|
2851
|
+
expect(detailsTab(/^Evidence checked/)).toHaveTextContent(
|
|
2852
|
+
"Evidence checked2",
|
|
2853
|
+
);
|
|
2854
|
+
|
|
2855
|
+
/*
|
|
2856
|
+
* An older API: the report's own list still names the queries, so the
|
|
2857
|
+
* header follows it rather than the raw call count.
|
|
2858
|
+
*/
|
|
2859
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
2860
|
+
|
|
2861
|
+
expect(within(evidenceList()).queryAllByRole("button")).toHaveLength(0);
|
|
2862
|
+
expect(screen.getByLabelText("Investigation usage")).toHaveTextContent(
|
|
2863
|
+
"2 telemetry queries",
|
|
2864
|
+
);
|
|
2399
2865
|
});
|
|
2400
2866
|
|
|
2401
|
-
test("
|
|
2402
|
-
const onReportSummaryChange: MockFunction = getJestMockFunction();
|
|
2867
|
+
test("falls back to the run's call count when there is no evidence at all", async () => {
|
|
2403
2868
|
postMock.mockResolvedValue(
|
|
2404
|
-
completedResponse({
|
|
2405
|
-
|
|
2869
|
+
completedResponse({ toolCallCount: 3 }) as never,
|
|
2870
|
+
);
|
|
2871
|
+
|
|
2872
|
+
renderPanel();
|
|
2873
|
+
await flush();
|
|
2874
|
+
|
|
2875
|
+
expect(detailsToggle()).toHaveTextContent("Investigation activity");
|
|
2876
|
+
expect(screen.getByLabelText("Investigation usage")).toHaveTextContent(
|
|
2877
|
+
"3 telemetry queries",
|
|
2878
|
+
);
|
|
2879
|
+
});
|
|
2880
|
+
|
|
2881
|
+
test("opening reveals the tabs and the evidence list, and closing hides them again", async () => {
|
|
2882
|
+
postMock.mockResolvedValue(structuredResponse() as never);
|
|
2883
|
+
|
|
2884
|
+
renderPanel();
|
|
2885
|
+
await flush();
|
|
2886
|
+
openDetails();
|
|
2887
|
+
|
|
2888
|
+
expect(detailsBody()).toBeVisible();
|
|
2889
|
+
expect(tabNames()).toEqual(["Evidence checked2", "Activity1"]);
|
|
2890
|
+
|
|
2891
|
+
const evidenceTab: HTMLElement = detailsTab(/^Evidence checked/);
|
|
2892
|
+
expect(evidenceTab).toHaveAttribute("aria-selected", "true");
|
|
2893
|
+
expect(evidenceTab).toHaveAttribute("tabindex", "0");
|
|
2894
|
+
expect(detailsTab(/^Activity/)).toHaveAttribute("aria-selected", "false");
|
|
2895
|
+
expect(detailsTab(/^Activity/)).toHaveAttribute("tabindex", "-1");
|
|
2896
|
+
|
|
2897
|
+
// Only the selected panel is reachable, and it is named by its tab.
|
|
2898
|
+
const panel: HTMLElement = screen.getByRole("tabpanel");
|
|
2899
|
+
expect(panel).toBe(
|
|
2900
|
+
screen.getByRole("tabpanel", { name: /^Evidence checked/ }),
|
|
2901
|
+
);
|
|
2902
|
+
expect(evidenceTab).toHaveAttribute("aria-controls", panel.id);
|
|
2903
|
+
expect(panel).toHaveAttribute("tabindex", "0");
|
|
2904
|
+
expect(panel).toContainElement(evidenceList());
|
|
2905
|
+
expect(
|
|
2906
|
+
within(evidenceList()).getByRole("button", { name: /Active incidents/ }),
|
|
2907
|
+
).toBeVisible();
|
|
2908
|
+
expect(
|
|
2909
|
+
within(evidenceList()).getByRole("button", { name: /Logs 17:20/ }),
|
|
2910
|
+
).toBeVisible();
|
|
2911
|
+
expect(screen.getByTestId("investigation-activity")).not.toBeVisible();
|
|
2912
|
+
|
|
2913
|
+
fireEvent.click(detailsToggle());
|
|
2914
|
+
|
|
2915
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "false");
|
|
2916
|
+
expect(detailsBody()).not.toBeVisible();
|
|
2917
|
+
expect(screen.queryByRole("tablist")).toBeNull();
|
|
2918
|
+
expect(screen.queryByRole("tabpanel")).toBeNull();
|
|
2919
|
+
expect(screen.queryByRole("list", { name: "Evidence checked" })).toBeNull();
|
|
2920
|
+
// The header's summary does not depend on the body being open.
|
|
2921
|
+
expect(screen.getByLabelText("Investigation usage")).toBeVisible();
|
|
2922
|
+
});
|
|
2923
|
+
|
|
2924
|
+
test("switches between the evidence and activity tabs", async () => {
|
|
2925
|
+
postMock.mockResolvedValue(structuredResponse() as never);
|
|
2926
|
+
|
|
2927
|
+
renderPanel();
|
|
2928
|
+
await flush();
|
|
2929
|
+
openDetails();
|
|
2930
|
+
|
|
2931
|
+
fireEvent.click(detailsTab(/^Activity/));
|
|
2932
|
+
|
|
2933
|
+
expect(detailsTab(/^Activity/)).toHaveAttribute("aria-selected", "true");
|
|
2934
|
+
expect(detailsTab(/^Evidence checked/)).toHaveAttribute(
|
|
2935
|
+
"aria-selected",
|
|
2936
|
+
"false",
|
|
2937
|
+
);
|
|
2938
|
+
const activityPanel: HTMLElement = screen.getByRole("tabpanel", {
|
|
2939
|
+
name: /^Activity/,
|
|
2940
|
+
});
|
|
2941
|
+
expect(activityPanel).toContainElement(
|
|
2942
|
+
screen.getByTestId("investigation-activity"),
|
|
2943
|
+
);
|
|
2944
|
+
expect(screen.getByTestId("investigation-activity")).toBeVisible();
|
|
2945
|
+
expect(screen.queryByRole("list", { name: "Evidence checked" })).toBeNull();
|
|
2946
|
+
|
|
2947
|
+
// The footer belongs to the body, not to one tab.
|
|
2948
|
+
expect(
|
|
2949
|
+
screen.getByRole("list", { name: "Model and tokens" }),
|
|
2950
|
+
).toBeVisible();
|
|
2951
|
+
|
|
2952
|
+
fireEvent.click(detailsTab(/^Evidence checked/));
|
|
2953
|
+
|
|
2954
|
+
expect(evidenceList()).toBeVisible();
|
|
2955
|
+
expect(screen.getByTestId("investigation-activity")).not.toBeVisible();
|
|
2956
|
+
});
|
|
2957
|
+
|
|
2958
|
+
/*
|
|
2959
|
+
* The old disclosure advertised the raw event count and showed only the
|
|
2960
|
+
* last ten steps. Several event types only close a step, so the count the
|
|
2961
|
+
* reader sees has to be the steps the feed draws — and a finished run is
|
|
2962
|
+
* short enough to show its whole trail.
|
|
2963
|
+
*/
|
|
2964
|
+
test("counts the steps the feed draws and shows the whole finished trail", async () => {
|
|
2965
|
+
const events: JSONArray = [];
|
|
2966
|
+
|
|
2967
|
+
for (let index: number = 0; index < 24; index++) {
|
|
2968
|
+
events.push({
|
|
2969
|
+
_id: `55555555-5555-4555-8555-${String(index).padStart(12, "0")}`,
|
|
2970
|
+
sequence: index + 1,
|
|
2971
|
+
eventType:
|
|
2972
|
+
index % 2 === 0
|
|
2973
|
+
? AIRunEventType.ToolCallStarted
|
|
2974
|
+
: AIRunEventType.ToolCallCompleted,
|
|
2975
|
+
toolName: "search_logs",
|
|
2976
|
+
createdAt: new Date("2026-08-07T10:00:00.000Z"),
|
|
2977
|
+
});
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2980
|
+
countActivityStepsMock.mockReturnValue(12);
|
|
2981
|
+
postMock.mockResolvedValue(structuredResponse({ events }) as never);
|
|
2982
|
+
|
|
2983
|
+
renderPanel();
|
|
2984
|
+
await flush();
|
|
2985
|
+
|
|
2986
|
+
const usage: HTMLElement = screen.getByLabelText("Investigation usage");
|
|
2987
|
+
expect(usage).toHaveTextContent("12 steps");
|
|
2988
|
+
expect(usage).not.toHaveTextContent("24");
|
|
2989
|
+
|
|
2990
|
+
openDetails();
|
|
2991
|
+
|
|
2992
|
+
expect(tabNames()).toEqual(["Evidence checked2", "Activity12"]);
|
|
2993
|
+
expect(lastActivityProps().events).toHaveLength(24);
|
|
2994
|
+
expect(lastActivityProps()).toEqual(
|
|
2995
|
+
expect.objectContaining({
|
|
2996
|
+
hideChrome: true,
|
|
2997
|
+
showLiveIndicator: false,
|
|
2998
|
+
maxVisibleSteps: 12,
|
|
2999
|
+
}),
|
|
3000
|
+
);
|
|
3001
|
+
});
|
|
3002
|
+
|
|
3003
|
+
/*
|
|
3004
|
+
* Evidence can land on a later poll than the report. A reader who opened
|
|
3005
|
+
* the section onto the activity is reading it; the arriving evidence adds
|
|
3006
|
+
* a tab beside it rather than yanking the view to the new first tab.
|
|
3007
|
+
*/
|
|
3008
|
+
test("keeps a reader on the activity when evidence arrives after they opened it", async () => {
|
|
3009
|
+
postMock
|
|
3010
|
+
.mockResolvedValueOnce(completedResponse() as never)
|
|
3011
|
+
.mockResolvedValue(structuredResponse() as never);
|
|
3012
|
+
|
|
3013
|
+
renderPanel();
|
|
3014
|
+
await flush();
|
|
3015
|
+
openDetails();
|
|
3016
|
+
|
|
3017
|
+
expect(detailsToggle()).toHaveTextContent("Investigation activity");
|
|
3018
|
+
expect(screen.queryByRole("tablist")).toBeNull();
|
|
3019
|
+
expect(screen.getByTestId("investigation-activity")).toBeVisible();
|
|
3020
|
+
|
|
3021
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
3022
|
+
|
|
3023
|
+
expect(detailsToggle()).toHaveTextContent("Evidence and activity");
|
|
3024
|
+
expect(detailsToggle()).toHaveAttribute("aria-expanded", "true");
|
|
3025
|
+
expect(tabNames()).toEqual(["Evidence checked2", "Activity1"]);
|
|
3026
|
+
expect(detailsTab(/^Activity/)).toHaveAttribute("aria-selected", "true");
|
|
3027
|
+
expect(detailsTab(/^Evidence checked/)).toHaveAttribute(
|
|
3028
|
+
"aria-selected",
|
|
3029
|
+
"false",
|
|
3030
|
+
);
|
|
3031
|
+
expect(screen.getByTestId("investigation-activity")).toBeVisible();
|
|
3032
|
+
expect(screen.queryByRole("list", { name: "Evidence checked" })).toBeNull();
|
|
3033
|
+
});
|
|
3034
|
+
|
|
3035
|
+
/*
|
|
3036
|
+
* The counterpart: nobody has looked yet, so there is nothing to keep, and
|
|
3037
|
+
* the section opens on the evidence like any report that has some.
|
|
3038
|
+
*/
|
|
3039
|
+
test("opens on the evidence when it arrived before the reader looked", async () => {
|
|
3040
|
+
postMock
|
|
3041
|
+
.mockResolvedValueOnce(completedResponse() as never)
|
|
3042
|
+
.mockResolvedValue(structuredResponse() as never);
|
|
3043
|
+
|
|
3044
|
+
renderPanel();
|
|
3045
|
+
await flush();
|
|
3046
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
3047
|
+
openDetails();
|
|
3048
|
+
|
|
3049
|
+
expect(detailsTab(/^Evidence checked/)).toHaveAttribute(
|
|
3050
|
+
"aria-selected",
|
|
3051
|
+
"true",
|
|
3052
|
+
);
|
|
3053
|
+
expect(evidenceList()).toBeVisible();
|
|
3054
|
+
});
|
|
3055
|
+
});
|
|
3056
|
+
|
|
3057
|
+
describe("InvestigationPanel report summary callback", () => {
|
|
3058
|
+
function nonNullCalls(callback: MockFunction): Array<unknown> {
|
|
3059
|
+
return callback.mock.calls
|
|
3060
|
+
.map((call: Array<unknown>): unknown => {
|
|
3061
|
+
return call[0];
|
|
3062
|
+
})
|
|
3063
|
+
.filter((value: unknown): boolean => {
|
|
3064
|
+
return value !== null;
|
|
3065
|
+
});
|
|
3066
|
+
}
|
|
3067
|
+
|
|
3068
|
+
test("reports the TL;DR of a completed report", async () => {
|
|
3069
|
+
const onReportSummaryChange: MockFunction = getJestMockFunction();
|
|
3070
|
+
postMock.mockResolvedValue(
|
|
3071
|
+
structuredResponse({ analysisTldr: TLDR }) as never,
|
|
3072
|
+
);
|
|
3073
|
+
|
|
3074
|
+
renderPanel({ onReportSummaryChange });
|
|
3075
|
+
await flush();
|
|
3076
|
+
|
|
3077
|
+
expect(onReportSummaryChange).toHaveBeenLastCalledWith(TLDR);
|
|
3078
|
+
expect(nonNullCalls(onReportSummaryChange)).toEqual([TLDR]);
|
|
3079
|
+
});
|
|
3080
|
+
|
|
3081
|
+
test("falls back to the report's Summary as plain text without a TL;DR", async () => {
|
|
3082
|
+
const onReportSummaryChange: MockFunction = getJestMockFunction();
|
|
3083
|
+
postMock.mockResolvedValue(structuredResponse() as never);
|
|
3084
|
+
|
|
3085
|
+
renderPanel({ onReportSummaryChange });
|
|
3086
|
+
await flush();
|
|
3087
|
+
|
|
3088
|
+
expect(onReportSummaryChange).toHaveBeenLastCalledWith(REPORT_SUMMARY);
|
|
3089
|
+
});
|
|
3090
|
+
|
|
3091
|
+
test("bounds a long Summary", async () => {
|
|
3092
|
+
const onReportSummaryChange: MockFunction = getJestMockFunction();
|
|
3093
|
+
postMock.mockResolvedValue(
|
|
3094
|
+
completedResponse({
|
|
3095
|
+
analysisMarkdown: `**Summary** — ${"pool exhausted ".repeat(60)}\n\n**Root cause** — a deploy.`,
|
|
2406
3096
|
}) as never,
|
|
2407
3097
|
);
|
|
2408
3098
|
|
|
@@ -2410,10 +3100,28 @@ describe("InvestigationPanel report summary callback", () => {
|
|
|
2410
3100
|
await flush();
|
|
2411
3101
|
|
|
2412
3102
|
const summary: string = nonNullCalls(onReportSummaryChange)[0] as string;
|
|
2413
|
-
|
|
3103
|
+
// Bounded by the analysisTldr column; the header clamps it on screen.
|
|
3104
|
+
expect(summary.length).toBeLessThanOrEqual(500);
|
|
3105
|
+
expect(summary.length).toBeGreaterThan(280);
|
|
2414
3106
|
expect(summary.endsWith("…")).toBe(true);
|
|
2415
3107
|
});
|
|
2416
3108
|
|
|
3109
|
+
test("reports a TL;DR at the server's 320-character cap whole", async () => {
|
|
3110
|
+
const onReportSummaryChange: MockFunction = getJestMockFunction();
|
|
3111
|
+
const longTldr: string =
|
|
3112
|
+
"checkout-api release 2026.09.14-2 restarted at 17:52:04 with DB_POOL_MAX=10 instead of 40, so requests waited up to 2s in pg.pool.connect for an orders-db connection and p95 latency rose from ~310 ms to 2.35 s (db.client.connections.usage pinned at 10/10). Rolling back to 2026.09.14-1 cleared it, as in #1017 and #1029.";
|
|
3113
|
+
|
|
3114
|
+
expect(longTldr).toHaveLength(320);
|
|
3115
|
+
postMock.mockResolvedValue(
|
|
3116
|
+
structuredResponse({ analysisTldr: longTldr }) as never,
|
|
3117
|
+
);
|
|
3118
|
+
|
|
3119
|
+
renderPanel({ onReportSummaryChange });
|
|
3120
|
+
await flush();
|
|
3121
|
+
|
|
3122
|
+
expect(nonNullCalls(onReportSummaryChange)).toEqual([longTldr]);
|
|
3123
|
+
});
|
|
3124
|
+
|
|
2417
3125
|
test("reports null when a report has neither a TL;DR nor a Summary", async () => {
|
|
2418
3126
|
const onReportSummaryChange: MockFunction = getJestMockFunction();
|
|
2419
3127
|
postMock.mockResolvedValue(completedResponse() as never);
|
|
@@ -2561,3 +3269,333 @@ describe("InvestigationPanel report summary callback", () => {
|
|
|
2561
3269
|
expect(second).toHaveBeenLastCalledWith("A newer summary.");
|
|
2562
3270
|
});
|
|
2563
3271
|
});
|
|
3272
|
+
|
|
3273
|
+
/*
|
|
3274
|
+
* The header shows a responder's verdict next to the report's summary, so the
|
|
3275
|
+
* panel reports it on the summary's terms: once per change, null until a
|
|
3276
|
+
* report is on screen, and afresh for every subject.
|
|
3277
|
+
*/
|
|
3278
|
+
describe("InvestigationPanel verdict callback", () => {
|
|
3279
|
+
function reportedVerdicts(callback: MockFunction): Array<unknown> {
|
|
3280
|
+
return callback.mock.calls.map((call: Array<unknown>): unknown => {
|
|
3281
|
+
return call[0];
|
|
3282
|
+
});
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
function nonNullVerdicts(callback: MockFunction): Array<unknown> {
|
|
3286
|
+
return reportedVerdicts(callback).filter((value: unknown): boolean => {
|
|
3287
|
+
return value !== null;
|
|
3288
|
+
});
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
test.each(Object.values(AIRunHumanVerdict))(
|
|
3292
|
+
"reports a %s verdict saved with the completed report",
|
|
3293
|
+
async (verdict: AIRunHumanVerdict) => {
|
|
3294
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3295
|
+
postMock.mockResolvedValue(
|
|
3296
|
+
structuredResponse({ humanVerdict: verdict }) as never,
|
|
3297
|
+
);
|
|
3298
|
+
|
|
3299
|
+
renderPanel({ onVerdictChange });
|
|
3300
|
+
await flush();
|
|
3301
|
+
|
|
3302
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(verdict);
|
|
3303
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([verdict]);
|
|
3304
|
+
},
|
|
3305
|
+
);
|
|
3306
|
+
|
|
3307
|
+
test("reports null for a report nobody has rated", async () => {
|
|
3308
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3309
|
+
postMock.mockResolvedValue(structuredResponse() as never);
|
|
3310
|
+
|
|
3311
|
+
renderPanel({ onVerdictChange });
|
|
3312
|
+
await flush();
|
|
3313
|
+
|
|
3314
|
+
expect(onVerdictChange).toHaveBeenCalledWith(null);
|
|
3315
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([]);
|
|
3316
|
+
});
|
|
3317
|
+
|
|
3318
|
+
test("reports no verdict it cannot name", async () => {
|
|
3319
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3320
|
+
postMock.mockResolvedValue(
|
|
3321
|
+
structuredResponse({ humanVerdict: "Edited" }) as never,
|
|
3322
|
+
);
|
|
3323
|
+
|
|
3324
|
+
renderPanel({ onVerdictChange });
|
|
3325
|
+
await flush();
|
|
3326
|
+
|
|
3327
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([]);
|
|
3328
|
+
});
|
|
3329
|
+
|
|
3330
|
+
test.each([
|
|
3331
|
+
[
|
|
3332
|
+
"while a new run is in flight",
|
|
3333
|
+
(): ApiResponse => {
|
|
3334
|
+
return successfulResponse(
|
|
3335
|
+
investigationPayload({
|
|
3336
|
+
status: AIRunStatus.Running,
|
|
3337
|
+
humanVerdict: AIRunHumanVerdict.Confirmed,
|
|
3338
|
+
}),
|
|
3339
|
+
);
|
|
3340
|
+
},
|
|
3341
|
+
],
|
|
3342
|
+
[
|
|
3343
|
+
"while the report is still being prepared",
|
|
3344
|
+
(): ApiResponse => {
|
|
3345
|
+
return completedResponse({
|
|
3346
|
+
analysisMarkdown: null,
|
|
3347
|
+
isAnalysisPending: true,
|
|
3348
|
+
humanVerdict: AIRunHumanVerdict.Confirmed,
|
|
3349
|
+
});
|
|
3350
|
+
},
|
|
3351
|
+
],
|
|
3352
|
+
])(
|
|
3353
|
+
"reports no verdict %s",
|
|
3354
|
+
async (_label: string, response: () => ApiResponse) => {
|
|
3355
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3356
|
+
postMock.mockResolvedValue(response() as never);
|
|
3357
|
+
|
|
3358
|
+
renderPanel({ onVerdictChange });
|
|
3359
|
+
await flush();
|
|
3360
|
+
|
|
3361
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([]);
|
|
3362
|
+
},
|
|
3363
|
+
);
|
|
3364
|
+
|
|
3365
|
+
test("reports a rating the moment it is made, and a changed one", async () => {
|
|
3366
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3367
|
+
postMock
|
|
3368
|
+
.mockResolvedValueOnce(structuredResponse() as never)
|
|
3369
|
+
.mockResolvedValueOnce(successfulResponse({}) as never)
|
|
3370
|
+
.mockResolvedValueOnce(successfulResponse({}) as never);
|
|
3371
|
+
|
|
3372
|
+
renderPanel({ onVerdictChange });
|
|
3373
|
+
await flush();
|
|
3374
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([]);
|
|
3375
|
+
|
|
3376
|
+
fireEvent.click(screen.getByRole("button", { name: "Confirmed" }));
|
|
3377
|
+
// Optimistic, like the panel's own pill: before the save resolves.
|
|
3378
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(
|
|
3379
|
+
AIRunHumanVerdict.Confirmed,
|
|
3380
|
+
);
|
|
3381
|
+
await flush();
|
|
3382
|
+
|
|
3383
|
+
fireEvent.click(screen.getByRole("button", { name: "Change" }));
|
|
3384
|
+
fireEvent.click(screen.getByRole("button", { name: "Rejected" }));
|
|
3385
|
+
await flush();
|
|
3386
|
+
|
|
3387
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([
|
|
3388
|
+
AIRunHumanVerdict.Confirmed,
|
|
3389
|
+
AIRunHumanVerdict.Rejected,
|
|
3390
|
+
]);
|
|
3391
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(
|
|
3392
|
+
AIRunHumanVerdict.Rejected,
|
|
3393
|
+
);
|
|
3394
|
+
});
|
|
3395
|
+
|
|
3396
|
+
test("takes a rating back out when the save fails", async () => {
|
|
3397
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3398
|
+
postMock
|
|
3399
|
+
.mockResolvedValueOnce(structuredResponse() as never)
|
|
3400
|
+
.mockResolvedValueOnce(
|
|
3401
|
+
new HTTPErrorResponse(
|
|
3402
|
+
500,
|
|
3403
|
+
{ message: "Verdict storage is unavailable." },
|
|
3404
|
+
{},
|
|
3405
|
+
) as never,
|
|
3406
|
+
);
|
|
3407
|
+
|
|
3408
|
+
renderPanel({ onVerdictChange });
|
|
3409
|
+
await flush();
|
|
3410
|
+
fireEvent.click(screen.getByRole("button", { name: "Rejected" }));
|
|
3411
|
+
await flush();
|
|
3412
|
+
|
|
3413
|
+
expect(screen.getByRole("alert")).toHaveTextContent(
|
|
3414
|
+
"Could not save your verdict",
|
|
3415
|
+
);
|
|
3416
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([
|
|
3417
|
+
AIRunHumanVerdict.Rejected,
|
|
3418
|
+
]);
|
|
3419
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(null);
|
|
3420
|
+
});
|
|
3421
|
+
|
|
3422
|
+
test("a poll started before a rating saved cannot flip the reported verdict", async () => {
|
|
3423
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3424
|
+
const stalePoll: Deferred<ApiResponse> = createDeferred<ApiResponse>();
|
|
3425
|
+
postMock
|
|
3426
|
+
.mockResolvedValueOnce(structuredResponse() as never)
|
|
3427
|
+
.mockReturnValueOnce(stalePoll.promise as never)
|
|
3428
|
+
.mockResolvedValueOnce(successfulResponse({}) as never);
|
|
3429
|
+
|
|
3430
|
+
renderPanel({ onVerdictChange });
|
|
3431
|
+
await flush();
|
|
3432
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
3433
|
+
expect(postMock).toHaveBeenCalledTimes(2);
|
|
3434
|
+
|
|
3435
|
+
fireEvent.click(screen.getByRole("button", { name: "Confirmed" }));
|
|
3436
|
+
await flush();
|
|
3437
|
+
const callsAfterRating: number = onVerdictChange.mock.calls.length;
|
|
3438
|
+
|
|
3439
|
+
await resolveDeferred(
|
|
3440
|
+
stalePoll,
|
|
3441
|
+
structuredResponse({ humanVerdict: null }),
|
|
3442
|
+
);
|
|
3443
|
+
|
|
3444
|
+
expect(onVerdictChange).toHaveBeenCalledTimes(callsAfterRating);
|
|
3445
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(
|
|
3446
|
+
AIRunHumanVerdict.Confirmed,
|
|
3447
|
+
);
|
|
3448
|
+
});
|
|
3449
|
+
|
|
3450
|
+
test("follows a verdict another responder saves", async () => {
|
|
3451
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3452
|
+
postMock
|
|
3453
|
+
.mockResolvedValueOnce(structuredResponse() as never)
|
|
3454
|
+
.mockResolvedValue(
|
|
3455
|
+
structuredResponse({
|
|
3456
|
+
humanVerdict: AIRunHumanVerdict.Rejected,
|
|
3457
|
+
}) as never,
|
|
3458
|
+
);
|
|
3459
|
+
|
|
3460
|
+
renderPanel({ onVerdictChange });
|
|
3461
|
+
await flush();
|
|
3462
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([]);
|
|
3463
|
+
|
|
3464
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
3465
|
+
|
|
3466
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(
|
|
3467
|
+
AIRunHumanVerdict.Rejected,
|
|
3468
|
+
);
|
|
3469
|
+
});
|
|
3470
|
+
|
|
3471
|
+
test("does not repeat an unchanged verdict across polls", async () => {
|
|
3472
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3473
|
+
postMock.mockResolvedValue(
|
|
3474
|
+
structuredResponse({
|
|
3475
|
+
humanVerdict: AIRunHumanVerdict.Confirmed,
|
|
3476
|
+
}) as never,
|
|
3477
|
+
);
|
|
3478
|
+
|
|
3479
|
+
renderPanel({ onVerdictChange });
|
|
3480
|
+
await flush();
|
|
3481
|
+
const callsAfterLoad: number = onVerdictChange.mock.calls.length;
|
|
3482
|
+
|
|
3483
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
3484
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
3485
|
+
|
|
3486
|
+
expect(investigationPostCount()).toBe(3);
|
|
3487
|
+
expect(onVerdictChange).toHaveBeenCalledTimes(callsAfterLoad);
|
|
3488
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([
|
|
3489
|
+
AIRunHumanVerdict.Confirmed,
|
|
3490
|
+
]);
|
|
3491
|
+
});
|
|
3492
|
+
|
|
3493
|
+
test("drops the verdict when a new run starts", async () => {
|
|
3494
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3495
|
+
postMock
|
|
3496
|
+
.mockResolvedValueOnce(
|
|
3497
|
+
structuredResponse({
|
|
3498
|
+
humanVerdict: AIRunHumanVerdict.Confirmed,
|
|
3499
|
+
}) as never,
|
|
3500
|
+
)
|
|
3501
|
+
.mockResolvedValue(
|
|
3502
|
+
successfulResponse(
|
|
3503
|
+
investigationPayload({
|
|
3504
|
+
status: AIRunStatus.Queued,
|
|
3505
|
+
runId: NEXT_RUN_ID,
|
|
3506
|
+
}),
|
|
3507
|
+
) as never,
|
|
3508
|
+
);
|
|
3509
|
+
|
|
3510
|
+
renderPanel({ onVerdictChange });
|
|
3511
|
+
await flush();
|
|
3512
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(
|
|
3513
|
+
AIRunHumanVerdict.Confirmed,
|
|
3514
|
+
);
|
|
3515
|
+
|
|
3516
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
3517
|
+
|
|
3518
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(null);
|
|
3519
|
+
});
|
|
3520
|
+
|
|
3521
|
+
test("reports null the moment the subject changes, then the new verdict", async () => {
|
|
3522
|
+
const onVerdictChange: MockFunction = getJestMockFunction();
|
|
3523
|
+
const nextSubject: Deferred<ApiResponse> = createDeferred<ApiResponse>();
|
|
3524
|
+
postMock
|
|
3525
|
+
.mockResolvedValueOnce(
|
|
3526
|
+
structuredResponse({
|
|
3527
|
+
humanVerdict: AIRunHumanVerdict.Confirmed,
|
|
3528
|
+
}) as never,
|
|
3529
|
+
)
|
|
3530
|
+
.mockReturnValueOnce(nextSubject.promise as never);
|
|
3531
|
+
|
|
3532
|
+
const view: ReturnType<typeof render> = renderPanel({ onVerdictChange });
|
|
3533
|
+
await flush();
|
|
3534
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(
|
|
3535
|
+
AIRunHumanVerdict.Confirmed,
|
|
3536
|
+
);
|
|
3537
|
+
|
|
3538
|
+
view.rerender(
|
|
3539
|
+
<InvestigationPanel
|
|
3540
|
+
subjectType="alert"
|
|
3541
|
+
subjectId={ALERT_ID}
|
|
3542
|
+
onVerdictChange={onVerdictChange}
|
|
3543
|
+
/>,
|
|
3544
|
+
);
|
|
3545
|
+
await flush();
|
|
3546
|
+
|
|
3547
|
+
// Before the alert's report arrives, and without a stale confirmation.
|
|
3548
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(null);
|
|
3549
|
+
|
|
3550
|
+
await resolveDeferred(
|
|
3551
|
+
nextSubject,
|
|
3552
|
+
structuredResponse({
|
|
3553
|
+
runId: NEXT_RUN_ID,
|
|
3554
|
+
humanVerdict: AIRunHumanVerdict.Rejected,
|
|
3555
|
+
}),
|
|
3556
|
+
);
|
|
3557
|
+
|
|
3558
|
+
expect(onVerdictChange).toHaveBeenLastCalledWith(
|
|
3559
|
+
AIRunHumanVerdict.Rejected,
|
|
3560
|
+
);
|
|
3561
|
+
expect(nonNullVerdicts(onVerdictChange)).toEqual([
|
|
3562
|
+
AIRunHumanVerdict.Confirmed,
|
|
3563
|
+
AIRunHumanVerdict.Rejected,
|
|
3564
|
+
]);
|
|
3565
|
+
});
|
|
3566
|
+
|
|
3567
|
+
test("uses the latest callback without re-reporting", async () => {
|
|
3568
|
+
const first: MockFunction = getJestMockFunction();
|
|
3569
|
+
const second: MockFunction = getJestMockFunction();
|
|
3570
|
+
postMock.mockResolvedValue(
|
|
3571
|
+
structuredResponse({
|
|
3572
|
+
humanVerdict: AIRunHumanVerdict.Confirmed,
|
|
3573
|
+
}) as never,
|
|
3574
|
+
);
|
|
3575
|
+
|
|
3576
|
+
const view: ReturnType<typeof render> = renderPanel({
|
|
3577
|
+
onVerdictChange: first,
|
|
3578
|
+
});
|
|
3579
|
+
await flush();
|
|
3580
|
+
expect(first).toHaveBeenLastCalledWith(AIRunHumanVerdict.Confirmed);
|
|
3581
|
+
const firstCallCount: number = first.mock.calls.length;
|
|
3582
|
+
|
|
3583
|
+
view.rerender(
|
|
3584
|
+
<InvestigationPanel
|
|
3585
|
+
subjectType="incident"
|
|
3586
|
+
subjectId={INCIDENT_ID}
|
|
3587
|
+
onVerdictChange={second}
|
|
3588
|
+
/>,
|
|
3589
|
+
);
|
|
3590
|
+
await flush();
|
|
3591
|
+
expect(second).not.toHaveBeenCalled();
|
|
3592
|
+
|
|
3593
|
+
postMock.mockResolvedValue(
|
|
3594
|
+
structuredResponse({ humanVerdict: AIRunHumanVerdict.Rejected }) as never,
|
|
3595
|
+
);
|
|
3596
|
+
await tick(SETTLED_POLL_INTERVAL_MS);
|
|
3597
|
+
|
|
3598
|
+
expect(reportedVerdicts(second)).toEqual([AIRunHumanVerdict.Rejected]);
|
|
3599
|
+
expect(first).toHaveBeenCalledTimes(firstCallCount);
|
|
3600
|
+
});
|
|
3601
|
+
});
|