@oneuptime/common 13.0.4 → 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 +10 -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/RumApplication.ts +1 -1
- package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +74 -0
- package/Models/DatabaseModels/{GoogleSecOpsConnection.ts → SecurityEventConnection.ts} +61 -51
- package/Models/DatabaseModels/{GoogleSecOpsConnectionRun.ts → SecurityEventConnectionRun.ts} +24 -24
- 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/TelemetryIngestionKey.ts +2 -2
- package/Models/DatabaseModels/ThreatIntelFeed.ts +1 -1
- package/Server/API/AIInvestigationAPI.ts +484 -24
- 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 +380 -0
- package/Server/API/StatusPageAPI.ts +308 -199
- package/Server/API/TelemetryAPI.ts +402 -265
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.ts +99 -0
- 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 +16 -0
- package/Server/Middleware/TelemetryIngest.ts +101 -6
- 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/ExceptionAggregationService.ts +7 -16
- 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 +10 -4
- package/Server/Services/InventoryItemService.ts +28 -0
- 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/LogAggregationService.ts +17 -23
- package/Server/Services/MetricAggregationService.ts +4 -14
- 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/{GoogleSecOpsConnectionRunService.ts → SecurityEventConnectionRunService.ts} +1 -1
- package/Server/Services/SecurityEventConnectionService.ts +590 -0
- 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/TraceAggregationService.ts +77 -28
- 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/AnalyticsDatabase/ModelPermission.ts +9 -0
- 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/Chat/ObservabilityAssistant.ts +13 -1
- package/Server/Utils/AI/IncidentAIContextBuilder.ts +39 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +15 -1
- package/Server/Utils/AI/SRE/InvestigationEvidence.ts +658 -0
- package/Server/Utils/AI/SRE/InvestigationReferences.ts +324 -0
- package/Server/Utils/AI/Toolbox/AlertTools.ts +37 -1
- package/Server/Utils/AI/Toolbox/IncidentTools.ts +22 -1
- package/Server/Utils/AI/Toolbox/Index.ts +38 -0
- package/Server/Utils/AI/Toolbox/SloTools.ts +416 -51
- package/Server/Utils/AI/Toolbox/TimelineTools.ts +9 -2
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +80 -0
- 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/MonitorCriteriaEvaluator.ts +5 -3
- 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/AwsSecurityHub/AwsSecurityHubClient.ts +1108 -0
- package/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.ts +732 -0
- package/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.ts +497 -0
- package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.ts +689 -0
- package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.ts +767 -0
- package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.ts +571 -0
- package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.ts +827 -0
- package/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.ts +609 -74
- package/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.ts +2101 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.ts +610 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.ts +549 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.ts +830 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.ts +684 -0
- package/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.ts +487 -0
- package/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.ts +778 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.ts +1182 -0
- package/Server/Utils/SecurityEvent/{GoogleSecOps/GoogleSecOpsRunExecutor.ts → Connectors/SecurityEventConnectionRunExecutor.ts} +165 -76
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.ts +306 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.ts +55 -0
- package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.ts +709 -0
- package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.ts +596 -0
- package/Server/Utils/SecurityEvent/Connectors/Types.ts +431 -0
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +1 -1
- package/Server/Utils/SecurityEvent/SecurityEventDedupe.ts +81 -0
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +2 -2
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +902 -40
- 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/StartServer.ts +10 -0
- package/Server/Utils/StatusPage/MonitorRulePatternValidator.ts +6 -43
- package/Server/Utils/StatusPageResource.ts +50 -5
- package/Server/Utils/Telemetry/EntityRegistry.ts +8 -0
- package/Server/Utils/Telemetry/KubernetesResourceAttributes.ts +108 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +174 -93
- package/Server/Utils/Telemetry/ResourceFacetPlanner.ts +251 -0
- package/Server/Utils/Telemetry/ResourceFacetResolver.ts +248 -413
- package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +668 -0
- package/Server/Utils/Telemetry/TraceContextPropagation.ts +348 -0
- package/Server/Utils/Telemetry.ts +18 -0
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +1063 -1
- package/Tests/App/Dashboard/AIRootCauseFeedItem.test.tsx +285 -0
- package/Tests/App/Dashboard/AddWidgetModal.test.tsx +4 -1
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +242 -0
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +307 -0
- package/Tests/App/Dashboard/AlertEpisodeViewFields.test.tsx +601 -15
- 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 +943 -0
- package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +168 -1
- package/Tests/App/Dashboard/CloudResourceTelemetryScope.test.ts +41 -0
- package/Tests/App/Dashboard/ConnectionTestModal.test.tsx +604 -0
- package/Tests/App/Dashboard/ConnectorTestReportView.test.tsx +755 -0
- 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/DashboardLazyPages.test.tsx +153 -6
- 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/EntityDetailPanel.test.tsx +165 -0
- package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +340 -0
- package/Tests/App/Dashboard/EpisodeChangeState.test.tsx +1069 -0
- package/Tests/App/Dashboard/EpisodeMembersCard.test.tsx +772 -0
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +2450 -0
- package/Tests/App/Dashboard/EventOverviewSkeleton.test.tsx +210 -0
- package/Tests/App/Dashboard/EventStatBar.test.tsx +392 -0
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +247 -0
- package/Tests/App/Dashboard/ExceptionAIAssistance.test.tsx +606 -0
- package/Tests/App/Dashboard/ExceptionBreadcrumbTimeline.test.tsx +273 -0
- package/Tests/App/Dashboard/ExceptionDetailSideMenu.test.tsx +176 -0
- package/Tests/App/Dashboard/ExceptionOverviewCards.test.tsx +366 -0
- package/Tests/App/Dashboard/ExceptionSegmentedControl.test.tsx +1020 -0
- package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +371 -0
- package/Tests/App/Dashboard/ExceptionStackFrameViewer.test.tsx +440 -0
- package/Tests/App/Dashboard/ExceptionSummary.test.tsx +381 -0
- package/Tests/App/Dashboard/ExceptionTriage.test.tsx +306 -0
- package/Tests/App/Dashboard/ExceptionsResourceFacets.test.tsx +604 -0
- package/Tests/App/Dashboard/ExceptionsViewerEntityChips.test.tsx +706 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +32 -0
- package/Tests/App/Dashboard/IncidentEpisodeViewFields.test.tsx +618 -13
- package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +254 -207
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +303 -135
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +1472 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +303 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1931 -25
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +159 -2
- package/Tests/App/Dashboard/InvestigationReferenceLink.test.tsx +177 -0
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +1398 -0
- package/Tests/App/Dashboard/InvestigationRunDetails.test.tsx +1166 -0
- package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +437 -0
- package/Tests/App/Dashboard/KubernetesImageReferenceView.test.tsx +114 -0
- package/Tests/App/Dashboard/KubernetesLogsTabChips.test.tsx +285 -0
- package/Tests/App/Dashboard/LogsEntityChipNames.test.tsx +316 -0
- package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +361 -0
- package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +65 -0
- package/Tests/App/Dashboard/NetworkTopologyLiveView.test.tsx +5 -0
- package/Tests/App/Dashboard/ProfileTableEntityNames.test.tsx +432 -0
- package/Tests/App/Dashboard/ProfileViewEntityName.test.tsx +250 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +10 -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/ResourceLogsTabsBareLayout.test.tsx +700 -0
- package/Tests/App/Dashboard/ResourcePageEntityNameProps.test.tsx +803 -0
- package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +11 -1
- package/Tests/App/Dashboard/ScheduledMaintenanceChangeState.test.tsx +1026 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +436 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +1195 -0
- package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +1764 -0
- package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +1958 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsEmptyState.test.tsx +448 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +1455 -0
- package/Tests/App/Dashboard/SecurityEventSeverityPill.test.tsx +233 -0
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +282 -0
- package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +247 -0
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +375 -274
- package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +410 -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/TelemetryResourceRetentionSettings.test.tsx +774 -0
- package/Tests/App/Dashboard/TopErrorsPanelResourceNames.test.tsx +316 -0
- package/Tests/App/Dashboard/TopologyConnectivitySection.test.tsx +206 -0
- package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +30 -0
- package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +88 -24
- package/Tests/App/Dashboard/TraceExplorer.test.tsx +1590 -0
- package/Tests/App/Dashboard/TraceWaterfall.test.tsx +488 -0
- package/Tests/App/Dashboard/TracesAnalyticsSeriesLabels.test.tsx +367 -0
- package/Tests/App/Dashboard/TracesEntityNames.test.tsx +617 -0
- package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +613 -0
- package/Tests/App/Dashboard/UseBulkShortenDeviceNames.test.tsx +1312 -0
- package/Tests/App/Dashboard/UseServiceNames.test.tsx +359 -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 +13 -7
- 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/InventoryItemNaming.test.ts +132 -16
- 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 +197 -22
- package/Tests/Server/API/AIInvestigationAPI.test.ts +611 -2
- package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +1098 -0
- 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 +1750 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +644 -1
- package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +857 -0
- package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +1084 -0
- package/Tests/Server/API/TelemetryFacetsAPI.test.ts +810 -0
- package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +240 -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/Middleware/TelemetryIngestBrowserKey.test.ts +229 -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/InventoryItemDisplayName.test.ts +66 -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/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
- 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 +1754 -0
- 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/TelemetryIngestionKeyValidation.test.ts +53 -0
- package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +218 -0
- package/Tests/Server/Services/TelemetryResourceFacetFilters.test.ts +155 -1
- package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +288 -0
- package/Tests/Server/Services/TraceAggregationExceptionScope.test.ts +142 -0
- package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +85 -24
- 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 +34 -11
- package/Tests/Server/Utils/AI/InvestigationEvidence.test.ts +1395 -0
- package/Tests/Server/Utils/AI/InvestigationReferences.test.ts +616 -0
- 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/AI/TimelineTools.test.ts +119 -0
- package/Tests/Server/Utils/AI/Toolbox/AIToolbox.test.ts +151 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +65 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorExceptionScope.test.ts +224 -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/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +55 -2
- 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/AwsSecurityHub/AwsSecurityHubClient.test.ts +1240 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.test.ts +1853 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorFetchSummary.test.ts +261 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.test.ts +1184 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.test.ts +1066 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.test.ts +1568 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.test.ts +930 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.test.ts +1409 -0
- 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} +9 -5
- 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} +249 -222
- 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/Connectors/GoogleSecOps/GoogleSecOpsSearchDetections.test.ts +763 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsTesterIntegration.test.ts +421 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.test.ts +763 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.test.ts +1296 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.test.ts +1102 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.test.ts +1174 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.test.ts +1032 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.test.ts +1558 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.test.ts +4483 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.test.ts +1178 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.test.ts +1215 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.test.ts +1068 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.test.ts +1004 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayOriginAllowlist.test.ts +41 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +1966 -179
- 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/Server/Utils/Telemetry/KubernetesResourceAttributes.test.ts +162 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +460 -13
- package/Tests/Server/Utils/Telemetry/ResourceFacetPlanner.test.ts +678 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +348 -2
- package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +525 -0
- package/Tests/Server/Utils/Telemetry/TraceContextPropagation.test.ts +420 -0
- 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 +133 -0
- package/Tests/Types/Rum/SessionReplayTransportContracts.test.ts +95 -0
- package/Tests/Types/SecurityEvent/Connectors/ConnectorDiagnostics.test.ts +82 -0
- package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +339 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +217 -0
- package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +200 -0
- package/Tests/Types/Telemetry/ExceptionSpanScope.test.ts +89 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +96 -0
- package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +304 -0
- package/Tests/UI/Components/ActiveFilterChipsLockedFilters.test.tsx +411 -0
- package/Tests/UI/Components/AlertBanner.test.tsx +319 -0
- package/Tests/UI/Components/BulkArchiveActionsCopy.test.tsx +310 -0
- package/Tests/UI/Components/Card.test.tsx +312 -1
- package/Tests/UI/Components/CardModelDetailHeaderLayout.test.tsx +253 -0
- package/Tests/UI/Components/CardModelDetailRefresher.test.tsx +342 -0
- package/Tests/UI/Components/Checkbox.test.tsx +79 -0
- package/Tests/UI/Components/CopyTextButton.test.tsx +142 -0
- package/Tests/UI/Components/Detail/DetailIdIsUnique.test.tsx +87 -0
- package/Tests/UI/Components/DetailCompactStyle.test.tsx +621 -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/ErrorBoundary.test.tsx +60 -0
- package/Tests/UI/Components/FacetSections.test.tsx +581 -0
- package/Tests/UI/Components/FacetSidebarControls.test.tsx +812 -0
- package/Tests/UI/Components/FacetVisibility.test.ts +429 -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 +788 -0
- package/Tests/UI/Components/LogsEntityNames.test.ts +1769 -0
- package/Tests/UI/Components/LogsEntityNamesComponents.test.tsx +696 -0
- package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +600 -0
- package/Tests/UI/Components/LogsViewerEntityNames.test.tsx +713 -0
- package/Tests/UI/Components/MarkdownInlineReferences.test.tsx +2079 -0
- package/Tests/UI/Components/MemberRoleAssignment.test.tsx +446 -0
- package/Tests/UI/Components/ModelDetailRefetch.test.tsx +397 -0
- package/Tests/UI/Components/ModelListRefetch.test.tsx +233 -0
- package/Tests/UI/Components/ModelPageModelChange.test.tsx +409 -0
- package/Tests/UI/Components/MoreMenu.test.tsx +133 -0
- package/Tests/UI/Components/MoreMenuMotion.test.tsx +84 -3
- package/Tests/UI/Components/PaginationIntegration.test.tsx +25 -0
- package/Tests/UI/Components/ResourceFacetConfigs.test.ts +172 -0
- 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/SavedViewsSidebarIntegration.test.tsx +32 -14
- package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +44 -1
- package/Tests/UI/Components/TelemetryActiveFilterChipsLockedFilters.test.tsx +367 -0
- package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +718 -0
- package/Tests/UI/Monitor/EvaluationLogList.test.tsx +303 -0
- package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +55 -1
- package/Tests/UI/Rum/FidelityNotices.test.ts +22 -0
- package/Tests/UI/Rum/RecordingHealthCard.test.tsx +120 -136
- package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +988 -0
- package/Tests/UI/Rum/ReplayCard.test.tsx +32 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +709 -12
- package/Tests/UI/Rum/ReplayEngine.test.ts +154 -0
- package/Tests/UI/Rum/ReplayHeader.test.tsx +284 -124
- package/Tests/UI/Rum/ReplayPinControl.test.tsx +189 -10
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +286 -12
- 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 +1228 -173
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +433 -3
- package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +1391 -0
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +222 -0
- package/Tests/UI/Rum/ReplayUi.test.tsx +189 -2
- package/Tests/UI/Rum/ReplayUserSessionsMenu.test.tsx +91 -0
- package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +1 -1
- package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +585 -0
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +844 -51
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +29 -1
- package/Tests/UI/Telemetry/TelemetryDetailPanel.test.tsx +288 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +31 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +6 -0
- package/Tests/UI/Utils/Clipboard.test.ts +154 -0
- package/Tests/UI/Utils/DashboardStackingLayers.test.ts +8 -1
- package/Tests/UI/Utils/Navigation.test.ts +24 -0
- package/Tests/UI/Utils/RuleRunClient.test.ts +303 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +2206 -0
- package/Tests/UI/Utils/Telemetry/UseTelemetryEntityNames.test.tsx +844 -0
- package/Tests/Utils/AI/InvestigationReport.test.ts +2430 -0
- package/Tests/Utils/APIOutgoingRequestTracer.test.ts +137 -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/Rum/SessionReplayHealthDiagnosis.test.ts +40 -0
- package/Tests/Utils/Rum/SessionReplayRecordingEnded.test.ts +619 -0
- package/Tests/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.test.ts +631 -0
- package/Tests/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.test.ts +479 -0
- package/Tests/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.test.ts +507 -0
- package/Tests/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.test.ts +686 -0
- package/Tests/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.test.ts +474 -0
- package/Tests/Utils/SecurityEvent/Connectors/OktaNormalizer.test.ts +736 -0
- package/Tests/Utils/SecurityEvent/Connectors/SplunkNormalizer.test.ts +407 -0
- package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.test.ts +129 -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/CrossSignalScope.test.ts +57 -1
- package/Tests/Utils/Telemetry/EntityRelationship.test.ts +36 -0
- package/Tests/Utils/Telemetry/LockedFilterSearch.test.ts +521 -0
- package/Tests/Utils/Telemetry/NetworkHost.test.ts +48 -0
- package/Tests/Utils/Telemetry/OriginAllowList.test.ts +154 -0
- package/Tests/Utils/Traces/CriticalPath.test.ts +25 -0
- package/Types/AI/AIChatTypes.ts +8 -0
- package/Types/AI/InvestigationEvidence.ts +96 -0
- 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/MonitorEvaluationSummary.ts +5 -0
- 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 +129 -2
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +5 -0
- package/Types/Rules/RuleRun.ts +518 -0
- package/Types/Rum/SessionReplay.ts +109 -0
- package/Types/Rum/SessionReplayApi.ts +49 -0
- package/Types/SecurityEvent/Connectors/ConnectorDiagnostics.ts +117 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.ts +113 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +599 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.ts +45 -0
- package/Types/SecurityEvent/GoogleSecOpsRegion.ts +34 -0
- 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/EntityType.ts +14 -0
- package/Types/Telemetry/ExceptionSpanScope.ts +83 -0
- package/Types/Telemetry/LockedFilterDetail.ts +25 -0
- package/Types/Telemetry/ResourceEntityFacet.ts +17 -10
- package/Types/Telemetry/ResourceFacetCatalog.ts +171 -0
- 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/Card/Card.tsx +118 -83
- package/UI/Components/Checkbox/Checkbox.tsx +8 -5
- package/UI/Components/CopyTextButton/CopyTextButton.tsx +7 -1
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +4 -1
- package/UI/Components/Detail/Detail.tsx +145 -23
- 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/ErrorBoundary.tsx +38 -0
- package/UI/Components/Forms/ModelForm.tsx +6 -5
- package/UI/Components/LabelRule/LabelRuleTable.tsx +8 -2
- package/UI/Components/LogsViewer/LogsEntityNames.ts +912 -0
- package/UI/Components/LogsViewer/LogsViewer.tsx +152 -77
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +17 -11
- package/UI/Components/LogsViewer/components/FacetSection.tsx +66 -79
- package/UI/Components/LogsViewer/components/FacetValueRow.tsx +17 -2
- package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +45 -5
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +100 -19
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +156 -39
- package/UI/Components/LogsViewer/components/LogsTable.tsx +30 -8
- package/UI/Components/LogsViewer/types.ts +6 -0
- package/UI/Components/Markdown.tsx/InlineReferences.tsx +628 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +385 -312
- package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +50 -22
- package/UI/Components/ModelDetail/CardModelDetail.tsx +15 -0
- package/UI/Components/ModelDetail/ModelDetail.tsx +64 -19
- package/UI/Components/ModelList/ModelList.tsx +33 -8
- package/UI/Components/MoreMenu/MoreMenu.tsx +14 -3
- package/UI/Components/Page/ModelPage.tsx +119 -54
- 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/Table/Table.tsx +8 -0
- package/UI/Components/Table/TableRow.tsx +13 -5
- package/UI/Components/TelemetryViewer/FacetVisibility.ts +229 -0
- package/UI/Components/TelemetryViewer/ResourceFacetConfigs.ts +46 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +7 -0
- package/UI/Components/TelemetryViewer/components/FacetSearchInput.tsx +79 -0
- package/UI/Components/TelemetryViewer/components/FacetSectionHeader.tsx +69 -0
- package/UI/Components/TelemetryViewer/components/FacetShowMoreButton.tsx +36 -0
- package/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.tsx +88 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +430 -0
- package/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.tsx +14 -10
- package/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.tsx +203 -10
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSection.tsx +60 -73
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +94 -7
- package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +17 -2
- package/UI/Components/TelemetryViewer/types.ts +19 -0
- package/UI/Components/TelemetryViewer/useFacetSearchExemptions.ts +158 -0
- package/UI/Components/TelemetryViewer/useFacetSectionSearch.ts +102 -0
- package/UI/Utils/Clipboard.ts +68 -2
- package/UI/Utils/Navigation.ts +17 -2
- package/UI/Utils/Rules/RuleRunClient.ts +178 -0
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +628 -0
- package/UI/Utils/Telemetry/UseTelemetryEntityNames.ts +151 -0
- package/Utils/AI/InvestigationReport.ts +1789 -0
- package/Utils/API.ts +90 -1
- 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/Rum/SessionReplayHealth.ts +11 -0
- package/Utils/Rum/SessionReplayRecordingEnded.ts +134 -0
- package/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.ts +427 -0
- package/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.ts +197 -0
- package/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.ts +464 -0
- package/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.ts +567 -0
- package/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.ts +299 -0
- package/Utils/SecurityEvent/Connectors/OktaNormalizer.ts +467 -0
- package/Utils/SecurityEvent/Connectors/SplunkNormalizer.ts +439 -0
- package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +124 -12
- 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/CrossSignalScope.ts +22 -8
- package/Utils/Telemetry/EntityRelationship.ts +8 -0
- package/Utils/Telemetry/LockedFilterSearch.ts +366 -0
- package/Utils/Telemetry/NetworkHost.ts +43 -0
- package/Utils/Telemetry/OriginAllowList.ts +139 -4
- package/Utils/Traces/CriticalPath.ts +10 -4
- 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 +10 -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/RumApplication.js +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.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/{GoogleSecOpsConnection.js → SecurityEventConnection.js} +87 -75
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js.map +1 -0
- package/build/dist/Models/DatabaseModels/{GoogleSecOpsConnectionRun.js → SecurityEventConnectionRun.js} +37 -37
- package/build/dist/Models/DatabaseModels/SecurityEventConnectionRun.js.map +1 -0
- 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/TelemetryIngestionKey.js +2 -2
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +336 -27
- package/build/dist/Server/API/AIInvestigationAPI.js.map +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 +263 -0
- package/build/dist/Server/API/SecurityEventConnectionAPI.js.map +1 -0
- package/build/dist/Server/API/StatusPageAPI.js +236 -154
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +248 -170
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js.map +1 -0
- 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 +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +57 -4
- package/build/dist/Server/Middleware/TelemetryIngest.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/ExceptionAggregationService.js +7 -16
- package/build/dist/Server/Services/ExceptionAggregationService.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 +10 -4
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +22 -0
- package/build/dist/Server/Services/InventoryItemService.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/LogAggregationService.js +8 -17
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +4 -14
- package/build/dist/Server/Services/MetricAggregationService.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/{GoogleSecOpsConnectionRunService.js → SecurityEventConnectionRunService.js} +2 -2
- package/build/dist/Server/Services/SecurityEventConnectionRunService.js.map +1 -0
- package/build/dist/Server/Services/SecurityEventConnectionService.js +396 -0
- package/build/dist/Server/Services/SecurityEventConnectionService.js.map +1 -0
- 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/TraceAggregationService.js +51 -25
- package/build/dist/Server/Services/TraceAggregationService.js.map +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/Types/AnalyticsDatabase/ModelPermission.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.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/Chat/ObservabilityAssistant.js +3 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.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/SRE/AIInvestigationEngine.js +14 -7
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js +468 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js +230 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js.map +1 -0
- 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/Index.js +32 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.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/AI/Toolbox/TimelineTools.js +6 -2
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +59 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.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/MonitorCriteriaEvaluator.js +5 -3
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.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/AwsSecurityHub/AwsSecurityHubClient.js +752 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js +493 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js +354 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js +405 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js +466 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js +344 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js +511 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.js +401 -68
- 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/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js +406 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js +336 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js +474 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js +417 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js +314 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js +494 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js +839 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/{GoogleSecOps/GoogleSecOpsRunExecutor.js → Connectors/SecurityEventConnectionRunExecutor.js} +77 -50
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js +214 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js +42 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js +494 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js +379 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js +122 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +1 -1
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js +52 -0
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +2 -2
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +599 -32
- 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/StartServer.js +10 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- 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/Server/Utils/Telemetry/EntityRegistry.js +8 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js +80 -0
- package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +122 -67
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js +146 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +174 -248
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +492 -0
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js +259 -0
- package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry.js +11 -5
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/AI/InvestigationEvidence.js +2 -0
- package/build/dist/Types/AI/InvestigationEvidence.js.map +1 -0
- 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 +116 -2
- 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/SessionReplay.js +95 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js +18 -0
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js +17 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +439 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js +39 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js.map +1 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js +35 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js.map +1 -0
- 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/EntityType.js +14 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ExceptionSpanScope.js +59 -0
- package/build/dist/Types/Telemetry/ExceptionSpanScope.js.map +1 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js +16 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js.map +1 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js +16 -10
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js.map +1 -1
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +119 -0
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -0
- 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/Card/Card.js +34 -17
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js +6 -4
- package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +74 -15
- 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/ErrorBoundary.js +34 -0
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- 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/LogsEntityNames.js +535 -0
- package/build/dist/UI/Components/LogsViewer/LogsEntityNames.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +117 -57
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +3 -7
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js +31 -44
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +17 -3
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +19 -3
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +64 -18
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +100 -41
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +13 -5
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js +403 -0
- package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +197 -179
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +30 -21
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +12 -0
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js +46 -12
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelList/ModelList.js +26 -7
- package/build/dist/UI/Components/ModelList/ModelList.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/Page/ModelPage.js +62 -34
- package/build/dist/UI/Components/Page/ModelPage.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/Table/Table.js +3 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +8 -1
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +111 -0
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.js +22 -0
- package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.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/FacetSearchInput.js +36 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSearchInput.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js +21 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js +14 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js +27 -0
- package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +202 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js +2 -6
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js +111 -12
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js +27 -40
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +70 -10
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +17 -3
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/types.js +0 -4
- package/build/dist/UI/Components/TelemetryViewer/types.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js +70 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js +52 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js.map +1 -0
- package/build/dist/UI/Utils/Clipboard.js +59 -2
- package/build/dist/UI/Utils/Clipboard.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +11 -2
- package/build/dist/UI/Utils/Navigation.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 +479 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js +113 -0
- package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js.map +1 -0
- package/build/dist/Utils/AI/InvestigationReport.js +1241 -0
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -0
- package/build/dist/Utils/API.js +25 -0
- package/build/dist/Utils/API.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/Rum/SessionReplayHealth.js +10 -0
- package/build/dist/Utils/Rum/SessionReplayHealth.js.map +1 -1
- package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js +54 -0
- package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js +311 -0
- package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js +150 -0
- package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js +328 -0
- package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js +405 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js +212 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js +351 -0
- package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js +348 -0
- package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +103 -10
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
- 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/CrossSignalScope.js +16 -5
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityRelationship.js +7 -0
- package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js +252 -0
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js.map +1 -0
- package/build/dist/Utils/Telemetry/NetworkHost.js +39 -0
- package/build/dist/Utils/Telemetry/NetworkHost.js.map +1 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js +105 -4
- package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -1
- package/build/dist/Utils/Traces/CriticalPath.js +9 -4
- package/build/dist/Utils/Traces/CriticalPath.js.map +1 -1
- package/package.json +1 -1
- package/Server/API/GoogleSecOpsConnectionAPI.ts +0 -79
- package/Server/Services/GoogleSecOpsConnectionService.ts +0 -101
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +0 -774
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +0 -423
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +0 -724
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +0 -248
- package/Tests/Server/Services/GoogleSecOpsDiagnosticsModel.test.ts +0 -153
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +0 -711
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +0 -838
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +0 -716
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +0 -860
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +0 -1231
- package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +0 -600
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +0 -56
- package/UI/Components/GanttChart/Bar/BarLabel.tsx +0 -17
- package/UI/Components/GanttChart/Bar/Index.tsx +0 -149
- package/UI/Components/GanttChart/ChartContainer.tsx +0 -50
- package/UI/Components/GanttChart/Index.tsx +0 -90
- package/UI/Components/GanttChart/Row/Index.tsx +0 -22
- package/UI/Components/GanttChart/Row/Row.tsx +0 -231
- package/UI/Components/GanttChart/Row/RowLabel.tsx +0 -30
- package/UI/Components/GanttChart/Rows.tsx +0 -59
- package/UI/Components/GanttChart/Timeline/Index.tsx +0 -46
- package/UI/Components/GanttChart/Timeline/TimelineInterval.tsx +0 -33
- package/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.tsx +0 -43
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +0 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js.map +0 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +0 -56
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +0 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js.map +0 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +0 -62
- 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/GoogleSecOpsPoller.js +0 -577
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +0 -1
- 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/GanttChart/Bar/BarLabel.js +0 -8
- package/build/dist/UI/Components/GanttChart/Bar/BarLabel.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Bar/Index.js +0 -77
- package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/ChartContainer.js +0 -33
- package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Index.js +0 -39
- package/build/dist/UI/Components/GanttChart/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/Index.js +0 -7
- package/build/dist/UI/Components/GanttChart/Row/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/Row.js +0 -106
- package/build/dist/UI/Components/GanttChart/Row/Row.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/RowLabel.js +0 -10
- package/build/dist/UI/Components/GanttChart/Row/RowLabel.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Rows.js +0 -19
- package/build/dist/UI/Components/GanttChart/Rows.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/Index.js +0 -16
- package/build/dist/UI/Components/GanttChart/Timeline/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js +0 -13
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js +0 -13
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js.map +0 -1
|
@@ -0,0 +1,1994 @@
|
|
|
1
|
+
import { afterEach, describe, expect, jest, test } from "@jest/globals";
|
|
2
|
+
import GoogleSecOpsClient, {
|
|
3
|
+
CuratedRuleDetectionCount,
|
|
4
|
+
FetchAlertsResult,
|
|
5
|
+
SearchDetectionsResult,
|
|
6
|
+
} from "../../../../../../Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsClient";
|
|
7
|
+
import GoogleSecOpsConnector from "../../../../../../Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector";
|
|
8
|
+
import {
|
|
9
|
+
ConnectorFetchFailureSummary,
|
|
10
|
+
ConnectorFetchOptions,
|
|
11
|
+
ConnectorFetchPurpose,
|
|
12
|
+
ConnectorFetchResult,
|
|
13
|
+
ConnectorFetchWindow,
|
|
14
|
+
readConnectorChecks,
|
|
15
|
+
readConnectorFetchSummary,
|
|
16
|
+
} from "../../../../../../Server/Utils/SecurityEvent/Connectors/Types";
|
|
17
|
+
import APIException from "../../../../../../Types/Exception/ApiException";
|
|
18
|
+
import BadDataException from "../../../../../../Types/Exception/BadDataException";
|
|
19
|
+
import { JSONObject } from "../../../../../../Types/JSON";
|
|
20
|
+
import NormalizedSecurityEvent from "../../../../../../Types/SecurityEvent/NormalizedSecurityEvent";
|
|
21
|
+
import {
|
|
22
|
+
SecurityConnectorCheck,
|
|
23
|
+
SecurityConnectorSample,
|
|
24
|
+
} from "../../../../../../Types/SecurityEvent/Connectors/ConnectorDiagnostics";
|
|
25
|
+
import GoogleSecOpsAlertNormalizer from "../../../../../../Utils/SecurityEvent/GoogleSecOpsAlertNormalizer";
|
|
26
|
+
import { contentHashEventUid } from "../../../../../../Utils/SecurityEvent/NormalizerHelpers";
|
|
27
|
+
import { getJestSpyOn } from "../../../../../Spy";
|
|
28
|
+
import {
|
|
29
|
+
AlertsCall,
|
|
30
|
+
ClientFactoryCall,
|
|
31
|
+
ConnectorHarness,
|
|
32
|
+
FIXTURE_CURATED_RULE_ID,
|
|
33
|
+
FakeClient,
|
|
34
|
+
SearchCall,
|
|
35
|
+
checkByKey,
|
|
36
|
+
connectorWith,
|
|
37
|
+
detection,
|
|
38
|
+
fetchOptions,
|
|
39
|
+
fetched,
|
|
40
|
+
makeFakeClient,
|
|
41
|
+
page,
|
|
42
|
+
poisonDetection,
|
|
43
|
+
rejectionOf,
|
|
44
|
+
secOpsSettings,
|
|
45
|
+
statusesOf,
|
|
46
|
+
} from "./GoogleSecOpsConnectorFixtures";
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* GoogleSecOpsConnector.fetchEvents: the three-pass read the retired
|
|
50
|
+
* GoogleSecOpsPoller ran, as a connector. One window is read as rule
|
|
51
|
+
* detections by created time, curated rule detections by created time and
|
|
52
|
+
* the alerts view by detection time, and unioned by Collection.id. These
|
|
53
|
+
* tests pin the pass requests (bases, scope, page sizes), the union, the
|
|
54
|
+
* per-pass checks and their wording, the split budgets (20 rule search
|
|
55
|
+
* pages, 200 curated requests, 16 alerts-view requests the late-alert sweep
|
|
56
|
+
* shares, the wall clock, and the poller's total request and record
|
|
57
|
+
* bounds), the alerts view's midpoint splitting, the curated-rule
|
|
58
|
+
* degradation, the failed-pass checks attached to a thrown
|
|
59
|
+
* error, the diagnostics details, samples and creation lag. The cursor,
|
|
60
|
+
* ingest and row bookkeeping around it belong to the generic poller.
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
const DAY_MS: number = 24 * 60 * 60 * 1000;
|
|
64
|
+
|
|
65
|
+
/*
|
|
66
|
+
* A scheduled poll's few minutes. A poll window shorter than a day also
|
|
67
|
+
* sweeps the alerts view over the day before it (late alerts); DAY_WINDOW
|
|
68
|
+
* already reaches back a day and does not.
|
|
69
|
+
*/
|
|
70
|
+
const WINDOW: ConnectorFetchWindow = {
|
|
71
|
+
startTime: new Date("2026-09-14T11:54:00.000Z"),
|
|
72
|
+
endTime: new Date("2026-09-14T12:00:00.000Z"),
|
|
73
|
+
};
|
|
74
|
+
const DAY_WINDOW: ConnectorFetchWindow = {
|
|
75
|
+
startTime: new Date("2026-09-13T12:00:00.000Z"),
|
|
76
|
+
endTime: new Date("2026-09-14T12:00:00.000Z"),
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
async function fetchWith(
|
|
80
|
+
fake: FakeClient,
|
|
81
|
+
overrides: {
|
|
82
|
+
options?: Partial<ConnectorFetchOptions> | undefined;
|
|
83
|
+
alertingOnly?: boolean | undefined;
|
|
84
|
+
window?: ConnectorFetchWindow | undefined;
|
|
85
|
+
} = {},
|
|
86
|
+
): Promise<ConnectorFetchResult> {
|
|
87
|
+
return connectorWith(fake.client).connector.fetchEvents(
|
|
88
|
+
secOpsSettings({ alertingOnly: overrides.alertingOnly }),
|
|
89
|
+
overrides.window || WINDOW,
|
|
90
|
+
fetchOptions(overrides.options),
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function uidsOf(result: ConnectorFetchResult): Array<string> {
|
|
95
|
+
return result.events
|
|
96
|
+
.map((event: NormalizedSecurityEvent): string => {
|
|
97
|
+
return event.eventUid;
|
|
98
|
+
})
|
|
99
|
+
.sort();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/*
|
|
103
|
+
* The alerts-view requests that read the poll window itself, without the
|
|
104
|
+
* late-alert sweep, which is the request ending where the window starts.
|
|
105
|
+
*/
|
|
106
|
+
function windowReadsOf(
|
|
107
|
+
fake: FakeClient,
|
|
108
|
+
window: ConnectorFetchWindow = WINDOW,
|
|
109
|
+
): Array<AlertsCall> {
|
|
110
|
+
return fake.alertsCalls.filter((call: AlertsCall): boolean => {
|
|
111
|
+
return call.endTime.getTime() !== window.startTime.getTime();
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function endlessPages(id: string): Array<SearchDetectionsResult> {
|
|
116
|
+
return [page([detection(id)], { nextPageToken: "again" })];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
describe("GoogleSecOpsConnector.fetchEvents passes", () => {
|
|
120
|
+
afterEach(() => {
|
|
121
|
+
jest.restoreAllMocks();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("a poll reads three passes over one window and unions them by Collection.id", async () => {
|
|
125
|
+
const fake: FakeClient = makeFakeClient({
|
|
126
|
+
rule: [page([detection("a"), detection("b")])],
|
|
127
|
+
curated: [page([detection("b"), detection("c")])],
|
|
128
|
+
// The window's alerts view, then a late-alert sweep that finds nothing.
|
|
129
|
+
alerts: [fetched([detection("c"), detection("d")]), fetched([])],
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
133
|
+
|
|
134
|
+
expect(uidsOf(result)).toEqual(["a", "b", "c", "d"]);
|
|
135
|
+
// Rule search, curated count, curated search, alerts view, sweep.
|
|
136
|
+
expect(result).toMatchObject({
|
|
137
|
+
fetchedCount: 4,
|
|
138
|
+
rejectedCount: 0,
|
|
139
|
+
failedCount: 0,
|
|
140
|
+
complete: true,
|
|
141
|
+
requestCount: 5,
|
|
142
|
+
warnings: [],
|
|
143
|
+
});
|
|
144
|
+
expect(result.checks).toEqual([
|
|
145
|
+
{
|
|
146
|
+
key: "read-rule-detections",
|
|
147
|
+
name: "Read rule detections by created time",
|
|
148
|
+
status: "pass",
|
|
149
|
+
durationMs: expect.any(Number),
|
|
150
|
+
message: "2 rule detections returned for the window by created time.",
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
key: "read-curated-detections",
|
|
154
|
+
name: "Read curated rule detections by created time",
|
|
155
|
+
status: "pass",
|
|
156
|
+
durationMs: expect.any(Number),
|
|
157
|
+
message:
|
|
158
|
+
"2 curated rule detections returned for the window by created time (1 of 1 curated rule with recent detections searched).",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
key: "read-alerts-view",
|
|
162
|
+
name: "Read alerts view by detection time",
|
|
163
|
+
status: "pass",
|
|
164
|
+
durationMs: expect.any(Number),
|
|
165
|
+
message:
|
|
166
|
+
"2 alerts returned by detection time. The configured Google SecOps instance is reachable and allows reading detections.",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
key: "read-late-alerts-view",
|
|
170
|
+
name: "Read late alerts by detection time",
|
|
171
|
+
status: "pass",
|
|
172
|
+
durationMs: expect.any(Number),
|
|
173
|
+
message:
|
|
174
|
+
"0 alerts returned with a detection time from 2026-09-13T12:00:00.000Z to 2026-09-14T11:54:00.000Z, before the window, so alerts Google made readable after their detection time are imported.",
|
|
175
|
+
},
|
|
176
|
+
]);
|
|
177
|
+
expect(result.details).toEqual({
|
|
178
|
+
basis: "created-time",
|
|
179
|
+
sourceCounts: {
|
|
180
|
+
ruleDetections: 2,
|
|
181
|
+
curatedDetections: 2,
|
|
182
|
+
alertsView: 2,
|
|
183
|
+
lateAlertsView: 0,
|
|
184
|
+
},
|
|
185
|
+
curatedRulesWithDetections: 1,
|
|
186
|
+
creationLag: { measured: 4, lateCount: 0, maxLagMinutes: 2 },
|
|
187
|
+
includeNonAlertingDetections: false,
|
|
188
|
+
});
|
|
189
|
+
for (const event of result.events) {
|
|
190
|
+
expect(event.vendorName).toBe("Google");
|
|
191
|
+
expect(event.productName).toBe("Google SecOps");
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
/*
|
|
196
|
+
* Google's searches return newest first, so a bounded read has no
|
|
197
|
+
* "everything before here was read" point; the poller narrows instead.
|
|
198
|
+
*/
|
|
199
|
+
test("never names a resume point, even when a bound stopped the read", async () => {
|
|
200
|
+
const complete: ConnectorFetchResult = await fetchWith(makeFakeClient({}));
|
|
201
|
+
const stopped: ConnectorFetchResult = await fetchWith(
|
|
202
|
+
makeFakeClient({ rule: endlessPages("endless") }),
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
expect(complete.resumeAfter).toBeUndefined();
|
|
206
|
+
expect(stopped.complete).toBe(false);
|
|
207
|
+
expect(stopped.resumeAfter).toBeUndefined();
|
|
208
|
+
expect(Object.prototype.hasOwnProperty.call(stopped, "resumeAfter")).toBe(
|
|
209
|
+
false,
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test("a poll's search passes ask for created time, the saved scope, full pages and the right route", async () => {
|
|
214
|
+
const fake: FakeClient = makeFakeClient({});
|
|
215
|
+
|
|
216
|
+
await fetchWith(fake);
|
|
217
|
+
|
|
218
|
+
expect(fake.searchCalls).toHaveLength(2);
|
|
219
|
+
expect(fake.searchCalls[0]).toMatchObject({
|
|
220
|
+
listBasis: "CREATED_TIME",
|
|
221
|
+
alertingOnly: true,
|
|
222
|
+
pageSize: 1000,
|
|
223
|
+
curated: false,
|
|
224
|
+
});
|
|
225
|
+
expect(fake.searchCalls[0]!.pageToken).toBeUndefined();
|
|
226
|
+
expect(fake.searchCalls[0]!.ruleId).toBeUndefined();
|
|
227
|
+
expect(fake.searchCalls[1]).toMatchObject({
|
|
228
|
+
listBasis: "CREATED_TIME",
|
|
229
|
+
alertingOnly: true,
|
|
230
|
+
pageSize: 1000,
|
|
231
|
+
curated: true,
|
|
232
|
+
ruleId: FIXTURE_CURATED_RULE_ID,
|
|
233
|
+
});
|
|
234
|
+
for (const call of fake.searchCalls) {
|
|
235
|
+
expect(call.startTime).toEqual(WINDOW.startTime);
|
|
236
|
+
expect(call.endTime).toEqual(WINDOW.endTime);
|
|
237
|
+
}
|
|
238
|
+
// The curated rules are counted from a week before the window to its end.
|
|
239
|
+
expect(fake.countCalls).toEqual([
|
|
240
|
+
{
|
|
241
|
+
startTime: new Date(WINDOW.startTime.getTime() - 7 * DAY_MS),
|
|
242
|
+
endTime: WINDOW.endTime,
|
|
243
|
+
},
|
|
244
|
+
]);
|
|
245
|
+
expect(fake.alertsCalls).toEqual([
|
|
246
|
+
{
|
|
247
|
+
startTime: WINDOW.startTime,
|
|
248
|
+
endTime: WINDOW.endTime,
|
|
249
|
+
maxAlerts: 1000,
|
|
250
|
+
includeNonAlertingDetections: false,
|
|
251
|
+
},
|
|
252
|
+
/*
|
|
253
|
+
* The late-alert sweep of a window shorter than a day: the 24 hours
|
|
254
|
+
* before the window's end, up to where the window's own read starts,
|
|
255
|
+
* alerts only.
|
|
256
|
+
*/
|
|
257
|
+
{
|
|
258
|
+
startTime: new Date(WINDOW.endTime.getTime() - DAY_MS),
|
|
259
|
+
endTime: WINDOW.startTime,
|
|
260
|
+
maxAlerts: 1000,
|
|
261
|
+
includeNonAlertingDetections: false,
|
|
262
|
+
},
|
|
263
|
+
]);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
test("a fetch with no purpose reads like a poll", async () => {
|
|
267
|
+
const fake: FakeClient = makeFakeClient({});
|
|
268
|
+
|
|
269
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
270
|
+
options: { purpose: undefined },
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
expect(
|
|
274
|
+
fake.searchCalls.map((call: SearchCall): string => {
|
|
275
|
+
return call.listBasis;
|
|
276
|
+
}),
|
|
277
|
+
).toEqual(["CREATED_TIME", "CREATED_TIME"]);
|
|
278
|
+
expect(result.details).toMatchObject({ basis: "created-time" });
|
|
279
|
+
expect(checkByKey(result.checks, "read-rule-detections").name).toBe(
|
|
280
|
+
"Read rule detections by created time",
|
|
281
|
+
);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test.each(["preview", "backfill"] as Array<ConnectorFetchPurpose>)(
|
|
285
|
+
"a %s reads the search passes by both bases and reports the detection-time basis",
|
|
286
|
+
async (purpose: ConnectorFetchPurpose) => {
|
|
287
|
+
const fake: FakeClient = makeFakeClient({
|
|
288
|
+
rule: [page([detection("x")])],
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
292
|
+
options: { purpose },
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
expect(
|
|
296
|
+
fake.searchCalls.map((call: SearchCall): string => {
|
|
297
|
+
return `${call.curated ? "curated" : "rule"}:${call.listBasis}`;
|
|
298
|
+
}),
|
|
299
|
+
).toEqual([
|
|
300
|
+
"rule:CREATED_TIME",
|
|
301
|
+
"rule:DETECTION_TIME",
|
|
302
|
+
"curated:CREATED_TIME",
|
|
303
|
+
"curated:DETECTION_TIME",
|
|
304
|
+
]);
|
|
305
|
+
expect(result.details).toMatchObject({
|
|
306
|
+
basis: "detection-time",
|
|
307
|
+
sourceCounts: {
|
|
308
|
+
ruleDetections: 2,
|
|
309
|
+
curatedDetections: 0,
|
|
310
|
+
alertsView: 0,
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
// The same record read by both bases is one record.
|
|
314
|
+
expect(result.fetchedCount).toBe(1);
|
|
315
|
+
/*
|
|
316
|
+
* Two rule searches, the curated count, the fixture curated rule by
|
|
317
|
+
* both bases and the alerts view; a preview or backfill never sweeps.
|
|
318
|
+
*/
|
|
319
|
+
expect(result.requestCount).toBe(6);
|
|
320
|
+
expect(fake.alertsCalls).toHaveLength(1);
|
|
321
|
+
expect(statusesOf(result.checks)).toEqual([
|
|
322
|
+
"read-rule-detections:pass",
|
|
323
|
+
"read-curated-detections:pass",
|
|
324
|
+
"read-alerts-view:pass",
|
|
325
|
+
]);
|
|
326
|
+
expect(checkByKey(result.checks, "read-rule-detections")).toMatchObject({
|
|
327
|
+
name: "Read rule detections by created and detection time",
|
|
328
|
+
message:
|
|
329
|
+
"2 rule detections returned for the window by created and detection time.",
|
|
330
|
+
});
|
|
331
|
+
expect(checkByKey(result.checks, "read-curated-detections").name).toBe(
|
|
332
|
+
"Read curated rule detections by created and detection time",
|
|
333
|
+
);
|
|
334
|
+
expect(checkByKey(result.checks, "read-alerts-view").name).toBe(
|
|
335
|
+
"Read alerts view by detection time",
|
|
336
|
+
);
|
|
337
|
+
},
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
test("each basis follows its own page tokens under the shared page budget", async () => {
|
|
341
|
+
const fake: FakeClient = makeFakeClient({
|
|
342
|
+
rule: [
|
|
343
|
+
page([detection("p1")], { nextPageToken: "t1" }),
|
|
344
|
+
page([detection("p2")]),
|
|
345
|
+
],
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
349
|
+
options: { purpose: "backfill" },
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
expect(
|
|
353
|
+
fake.searchCalls
|
|
354
|
+
.filter((call: SearchCall): boolean => {
|
|
355
|
+
return call.curated !== true;
|
|
356
|
+
})
|
|
357
|
+
.map((call: SearchCall): string => {
|
|
358
|
+
return `${call.listBasis}:${call.pageToken || "-"}`;
|
|
359
|
+
}),
|
|
360
|
+
).toEqual([
|
|
361
|
+
"CREATED_TIME:-",
|
|
362
|
+
"CREATED_TIME:t1",
|
|
363
|
+
"DETECTION_TIME:-",
|
|
364
|
+
"DETECTION_TIME:t1",
|
|
365
|
+
]);
|
|
366
|
+
expect(result.fetchedCount).toBe(2);
|
|
367
|
+
// Four rule pages, the curated count, two curated pages, the alerts view.
|
|
368
|
+
expect(result.requestCount).toBe(8);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
test.each([
|
|
372
|
+
[true, true, false],
|
|
373
|
+
[false, false, true],
|
|
374
|
+
])(
|
|
375
|
+
"alertingOnly %s sends alertingOnly %s to the searches and includeNonAlertingDetections %s to the alerts view",
|
|
376
|
+
async (
|
|
377
|
+
alertingOnly: boolean,
|
|
378
|
+
searchAlertingOnly: boolean,
|
|
379
|
+
includeNonAlertingDetections: boolean,
|
|
380
|
+
) => {
|
|
381
|
+
const fake: FakeClient = makeFakeClient({});
|
|
382
|
+
|
|
383
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
384
|
+
alertingOnly,
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
expect(
|
|
388
|
+
fake.searchCalls.map((call: SearchCall): boolean => {
|
|
389
|
+
return call.alertingOnly;
|
|
390
|
+
}),
|
|
391
|
+
).toEqual([searchAlertingOnly, searchAlertingOnly]);
|
|
392
|
+
// The window's read follows the scope; the late-alert sweep reads alerts only.
|
|
393
|
+
expect(
|
|
394
|
+
fake.alertsCalls.map((call: AlertsCall): boolean | undefined => {
|
|
395
|
+
return call.includeNonAlertingDetections;
|
|
396
|
+
}),
|
|
397
|
+
).toEqual([includeNonAlertingDetections, false]);
|
|
398
|
+
expect(result.details).toMatchObject({ includeNonAlertingDetections });
|
|
399
|
+
},
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
test("nextPageToken is followed and the token is forwarded", async () => {
|
|
403
|
+
const fake: FakeClient = makeFakeClient({
|
|
404
|
+
rule: [
|
|
405
|
+
page([detection("p1")], { nextPageToken: "t1" }),
|
|
406
|
+
page([detection("p2")], { nextPageToken: "t2" }),
|
|
407
|
+
page([detection("p3")]),
|
|
408
|
+
],
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
412
|
+
|
|
413
|
+
expect(
|
|
414
|
+
fake.searchCalls
|
|
415
|
+
.filter((call: SearchCall): boolean => {
|
|
416
|
+
return call.curated !== true;
|
|
417
|
+
})
|
|
418
|
+
.map((call: SearchCall): string | undefined => {
|
|
419
|
+
return call.pageToken;
|
|
420
|
+
}),
|
|
421
|
+
).toEqual([undefined, "t1", "t2"]);
|
|
422
|
+
// Three rule pages, the curated count and search, alerts view, sweep.
|
|
423
|
+
expect(result).toMatchObject({
|
|
424
|
+
complete: true,
|
|
425
|
+
fetchedCount: 3,
|
|
426
|
+
requestCount: 7,
|
|
427
|
+
details: expect.objectContaining({
|
|
428
|
+
sourceCounts: {
|
|
429
|
+
ruleDetections: 3,
|
|
430
|
+
curatedDetections: 0,
|
|
431
|
+
alertsView: 0,
|
|
432
|
+
lateAlertsView: 0,
|
|
433
|
+
},
|
|
434
|
+
}),
|
|
435
|
+
});
|
|
436
|
+
expect(checkByKey(result.checks, "read-rule-detections").message).toBe(
|
|
437
|
+
"3 rule detections returned for the window by created time.",
|
|
438
|
+
);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
/*
|
|
442
|
+
* A record with no id is identified by a hash of its content, so the
|
|
443
|
+
* connector must hand Google's object to the normalizer exactly as read:
|
|
444
|
+
* adding a field would give it a new identifier and re-import it.
|
|
445
|
+
*/
|
|
446
|
+
test("a record with no id is unioned by its content hash and reaches the normalizer untouched", async () => {
|
|
447
|
+
const noId: JSONObject = {
|
|
448
|
+
type: "RULE_DETECTION",
|
|
449
|
+
detectionTime: "2026-09-14T11:00:00.000Z",
|
|
450
|
+
createdTime: "2026-09-14T11:02:00.000Z",
|
|
451
|
+
detection: [{ ruleName: "No id rule", severity: "LOW" }],
|
|
452
|
+
};
|
|
453
|
+
const fromSearch: JSONObject = JSON.parse(JSON.stringify(noId));
|
|
454
|
+
const fromAlerts: JSONObject = JSON.parse(JSON.stringify(noId));
|
|
455
|
+
const normalize: ReturnType<typeof getJestSpyOn> = getJestSpyOn(
|
|
456
|
+
GoogleSecOpsAlertNormalizer,
|
|
457
|
+
"normalize",
|
|
458
|
+
);
|
|
459
|
+
const fake: FakeClient = makeFakeClient({
|
|
460
|
+
rule: [page([fromSearch])],
|
|
461
|
+
alerts: [fetched([fromAlerts])],
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
465
|
+
|
|
466
|
+
expect(result.fetchedCount).toBe(1);
|
|
467
|
+
expect(result.events).toHaveLength(1);
|
|
468
|
+
expect(result.events[0]!.eventUid).toBe(contentHashEventUid(noId));
|
|
469
|
+
expect(normalize).toHaveBeenCalledTimes(1);
|
|
470
|
+
// The later copy of the same record wins the union slot.
|
|
471
|
+
expect(normalize.mock.calls[0]![0]).toBe(fromAlerts);
|
|
472
|
+
expect(fromSearch).toEqual(noId);
|
|
473
|
+
expect(fromAlerts).toEqual(noId);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
test("an object that cannot even be inspected is kept under its own key without hiding the records beside it", async () => {
|
|
477
|
+
const uninspectable: () => JSONObject = (): JSONObject => {
|
|
478
|
+
const record: JSONObject = {};
|
|
479
|
+
Object.defineProperty(record, "id", {
|
|
480
|
+
get: (): never => {
|
|
481
|
+
throw new Error("unreadable");
|
|
482
|
+
},
|
|
483
|
+
enumerable: true,
|
|
484
|
+
});
|
|
485
|
+
return record;
|
|
486
|
+
};
|
|
487
|
+
const fake: FakeClient = makeFakeClient({
|
|
488
|
+
rule: [page([uninspectable(), uninspectable(), detection("valid")])],
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
492
|
+
|
|
493
|
+
expect(result.fetchedCount).toBe(3);
|
|
494
|
+
expect(uidsOf(result)).toEqual(["valid"]);
|
|
495
|
+
expect(result.rejectedCount + result.failedCount).toBe(2);
|
|
496
|
+
expect(result.complete).toBe(true);
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
/*
|
|
500
|
+
* Rejected objects are permanently unrecognizable and failed ones are for
|
|
501
|
+
* the poller to retry; both are only counted here. The poller owns the
|
|
502
|
+
* warnings about them and folds failures into completeness, so the
|
|
503
|
+
* connector's own complete flag describes its bounds alone.
|
|
504
|
+
*/
|
|
505
|
+
test("unrecognized records are rejected and records that throw are failed, without touching completeness", async () => {
|
|
506
|
+
const fake: FakeClient = makeFakeClient({
|
|
507
|
+
rule: [
|
|
508
|
+
page([
|
|
509
|
+
{ arbitrary: "envelope" },
|
|
510
|
+
poisonDetection("poison"),
|
|
511
|
+
detection("ok"),
|
|
512
|
+
]),
|
|
513
|
+
],
|
|
514
|
+
alerts: [fetched([{ progress: 0.5, complete: false }])],
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
518
|
+
|
|
519
|
+
expect(result).toMatchObject({
|
|
520
|
+
fetchedCount: 4,
|
|
521
|
+
rejectedCount: 2,
|
|
522
|
+
failedCount: 1,
|
|
523
|
+
complete: true,
|
|
524
|
+
warnings: [],
|
|
525
|
+
});
|
|
526
|
+
expect(uidsOf(result)).toEqual(["ok"]);
|
|
527
|
+
expect(result.samples).toHaveLength(1);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
test("rejects unusable settings before building a client or contacting anything", async () => {
|
|
531
|
+
const fake: FakeClient = makeFakeClient({});
|
|
532
|
+
const harness: ConnectorHarness = connectorWith(fake.client);
|
|
533
|
+
|
|
534
|
+
const error: unknown = await rejectionOf(
|
|
535
|
+
harness.connector.fetchEvents(
|
|
536
|
+
secOpsSettings({ config: { region: "mars" } }),
|
|
537
|
+
WINDOW,
|
|
538
|
+
fetchOptions(),
|
|
539
|
+
),
|
|
540
|
+
);
|
|
541
|
+
|
|
542
|
+
expect(error).toBeInstanceOf(BadDataException);
|
|
543
|
+
expect((error as Error).message).toBe(
|
|
544
|
+
"Region must be a Google SecOps regional prefix like 'us' or 'europe'.",
|
|
545
|
+
);
|
|
546
|
+
expect(harness.factoryCalls).toHaveLength(0);
|
|
547
|
+
expect(fake.searchCalls).toHaveLength(0);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
test("builds the client with the fetch's request deadline", async () => {
|
|
551
|
+
const fake: FakeClient = makeFakeClient({});
|
|
552
|
+
const harness: ConnectorHarness = connectorWith(fake.client);
|
|
553
|
+
|
|
554
|
+
await harness.connector.fetchEvents(
|
|
555
|
+
secOpsSettings(),
|
|
556
|
+
WINDOW,
|
|
557
|
+
fetchOptions({ requestTimeoutInMs: 4321 }),
|
|
558
|
+
);
|
|
559
|
+
|
|
560
|
+
expect(harness.factoryCalls).toEqual([
|
|
561
|
+
expect.objectContaining({
|
|
562
|
+
region: "us",
|
|
563
|
+
requestTimeoutInMs: 4321,
|
|
564
|
+
}) as unknown as ClientFactoryCall,
|
|
565
|
+
]);
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
describe("GoogleSecOpsConnector.fetchEvents failures", () => {
|
|
570
|
+
afterEach(() => {
|
|
571
|
+
jest.restoreAllMocks();
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
test.each([400, 403, 404])(
|
|
575
|
+
"a curated pass answering HTTP %s is a warning and the fetch continues",
|
|
576
|
+
async (status: number) => {
|
|
577
|
+
// A tenant without curated access rejects the curated rule counts.
|
|
578
|
+
const fake: FakeClient = makeFakeClient({
|
|
579
|
+
rule: [page([detection("r")])],
|
|
580
|
+
counts: [
|
|
581
|
+
new APIException(
|
|
582
|
+
`Google SecOps curated rule detection counts failed (HTTP ${status}): {"error":{"code":${status}}}`,
|
|
583
|
+
),
|
|
584
|
+
],
|
|
585
|
+
alerts: [fetched([detection("v")]), fetched([])],
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
589
|
+
|
|
590
|
+
expect(result.complete).toBe(true);
|
|
591
|
+
expect(uidsOf(result)).toEqual(["r", "v"]);
|
|
592
|
+
expect(result.warnings).toEqual([
|
|
593
|
+
`Curated rule detections could not be read (HTTP ${status}); this tenant may not have curated rule access. Rule detections and the alerts view were still read.`,
|
|
594
|
+
]);
|
|
595
|
+
expect(checkByKey(result.checks, "read-curated-detections")).toEqual({
|
|
596
|
+
key: "read-curated-detections",
|
|
597
|
+
name: "Read curated rule detections by created time",
|
|
598
|
+
status: "warn",
|
|
599
|
+
durationMs: expect.any(Number),
|
|
600
|
+
message: `Google SecOps curated rule detection counts failed (HTTP ${status}): {"error":{"code":${status}}}`,
|
|
601
|
+
remediation:
|
|
602
|
+
"Curated (Google-authored) rule detections need that entitlement on the tenant. Nothing to fix unless you expect curated detections to be imported.",
|
|
603
|
+
details: { httpStatus: status },
|
|
604
|
+
});
|
|
605
|
+
expect(statusesOf(result.checks)).toEqual([
|
|
606
|
+
"read-rule-detections:pass",
|
|
607
|
+
"read-curated-detections:warn",
|
|
608
|
+
"read-alerts-view:pass",
|
|
609
|
+
"read-late-alerts-view:pass",
|
|
610
|
+
]);
|
|
611
|
+
expect(result.details).toMatchObject({
|
|
612
|
+
sourceCounts: {
|
|
613
|
+
ruleDetections: 1,
|
|
614
|
+
curatedDetections: 0,
|
|
615
|
+
alertsView: 1,
|
|
616
|
+
},
|
|
617
|
+
curatedRulesWithDetections: 0,
|
|
618
|
+
});
|
|
619
|
+
// With no curated rules named, no curated search goes out.
|
|
620
|
+
expect(fake.countCalls).toHaveLength(1);
|
|
621
|
+
expect(
|
|
622
|
+
fake.searchCalls.map((call: SearchCall): boolean | undefined => {
|
|
623
|
+
return call.curated;
|
|
624
|
+
}),
|
|
625
|
+
).toEqual([false]);
|
|
626
|
+
expect(result.requestCount).toBe(4);
|
|
627
|
+
// The alerts view over the window still ran, and so did the sweep.
|
|
628
|
+
expect(windowReadsOf(fake)).toHaveLength(1);
|
|
629
|
+
expect(fake.alertsCalls).toHaveLength(2);
|
|
630
|
+
},
|
|
631
|
+
);
|
|
632
|
+
|
|
633
|
+
test.each([401, 429, 500, 503])(
|
|
634
|
+
"a curated pass answering HTTP %s throws the original error with the passes that ran attached",
|
|
635
|
+
async (status: number) => {
|
|
636
|
+
const original: APIException = new APIException(
|
|
637
|
+
`Google SecOps detections search failed (HTTP ${status}): {"error":{"code":${status}}}`,
|
|
638
|
+
);
|
|
639
|
+
const fake: FakeClient = makeFakeClient({
|
|
640
|
+
rule: [page([detection("r")])],
|
|
641
|
+
curated: [original],
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
645
|
+
|
|
646
|
+
expect(error).toBe(original);
|
|
647
|
+
expect((error as Error).message).toBe(
|
|
648
|
+
`Google SecOps detections search failed (HTTP ${status}): {"error":{"code":${status}}}`,
|
|
649
|
+
);
|
|
650
|
+
const checks: Array<SecurityConnectorCheck> | undefined =
|
|
651
|
+
readConnectorChecks(error);
|
|
652
|
+
expect(statusesOf(checks)).toEqual([
|
|
653
|
+
"read-rule-detections:pass",
|
|
654
|
+
"read-curated-detections:fail",
|
|
655
|
+
]);
|
|
656
|
+
expect(checkByKey(checks, "read-curated-detections")).toMatchObject({
|
|
657
|
+
name: "Read curated rule detections by created time",
|
|
658
|
+
message: `Google SecOps detections search failed (HTTP ${status}): {"error":{"code":${status}}}`,
|
|
659
|
+
});
|
|
660
|
+
expect(fake.alertsCalls).toHaveLength(0);
|
|
661
|
+
},
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
test.each([
|
|
665
|
+
"Google SecOps detections search returned a non-JSON body.",
|
|
666
|
+
"Google SecOps detections search timed out after 60 seconds with no response.",
|
|
667
|
+
'Google SecOps detections search returned an unrecognized response shape: {"nope":true}',
|
|
668
|
+
])(
|
|
669
|
+
"a curated pass failing with no HTTP status (%s) fails like any other pass",
|
|
670
|
+
async (message: string) => {
|
|
671
|
+
const original: APIException = new APIException(message);
|
|
672
|
+
const fake: FakeClient = makeFakeClient({ curated: [original] });
|
|
673
|
+
|
|
674
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
675
|
+
|
|
676
|
+
expect(error).toBe(original);
|
|
677
|
+
expect((error as Error).message).toBe(message);
|
|
678
|
+
expect(statusesOf(readConnectorChecks(error))).toEqual([
|
|
679
|
+
"read-rule-detections:pass",
|
|
680
|
+
"read-curated-detections:fail",
|
|
681
|
+
]);
|
|
682
|
+
},
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
test("a rule pass failure names its own pass and nothing after it runs", async () => {
|
|
686
|
+
const original: APIException = new APIException(
|
|
687
|
+
"Google SecOps detections search failed (HTTP 403): denied",
|
|
688
|
+
);
|
|
689
|
+
const fake: FakeClient = makeFakeClient({ rule: [original] });
|
|
690
|
+
|
|
691
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
692
|
+
|
|
693
|
+
expect(error).toBe(original);
|
|
694
|
+
expect(error).toBeInstanceOf(APIException);
|
|
695
|
+
expect(readConnectorChecks(error)).toEqual([
|
|
696
|
+
{
|
|
697
|
+
key: "read-rule-detections",
|
|
698
|
+
name: "Read rule detections by created time",
|
|
699
|
+
status: "fail",
|
|
700
|
+
durationMs: expect.any(Number),
|
|
701
|
+
message: "Google SecOps detections search failed (HTTP 403): denied",
|
|
702
|
+
},
|
|
703
|
+
]);
|
|
704
|
+
expect(fake.searchCalls).toHaveLength(1);
|
|
705
|
+
expect(fake.alertsCalls).toHaveLength(0);
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
test("a token exchange failing on the first request is the rule pass's failure", async () => {
|
|
709
|
+
const original: APIException = new APIException(
|
|
710
|
+
'Google token exchange failed (HTTP 401): {"error":"invalid_grant"}',
|
|
711
|
+
);
|
|
712
|
+
const fake: FakeClient = makeFakeClient({ rule: [original] });
|
|
713
|
+
|
|
714
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
715
|
+
|
|
716
|
+
expect(
|
|
717
|
+
(error as Error).message.startsWith(
|
|
718
|
+
"Google token exchange failed (HTTP 401): ",
|
|
719
|
+
),
|
|
720
|
+
).toBe(true);
|
|
721
|
+
expect(statusesOf(readConnectorChecks(error))).toEqual([
|
|
722
|
+
"read-rule-detections:fail",
|
|
723
|
+
]);
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
test("an alerts-view failure carries both search passes and its own failed check", async () => {
|
|
727
|
+
const original: APIException = new APIException(
|
|
728
|
+
"Google SecOps alerts fetch failed (HTTP 403): permission denied",
|
|
729
|
+
);
|
|
730
|
+
const fake: FakeClient = makeFakeClient({
|
|
731
|
+
rule: [page([detection("r")])],
|
|
732
|
+
curated: [page([detection("c")])],
|
|
733
|
+
alerts: [original],
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
737
|
+
|
|
738
|
+
expect(error).toBe(original);
|
|
739
|
+
const checks: Array<SecurityConnectorCheck> | undefined =
|
|
740
|
+
readConnectorChecks(error);
|
|
741
|
+
expect(statusesOf(checks)).toEqual([
|
|
742
|
+
"read-rule-detections:pass",
|
|
743
|
+
"read-curated-detections:pass",
|
|
744
|
+
"read-alerts-view:fail",
|
|
745
|
+
]);
|
|
746
|
+
expect(checkByKey(checks, "read-alerts-view")).toMatchObject({
|
|
747
|
+
name: "Read alerts view by detection time",
|
|
748
|
+
message:
|
|
749
|
+
"Google SecOps alerts fetch failed (HTTP 403): permission denied",
|
|
750
|
+
});
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
test("a failed pass of a preview is named after both bases", async () => {
|
|
754
|
+
const fake: FakeClient = makeFakeClient({
|
|
755
|
+
curated: [
|
|
756
|
+
new APIException(
|
|
757
|
+
'Google SecOps detections search failed (HTTP 500): {"error":{"code":500}}',
|
|
758
|
+
),
|
|
759
|
+
],
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
const error: unknown = await rejectionOf(
|
|
763
|
+
fetchWith(fake, { options: { purpose: "preview" } }),
|
|
764
|
+
);
|
|
765
|
+
|
|
766
|
+
expect(
|
|
767
|
+
checkByKey(readConnectorChecks(error), "read-curated-detections").name,
|
|
768
|
+
).toBe("Read curated rule detections by created and detection time");
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
test("an alerts-view failure after a curated warning keeps the warning check", async () => {
|
|
772
|
+
const fake: FakeClient = makeFakeClient({
|
|
773
|
+
counts: [
|
|
774
|
+
new APIException(
|
|
775
|
+
'Google SecOps curated rule detection counts failed (HTTP 403): {"error":{"code":403}}',
|
|
776
|
+
),
|
|
777
|
+
],
|
|
778
|
+
alerts: [
|
|
779
|
+
new APIException(
|
|
780
|
+
"Google SecOps alerts fetch returned a non-JSON body.",
|
|
781
|
+
),
|
|
782
|
+
],
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
786
|
+
|
|
787
|
+
expect(statusesOf(readConnectorChecks(error))).toEqual([
|
|
788
|
+
"read-rule-detections:pass",
|
|
789
|
+
"read-curated-detections:warn",
|
|
790
|
+
"read-alerts-view:fail",
|
|
791
|
+
]);
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
test("the failed check is redacted and kept whole while the thrown error is left exactly as the client wrote it", async () => {
|
|
795
|
+
const message: string = `Google SecOps alerts fetch failed (HTTP 400): {"error":{"private_key":"-----BEGIN PRIVATE KEY-----leaked"}} ${"detail ".repeat(200)}tail`;
|
|
796
|
+
const original: APIException = new APIException(message);
|
|
797
|
+
const fake: FakeClient = makeFakeClient({ alerts: [original] });
|
|
798
|
+
|
|
799
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
800
|
+
|
|
801
|
+
expect((error as Error).message).toBe(message);
|
|
802
|
+
const failed: SecurityConnectorCheck = checkByKey(
|
|
803
|
+
readConnectorChecks(error),
|
|
804
|
+
"read-alerts-view",
|
|
805
|
+
);
|
|
806
|
+
expect(failed.message).not.toContain("leaked");
|
|
807
|
+
expect(failed.message.endsWith("tail")).toBe(true);
|
|
808
|
+
expect(failed.message).not.toContain("(truncated)");
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
test("the attached checks stay off the error's enumerable properties", async () => {
|
|
812
|
+
const original: APIException = new APIException(
|
|
813
|
+
"Google SecOps detections search failed (HTTP 403): denied",
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
const error: unknown = await rejectionOf(
|
|
817
|
+
fetchWith(makeFakeClient({ rule: [original] })),
|
|
818
|
+
);
|
|
819
|
+
|
|
820
|
+
expect(Object.keys(error as Record<string, unknown>)).not.toContain(
|
|
821
|
+
"oneuptimeConnectorChecks",
|
|
822
|
+
);
|
|
823
|
+
expect(readConnectorChecks(error)).toHaveLength(1);
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
test("a curated downgrade's warn check keeps a 403 body over the default message limit whole, and still redacted", async () => {
|
|
827
|
+
/*
|
|
828
|
+
* Every failure check is written whole; the curated warn check used the
|
|
829
|
+
* default 1000 character clamp, which cut Google's explanation of the
|
|
830
|
+
* missing entitlement off mid-body.
|
|
831
|
+
*/
|
|
832
|
+
const body: string = "curated entitlement missing ".repeat(45);
|
|
833
|
+
const message: string = `Google SecOps curated rule detection counts failed (HTTP 403): {"error":{"private_key":"-----BEGIN PRIVATE KEY-----leaked"}} ${body}tail`;
|
|
834
|
+
expect(message.length).toBeGreaterThan(1000);
|
|
835
|
+
const fake: FakeClient = makeFakeClient({
|
|
836
|
+
rule: [page([detection("r")])],
|
|
837
|
+
counts: [new APIException(message)],
|
|
838
|
+
alerts: [fetched([detection("v")])],
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
842
|
+
|
|
843
|
+
const warned: SecurityConnectorCheck = checkByKey(
|
|
844
|
+
result.checks,
|
|
845
|
+
"read-curated-detections",
|
|
846
|
+
);
|
|
847
|
+
expect(warned.status).toBe("warn");
|
|
848
|
+
expect(warned.message.length).toBeGreaterThan(1000);
|
|
849
|
+
expect(warned.message).toContain(`${body}tail`);
|
|
850
|
+
expect(warned.message.endsWith("tail")).toBe(true);
|
|
851
|
+
expect(warned.message).not.toContain("(truncated)");
|
|
852
|
+
expect(warned.message).not.toContain("leaked");
|
|
853
|
+
expect(
|
|
854
|
+
warned.message.startsWith(
|
|
855
|
+
"Google SecOps curated rule detection counts failed (HTTP 403): ",
|
|
856
|
+
),
|
|
857
|
+
).toBe(true);
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
test("a failure after a curated downgrade carries the passes' warnings, request and record counts and details on the original error", async () => {
|
|
861
|
+
/*
|
|
862
|
+
* The retired GoogleSecOpsPoller mutated one result through every pass
|
|
863
|
+
* and kept the curated warning, the counts, sourceCounts, basis and
|
|
864
|
+
* includeNonAlertingDetections on its failed run. The connector hands the
|
|
865
|
+
* same to the shared poller on the error it rethrows.
|
|
866
|
+
*/
|
|
867
|
+
const original: APIException = new APIException(
|
|
868
|
+
'Google SecOps alerts fetch failed (HTTP 500): {"error":{"code":500}}',
|
|
869
|
+
);
|
|
870
|
+
const fake: FakeClient = makeFakeClient({
|
|
871
|
+
rule: [page([detection("r1"), detection("r2")])],
|
|
872
|
+
counts: [
|
|
873
|
+
new APIException(
|
|
874
|
+
'Google SecOps curated rule detection counts failed (HTTP 403): {"error":{"code":403}}',
|
|
875
|
+
),
|
|
876
|
+
],
|
|
877
|
+
alerts: [original],
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
881
|
+
|
|
882
|
+
expect(error).toBe(original);
|
|
883
|
+
expect(error).toBeInstanceOf(APIException);
|
|
884
|
+
expect((error as Error).message).toBe(
|
|
885
|
+
'Google SecOps alerts fetch failed (HTTP 500): {"error":{"code":500}}',
|
|
886
|
+
);
|
|
887
|
+
expect(statusesOf(readConnectorChecks(error))).toEqual([
|
|
888
|
+
"read-rule-detections:pass",
|
|
889
|
+
"read-curated-detections:warn",
|
|
890
|
+
"read-alerts-view:fail",
|
|
891
|
+
]);
|
|
892
|
+
const summary: ConnectorFetchFailureSummary | undefined =
|
|
893
|
+
readConnectorFetchSummary(error);
|
|
894
|
+
expect(summary).toBeDefined();
|
|
895
|
+
expect(summary!.warnings).toHaveLength(1);
|
|
896
|
+
expect(
|
|
897
|
+
summary!.warnings[0]!.startsWith(
|
|
898
|
+
"Curated rule detections could not be read (HTTP 403)",
|
|
899
|
+
),
|
|
900
|
+
).toBe(true);
|
|
901
|
+
// The rule search, the curated count and the alerts-view request that failed.
|
|
902
|
+
expect(
|
|
903
|
+
fake.searchCalls.length +
|
|
904
|
+
fake.countCalls.length +
|
|
905
|
+
fake.alertsCalls.length,
|
|
906
|
+
).toBe(3);
|
|
907
|
+
expect(summary!.requestCount).toBe(3);
|
|
908
|
+
expect(summary!.fetchedCount).toBe(2);
|
|
909
|
+
expect(summary!.details).toEqual({
|
|
910
|
+
basis: "created-time",
|
|
911
|
+
sourceCounts: { ruleDetections: 2, curatedDetections: 0, alertsView: 0 },
|
|
912
|
+
includeNonAlertingDetections: false,
|
|
913
|
+
});
|
|
914
|
+
expect(Object.keys(error as Record<string, unknown>)).not.toContain(
|
|
915
|
+
"oneuptimeConnectorFetchSummary",
|
|
916
|
+
);
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
test("a rule pass failure carries a summary with the request it made and nothing fetched", async () => {
|
|
920
|
+
const original: APIException = new APIException(
|
|
921
|
+
"Google SecOps detections search failed (HTTP 403): denied",
|
|
922
|
+
);
|
|
923
|
+
const fake: FakeClient = makeFakeClient({ rule: [original] });
|
|
924
|
+
|
|
925
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
926
|
+
|
|
927
|
+
expect(error).toBe(original);
|
|
928
|
+
const summary: ConnectorFetchFailureSummary | undefined =
|
|
929
|
+
readConnectorFetchSummary(error);
|
|
930
|
+
expect(summary).toEqual({
|
|
931
|
+
warnings: [],
|
|
932
|
+
requestCount: 1,
|
|
933
|
+
fetchedCount: 0,
|
|
934
|
+
details: {
|
|
935
|
+
basis: "created-time",
|
|
936
|
+
sourceCounts: {
|
|
937
|
+
ruleDetections: 0,
|
|
938
|
+
curatedDetections: 0,
|
|
939
|
+
alertsView: 0,
|
|
940
|
+
},
|
|
941
|
+
includeNonAlertingDetections: false,
|
|
942
|
+
},
|
|
943
|
+
});
|
|
944
|
+
expect(summary!.requestCount).toBeGreaterThanOrEqual(1);
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
test("a pass failing on a later page counts the records its earlier pages collected, while its source count stays unset", async () => {
|
|
948
|
+
/*
|
|
949
|
+
* sourceCounts are filled when a pass finishes, as the retired poller
|
|
950
|
+
* filled them; the union (fetchedCount) grows with every page read.
|
|
951
|
+
*/
|
|
952
|
+
const fake: FakeClient = makeFakeClient({
|
|
953
|
+
rule: [
|
|
954
|
+
page([detection("a"), detection("b")], { nextPageToken: "page-2" }),
|
|
955
|
+
new APIException(
|
|
956
|
+
"Google SecOps detections search failed (HTTP 503): unavailable",
|
|
957
|
+
),
|
|
958
|
+
],
|
|
959
|
+
});
|
|
960
|
+
|
|
961
|
+
const error: unknown = await rejectionOf(fetchWith(fake));
|
|
962
|
+
|
|
963
|
+
const summary: ConnectorFetchFailureSummary | undefined =
|
|
964
|
+
readConnectorFetchSummary(error);
|
|
965
|
+
expect(summary).toMatchObject({
|
|
966
|
+
warnings: [],
|
|
967
|
+
requestCount: 2,
|
|
968
|
+
fetchedCount: 2,
|
|
969
|
+
details: {
|
|
970
|
+
sourceCounts: {
|
|
971
|
+
ruleDetections: 0,
|
|
972
|
+
curatedDetections: 0,
|
|
973
|
+
alertsView: 0,
|
|
974
|
+
},
|
|
975
|
+
},
|
|
976
|
+
});
|
|
977
|
+
});
|
|
978
|
+
|
|
979
|
+
test("a failed preview with Detections selected reports its detection-time basis and scope in the summary", async () => {
|
|
980
|
+
const fake: FakeClient = makeFakeClient({
|
|
981
|
+
// The same detection by both bases is one record in the union.
|
|
982
|
+
rule: [page([detection("same")])],
|
|
983
|
+
curated: [
|
|
984
|
+
new APIException(
|
|
985
|
+
'Google SecOps detections search failed (HTTP 500): {"error":{"code":500}}',
|
|
986
|
+
),
|
|
987
|
+
],
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
const error: unknown = await rejectionOf(
|
|
991
|
+
fetchWith(fake, {
|
|
992
|
+
options: { purpose: "preview" },
|
|
993
|
+
alertingOnly: false,
|
|
994
|
+
}),
|
|
995
|
+
);
|
|
996
|
+
|
|
997
|
+
// Two rule searches, the curated count and the curated search that failed.
|
|
998
|
+
expect(readConnectorFetchSummary(error)).toEqual({
|
|
999
|
+
warnings: [],
|
|
1000
|
+
requestCount: 4,
|
|
1001
|
+
fetchedCount: 1,
|
|
1002
|
+
details: {
|
|
1003
|
+
basis: "detection-time",
|
|
1004
|
+
sourceCounts: {
|
|
1005
|
+
ruleDetections: 2,
|
|
1006
|
+
curatedDetections: 0,
|
|
1007
|
+
alertsView: 0,
|
|
1008
|
+
},
|
|
1009
|
+
includeNonAlertingDetections: true,
|
|
1010
|
+
},
|
|
1011
|
+
});
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
test("a rejection that is not an Error object is rethrown as it was", async () => {
|
|
1015
|
+
const client: GoogleSecOpsClient = {
|
|
1016
|
+
searchDetections: (): Promise<SearchDetectionsResult> => {
|
|
1017
|
+
return Promise.reject("socket hang up");
|
|
1018
|
+
},
|
|
1019
|
+
} as unknown as GoogleSecOpsClient;
|
|
1020
|
+
|
|
1021
|
+
const error: unknown = await rejectionOf(
|
|
1022
|
+
connectorWith(client).connector.fetchEvents(
|
|
1023
|
+
secOpsSettings(),
|
|
1024
|
+
WINDOW,
|
|
1025
|
+
fetchOptions(),
|
|
1026
|
+
),
|
|
1027
|
+
);
|
|
1028
|
+
|
|
1029
|
+
expect(error).toBe("socket hang up");
|
|
1030
|
+
expect(readConnectorChecks(error)).toBeUndefined();
|
|
1031
|
+
expect(readConnectorFetchSummary(error)).toBeUndefined();
|
|
1032
|
+
});
|
|
1033
|
+
});
|
|
1034
|
+
|
|
1035
|
+
describe("GoogleSecOpsConnector.fetchEvents budgets", () => {
|
|
1036
|
+
afterEach(() => {
|
|
1037
|
+
jest.restoreAllMocks();
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
function useClock(): {
|
|
1041
|
+
advance: (ms: number) => void;
|
|
1042
|
+
set: (ms: number) => void;
|
|
1043
|
+
} {
|
|
1044
|
+
const realNow: number = Date.now();
|
|
1045
|
+
let elapsedMs: number = 0;
|
|
1046
|
+
getJestSpyOn(Date, "now").mockImplementation((): number => {
|
|
1047
|
+
return realNow + elapsedMs;
|
|
1048
|
+
});
|
|
1049
|
+
return {
|
|
1050
|
+
advance: (ms: number): void => {
|
|
1051
|
+
elapsedMs += ms;
|
|
1052
|
+
},
|
|
1053
|
+
set: (ms: number): void => {
|
|
1054
|
+
elapsedMs = ms;
|
|
1055
|
+
},
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
test("the rule pass stops at its own 20 pages while the curated pass and the alerts view keep their own budgets", async () => {
|
|
1060
|
+
const fake: FakeClient = makeFakeClient({ rule: endlessPages("endless") });
|
|
1061
|
+
|
|
1062
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1063
|
+
|
|
1064
|
+
expect(
|
|
1065
|
+
fake.searchCalls.filter((call: SearchCall): boolean => {
|
|
1066
|
+
return call.curated === false;
|
|
1067
|
+
}),
|
|
1068
|
+
).toHaveLength(20);
|
|
1069
|
+
// The curated pass still counted and searched on its own budget.
|
|
1070
|
+
expect(fake.countCalls).toHaveLength(1);
|
|
1071
|
+
expect(
|
|
1072
|
+
fake.searchCalls
|
|
1073
|
+
.filter((call: SearchCall): boolean => {
|
|
1074
|
+
return call.curated === true;
|
|
1075
|
+
})
|
|
1076
|
+
.map((call: SearchCall): string | undefined => {
|
|
1077
|
+
return call.ruleId;
|
|
1078
|
+
}),
|
|
1079
|
+
).toEqual([FIXTURE_CURATED_RULE_ID]);
|
|
1080
|
+
// The alerts view and the late-alert sweep still ran on theirs.
|
|
1081
|
+
expect(fake.alertsCalls).toHaveLength(2);
|
|
1082
|
+
expect(result.requestCount).toBe(24);
|
|
1083
|
+
expect(result.complete).toBe(false);
|
|
1084
|
+
expect(checkByKey(result.checks, "read-rule-detections")).toMatchObject({
|
|
1085
|
+
status: "warn",
|
|
1086
|
+
message:
|
|
1087
|
+
"20 rule detections returned for the window by created time. The pass was stopped by the request budget after 20 requests.",
|
|
1088
|
+
});
|
|
1089
|
+
expect(checkByKey(result.checks, "read-curated-detections")).toMatchObject({
|
|
1090
|
+
status: "pass",
|
|
1091
|
+
message:
|
|
1092
|
+
"0 curated rule detections returned for the window by created time (1 of 1 curated rule with recent detections searched).",
|
|
1093
|
+
});
|
|
1094
|
+
expect(statusesOf(result.checks)).toEqual([
|
|
1095
|
+
"read-rule-detections:warn",
|
|
1096
|
+
"read-curated-detections:pass",
|
|
1097
|
+
"read-alerts-view:pass",
|
|
1098
|
+
"read-late-alerts-view:pass",
|
|
1099
|
+
]);
|
|
1100
|
+
expect(result.warnings).toEqual([
|
|
1101
|
+
"Read rule detections by created time was stopped by the request budget after 20 requests.",
|
|
1102
|
+
]);
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
test("a preview's two bases share the same 20 pages", async () => {
|
|
1106
|
+
const fake: FakeClient = makeFakeClient({ rule: endlessPages("endless") });
|
|
1107
|
+
|
|
1108
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1109
|
+
options: { purpose: "preview" },
|
|
1110
|
+
});
|
|
1111
|
+
|
|
1112
|
+
const ruleCalls: Array<SearchCall> = fake.searchCalls.filter(
|
|
1113
|
+
(call: SearchCall): boolean => {
|
|
1114
|
+
return call.curated === false;
|
|
1115
|
+
},
|
|
1116
|
+
);
|
|
1117
|
+
// The created-time basis spends every page; detection time never starts.
|
|
1118
|
+
expect(ruleCalls).toHaveLength(20);
|
|
1119
|
+
expect(
|
|
1120
|
+
ruleCalls.every((call: SearchCall): boolean => {
|
|
1121
|
+
return call.listBasis === "CREATED_TIME";
|
|
1122
|
+
}),
|
|
1123
|
+
).toBe(true);
|
|
1124
|
+
expect(checkByKey(result.checks, "read-rule-detections").message).toBe(
|
|
1125
|
+
"20 rule detections returned for the window by created and detection time. The pass was stopped by the request budget after 20 requests.",
|
|
1126
|
+
);
|
|
1127
|
+
});
|
|
1128
|
+
|
|
1129
|
+
test("the alerts view stops at its own 16 requests while the searches still read", async () => {
|
|
1130
|
+
const fake: FakeClient = makeFakeClient({
|
|
1131
|
+
rule: [
|
|
1132
|
+
page(
|
|
1133
|
+
Array.from(
|
|
1134
|
+
{ length: 1000 },
|
|
1135
|
+
(_value: unknown, index: number): JSONObject => {
|
|
1136
|
+
return detection(`rule-${index}`);
|
|
1137
|
+
},
|
|
1138
|
+
),
|
|
1139
|
+
{ nextPageToken: "second" },
|
|
1140
|
+
),
|
|
1141
|
+
page([detection("rule-1000")]),
|
|
1142
|
+
],
|
|
1143
|
+
alerts: [fetched([detection("burst")], { truncatedByCount: true })],
|
|
1144
|
+
});
|
|
1145
|
+
|
|
1146
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1147
|
+
window: DAY_WINDOW,
|
|
1148
|
+
});
|
|
1149
|
+
|
|
1150
|
+
// A day's window never sweeps, so every alerts-view request is the window's.
|
|
1151
|
+
expect(fake.alertsCalls).toHaveLength(16);
|
|
1152
|
+
// Two rule pages, the curated count and search, 16 alerts-view requests.
|
|
1153
|
+
expect(result.requestCount).toBe(20);
|
|
1154
|
+
expect(result.complete).toBe(false);
|
|
1155
|
+
expect(result.details).toMatchObject({
|
|
1156
|
+
sourceCounts: {
|
|
1157
|
+
ruleDetections: 1001,
|
|
1158
|
+
curatedDetections: 0,
|
|
1159
|
+
alertsView: 16,
|
|
1160
|
+
},
|
|
1161
|
+
});
|
|
1162
|
+
expect(statusesOf(result.checks)).toEqual([
|
|
1163
|
+
"read-rule-detections:pass",
|
|
1164
|
+
"read-curated-detections:pass",
|
|
1165
|
+
"read-alerts-view:warn",
|
|
1166
|
+
]);
|
|
1167
|
+
expect(checkByKey(result.checks, "read-alerts-view").message).toBe(
|
|
1168
|
+
"16 alerts returned by detection time. The pass was stopped by the request budget after 16 requests.",
|
|
1169
|
+
);
|
|
1170
|
+
expect(result.warnings).toEqual([
|
|
1171
|
+
"Google limited the alerts view response for 2026-09-13T12:00:00.000Z to 2026-09-14T12:00:00.000Z, so it was split into smaller windows 16 times.",
|
|
1172
|
+
"Read alerts view by detection time was stopped by the request budget after 16 requests.",
|
|
1173
|
+
]);
|
|
1174
|
+
});
|
|
1175
|
+
|
|
1176
|
+
test("the late-alert sweep shares the alerts view's 16 requests, so a window read that spends them leaves the sweep skipped and named", async () => {
|
|
1177
|
+
// Shorter than a day, so a poll of it sweeps; long enough to split 16 times.
|
|
1178
|
+
const halfDay: ConnectorFetchWindow = {
|
|
1179
|
+
startTime: new Date("2026-09-14T00:00:00.000Z"),
|
|
1180
|
+
endTime: new Date("2026-09-14T12:00:00.000Z"),
|
|
1181
|
+
};
|
|
1182
|
+
const fake: FakeClient = makeFakeClient({
|
|
1183
|
+
alerts: [fetched([detection("burst")], { truncatedByCount: true })],
|
|
1184
|
+
});
|
|
1185
|
+
|
|
1186
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1187
|
+
window: halfDay,
|
|
1188
|
+
});
|
|
1189
|
+
|
|
1190
|
+
expect(fake.alertsCalls).toHaveLength(16);
|
|
1191
|
+
expect(windowReadsOf(fake, halfDay)).toHaveLength(16);
|
|
1192
|
+
// The rule search, the curated count and search, 16 alerts-view requests.
|
|
1193
|
+
expect(result.requestCount).toBe(19);
|
|
1194
|
+
// Incomplete because of the window read; the sweep never holds a poll.
|
|
1195
|
+
expect(result.complete).toBe(false);
|
|
1196
|
+
expect(statusesOf(result.checks)).toEqual([
|
|
1197
|
+
"read-rule-detections:pass",
|
|
1198
|
+
"read-curated-detections:pass",
|
|
1199
|
+
"read-alerts-view:warn",
|
|
1200
|
+
"read-late-alerts-view:skip",
|
|
1201
|
+
]);
|
|
1202
|
+
expect(checkByKey(result.checks, "read-late-alerts-view").message).toBe(
|
|
1203
|
+
"Not run: stopped by the request budget after 0 requests. The passes that share this request budget spent it before this pass started.",
|
|
1204
|
+
);
|
|
1205
|
+
expect(result.warnings).toEqual([
|
|
1206
|
+
"Google limited the alerts view response for 2026-09-14T00:00:00.000Z to 2026-09-14T12:00:00.000Z, so it was split into smaller windows 16 times.",
|
|
1207
|
+
"Read alerts view by detection time was stopped by the request budget after 16 requests.",
|
|
1208
|
+
"Read late alerts by detection time was stopped by the request budget after 0 requests.",
|
|
1209
|
+
]);
|
|
1210
|
+
expect(result.details).toMatchObject({
|
|
1211
|
+
sourceCounts: {
|
|
1212
|
+
ruleDetections: 0,
|
|
1213
|
+
curatedDetections: 0,
|
|
1214
|
+
alertsView: 16,
|
|
1215
|
+
lateAlertsView: 0,
|
|
1216
|
+
},
|
|
1217
|
+
});
|
|
1218
|
+
});
|
|
1219
|
+
|
|
1220
|
+
test("a pass the time budget never let start is skipped and named", async () => {
|
|
1221
|
+
const clock: { advance: (ms: number) => void } = useClock();
|
|
1222
|
+
const fake: FakeClient = makeFakeClient({
|
|
1223
|
+
rule: [
|
|
1224
|
+
(): SearchDetectionsResult => {
|
|
1225
|
+
// The rule pass is slow enough to spend the whole four minutes.
|
|
1226
|
+
clock.advance(5 * 60 * 1000);
|
|
1227
|
+
return page([detection("slow")]);
|
|
1228
|
+
},
|
|
1229
|
+
],
|
|
1230
|
+
});
|
|
1231
|
+
|
|
1232
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1233
|
+
|
|
1234
|
+
expect(fake.searchCalls).toHaveLength(1);
|
|
1235
|
+
expect(fake.countCalls).toHaveLength(0);
|
|
1236
|
+
expect(fake.alertsCalls).toHaveLength(0);
|
|
1237
|
+
expect(checkByKey(result.checks, "read-rule-detections").status).toBe(
|
|
1238
|
+
"pass",
|
|
1239
|
+
);
|
|
1240
|
+
for (const key of [
|
|
1241
|
+
"read-curated-detections",
|
|
1242
|
+
"read-alerts-view",
|
|
1243
|
+
"read-late-alerts-view",
|
|
1244
|
+
]) {
|
|
1245
|
+
expect(checkByKey(result.checks, key)).toMatchObject({
|
|
1246
|
+
status: "skip",
|
|
1247
|
+
message: "Not run: the poll time budget was spent.",
|
|
1248
|
+
});
|
|
1249
|
+
}
|
|
1250
|
+
expect(result.warnings).toEqual([
|
|
1251
|
+
"Read curated rule detections by created time was not run: the poll time budget was spent.",
|
|
1252
|
+
"Read alerts view by detection time was not run: the poll time budget was spent.",
|
|
1253
|
+
"Read late alerts by detection time was not run: the poll time budget was spent.",
|
|
1254
|
+
]);
|
|
1255
|
+
expect(result.complete).toBe(false);
|
|
1256
|
+
// What was read is still returned for import.
|
|
1257
|
+
expect(uidsOf(result)).toEqual(["slow"]);
|
|
1258
|
+
});
|
|
1259
|
+
|
|
1260
|
+
test("a pass the time budget stops part way names how far it got", async () => {
|
|
1261
|
+
const clock: { advance: (ms: number) => void } = useClock();
|
|
1262
|
+
const fake: FakeClient = makeFakeClient({
|
|
1263
|
+
rule: [
|
|
1264
|
+
page([detection("first")], { nextPageToken: "t1" }),
|
|
1265
|
+
(): SearchDetectionsResult => {
|
|
1266
|
+
clock.advance(5 * 60 * 1000);
|
|
1267
|
+
return page([detection("second")], { nextPageToken: "t2" });
|
|
1268
|
+
},
|
|
1269
|
+
],
|
|
1270
|
+
});
|
|
1271
|
+
|
|
1272
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1273
|
+
|
|
1274
|
+
expect(fake.searchCalls).toHaveLength(2);
|
|
1275
|
+
expect(checkByKey(result.checks, "read-rule-detections")).toMatchObject({
|
|
1276
|
+
status: "warn",
|
|
1277
|
+
message:
|
|
1278
|
+
"2 rule detections returned for the window by created time. The pass was stopped by the poll time budget after 2 requests.",
|
|
1279
|
+
});
|
|
1280
|
+
expect(result.warnings[0]).toBe(
|
|
1281
|
+
"Read rule detections by created time was stopped by the poll time budget after 2 requests.",
|
|
1282
|
+
);
|
|
1283
|
+
expect(result.complete).toBe(false);
|
|
1284
|
+
});
|
|
1285
|
+
|
|
1286
|
+
test("the wall clock is options.maxDurationMs when one is given", async () => {
|
|
1287
|
+
const clock: { advance: (ms: number) => void } = useClock();
|
|
1288
|
+
const fake: FakeClient = makeFakeClient({
|
|
1289
|
+
rule: [
|
|
1290
|
+
(): SearchDetectionsResult => {
|
|
1291
|
+
clock.advance(1500);
|
|
1292
|
+
return page([]);
|
|
1293
|
+
},
|
|
1294
|
+
],
|
|
1295
|
+
});
|
|
1296
|
+
|
|
1297
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1298
|
+
options: { maxDurationMs: 1000 },
|
|
1299
|
+
});
|
|
1300
|
+
|
|
1301
|
+
expect(statusesOf(result.checks)).toEqual([
|
|
1302
|
+
"read-rule-detections:pass",
|
|
1303
|
+
"read-curated-detections:skip",
|
|
1304
|
+
"read-alerts-view:skip",
|
|
1305
|
+
"read-late-alerts-view:skip",
|
|
1306
|
+
]);
|
|
1307
|
+
});
|
|
1308
|
+
|
|
1309
|
+
test.each([undefined, 0, Number.NaN, -5])(
|
|
1310
|
+
"a maxDurationMs of %s falls back to four minutes",
|
|
1311
|
+
async (maxDurationMs: number | undefined) => {
|
|
1312
|
+
const clock: { set: (ms: number) => void } = useClock();
|
|
1313
|
+
const fake: FakeClient = makeFakeClient({
|
|
1314
|
+
rule: [
|
|
1315
|
+
(): SearchDetectionsResult => {
|
|
1316
|
+
clock.set(4 * 60 * 1000 - 1);
|
|
1317
|
+
return page([]);
|
|
1318
|
+
},
|
|
1319
|
+
],
|
|
1320
|
+
/*
|
|
1321
|
+
* The curated pass's count is the last request the fallback clock
|
|
1322
|
+
* still allows, and it leaves the run exactly at four minutes. No
|
|
1323
|
+
* curated rule fired, so the pass ends there, on its count alone.
|
|
1324
|
+
*/
|
|
1325
|
+
counts: [
|
|
1326
|
+
(): Array<CuratedRuleDetectionCount> => {
|
|
1327
|
+
clock.set(4 * 60 * 1000);
|
|
1328
|
+
return [];
|
|
1329
|
+
},
|
|
1330
|
+
],
|
|
1331
|
+
});
|
|
1332
|
+
|
|
1333
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1334
|
+
options: { maxDurationMs },
|
|
1335
|
+
});
|
|
1336
|
+
|
|
1337
|
+
expect(statusesOf(result.checks)).toEqual([
|
|
1338
|
+
"read-rule-detections:pass",
|
|
1339
|
+
"read-curated-detections:pass",
|
|
1340
|
+
"read-alerts-view:skip",
|
|
1341
|
+
"read-late-alerts-view:skip",
|
|
1342
|
+
]);
|
|
1343
|
+
expect(fake.countCalls).toHaveLength(1);
|
|
1344
|
+
expect(fake.alertsCalls).toHaveLength(0);
|
|
1345
|
+
},
|
|
1346
|
+
);
|
|
1347
|
+
|
|
1348
|
+
test("maxRequests caps the requests of every pass together", async () => {
|
|
1349
|
+
const fake: FakeClient = makeFakeClient({ rule: endlessPages("endless") });
|
|
1350
|
+
|
|
1351
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1352
|
+
options: { maxRequests: 3 },
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
expect(fake.searchCalls).toHaveLength(3);
|
|
1356
|
+
expect(fake.countCalls).toHaveLength(0);
|
|
1357
|
+
expect(fake.alertsCalls).toHaveLength(0);
|
|
1358
|
+
expect(result.requestCount).toBe(3);
|
|
1359
|
+
expect(result.complete).toBe(false);
|
|
1360
|
+
expect(checkByKey(result.checks, "read-rule-detections")).toMatchObject({
|
|
1361
|
+
status: "warn",
|
|
1362
|
+
message:
|
|
1363
|
+
"3 rule detections returned for the window by created time. The pass was stopped by the per-run request limit after 3 requests.",
|
|
1364
|
+
});
|
|
1365
|
+
for (const key of [
|
|
1366
|
+
"read-curated-detections",
|
|
1367
|
+
"read-alerts-view",
|
|
1368
|
+
"read-late-alerts-view",
|
|
1369
|
+
]) {
|
|
1370
|
+
expect(checkByKey(result.checks, key)).toMatchObject({
|
|
1371
|
+
status: "skip",
|
|
1372
|
+
message:
|
|
1373
|
+
"Not run: stopped by the per-run request limit after 0 requests. The earlier passes used every request this run allows.",
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
expect(result.warnings).toEqual([
|
|
1377
|
+
"Read rule detections by created time was stopped by the per-run request limit after 3 requests.",
|
|
1378
|
+
"Read curated rule detections by created time was stopped by the per-run request limit after 0 requests.",
|
|
1379
|
+
"Read alerts view by detection time was stopped by the per-run request limit after 0 requests.",
|
|
1380
|
+
"Read late alerts by detection time was stopped by the per-run request limit after 0 requests.",
|
|
1381
|
+
]);
|
|
1382
|
+
});
|
|
1383
|
+
|
|
1384
|
+
test("the poller's single-list default of 20 requests leaves the alerts view unread, and says so", async () => {
|
|
1385
|
+
const fake: FakeClient = makeFakeClient({ rule: endlessPages("endless") });
|
|
1386
|
+
|
|
1387
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1388
|
+
options: { maxRequests: 20 },
|
|
1389
|
+
});
|
|
1390
|
+
|
|
1391
|
+
expect(result.requestCount).toBe(20);
|
|
1392
|
+
expect(fake.alertsCalls).toHaveLength(0);
|
|
1393
|
+
expect(checkByKey(result.checks, "read-alerts-view").message).toBe(
|
|
1394
|
+
"Not run: stopped by the per-run request limit after 0 requests. The earlier passes used every request this run allows.",
|
|
1395
|
+
);
|
|
1396
|
+
});
|
|
1397
|
+
|
|
1398
|
+
test.each([undefined, Number.NaN, 0])(
|
|
1399
|
+
"a maxRequests of %s falls back to the connector's own budget",
|
|
1400
|
+
async (maxRequests: number | undefined) => {
|
|
1401
|
+
const fake: FakeClient = makeFakeClient({
|
|
1402
|
+
rule: endlessPages("endless"),
|
|
1403
|
+
});
|
|
1404
|
+
|
|
1405
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1406
|
+
options: { maxRequests: maxRequests as number },
|
|
1407
|
+
});
|
|
1408
|
+
|
|
1409
|
+
// 20 rule pages, the curated count and search, alerts view and sweep.
|
|
1410
|
+
expect(result.requestCount).toBe(24);
|
|
1411
|
+
},
|
|
1412
|
+
);
|
|
1413
|
+
|
|
1414
|
+
test("maxEvents stops collecting mid-page with complete=false and names the record limit", async () => {
|
|
1415
|
+
const fake: FakeClient = makeFakeClient({
|
|
1416
|
+
rule: [page([detection("a"), detection("b"), detection("c")])],
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1419
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1420
|
+
options: { maxEvents: 2 },
|
|
1421
|
+
});
|
|
1422
|
+
|
|
1423
|
+
expect(result.fetchedCount).toBe(2);
|
|
1424
|
+
expect(uidsOf(result)).toEqual(["a", "b"]);
|
|
1425
|
+
expect(result.complete).toBe(false);
|
|
1426
|
+
expect(fake.searchCalls).toHaveLength(1);
|
|
1427
|
+
expect(fake.alertsCalls).toHaveLength(0);
|
|
1428
|
+
expect(checkByKey(result.checks, "read-rule-detections")).toMatchObject({
|
|
1429
|
+
status: "warn",
|
|
1430
|
+
message:
|
|
1431
|
+
"3 rule detections returned for the window by created time. The pass was stopped by the per-run record limit after 1 request.",
|
|
1432
|
+
});
|
|
1433
|
+
for (const key of [
|
|
1434
|
+
"read-curated-detections",
|
|
1435
|
+
"read-alerts-view",
|
|
1436
|
+
"read-late-alerts-view",
|
|
1437
|
+
]) {
|
|
1438
|
+
expect(checkByKey(result.checks, key)).toMatchObject({
|
|
1439
|
+
status: "skip",
|
|
1440
|
+
message:
|
|
1441
|
+
"Not run: stopped by the per-run record limit after 0 requests. The earlier passes collected every record this run allows.",
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
expect(result.warnings[0]).toBe(
|
|
1445
|
+
"Read rule detections by created time was stopped by the per-run record limit after 1 request.",
|
|
1446
|
+
);
|
|
1447
|
+
});
|
|
1448
|
+
|
|
1449
|
+
test("a record already collected never counts against maxEvents, while a full union stops the passes after it", async () => {
|
|
1450
|
+
const fake: FakeClient = makeFakeClient({
|
|
1451
|
+
rule: [page([detection("a"), detection("b"), detection("a")])],
|
|
1452
|
+
});
|
|
1453
|
+
|
|
1454
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1455
|
+
options: { maxEvents: 2 },
|
|
1456
|
+
});
|
|
1457
|
+
|
|
1458
|
+
expect(result.fetchedCount).toBe(2);
|
|
1459
|
+
// The repeated record did not hit the bound, so the rule pass read everything.
|
|
1460
|
+
expect(checkByKey(result.checks, "read-rule-detections")).toMatchObject({
|
|
1461
|
+
status: "pass",
|
|
1462
|
+
message: "3 rule detections returned for the window by created time.",
|
|
1463
|
+
});
|
|
1464
|
+
// A later pass could add records, so it does not start once the bound is reached.
|
|
1465
|
+
expect(checkByKey(result.checks, "read-curated-detections")).toMatchObject({
|
|
1466
|
+
status: "skip",
|
|
1467
|
+
message:
|
|
1468
|
+
"Not run: stopped by the per-run record limit after 0 requests. The earlier passes collected every record this run allows.",
|
|
1469
|
+
});
|
|
1470
|
+
expect(fake.searchCalls).toHaveLength(1);
|
|
1471
|
+
expect(result.complete).toBe(false);
|
|
1472
|
+
});
|
|
1473
|
+
|
|
1474
|
+
test("an alerts-view response that crosses maxEvents stops the alerts view", async () => {
|
|
1475
|
+
const fake: FakeClient = makeFakeClient({
|
|
1476
|
+
rule: [page([detection("a")])],
|
|
1477
|
+
alerts: [
|
|
1478
|
+
fetched([detection("b"), detection("c"), detection("d")], {
|
|
1479
|
+
truncatedByCount: true,
|
|
1480
|
+
}),
|
|
1481
|
+
],
|
|
1482
|
+
});
|
|
1483
|
+
|
|
1484
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1485
|
+
options: { maxEvents: 3 },
|
|
1486
|
+
window: DAY_WINDOW,
|
|
1487
|
+
});
|
|
1488
|
+
|
|
1489
|
+
expect(result.fetchedCount).toBe(3);
|
|
1490
|
+
expect(fake.alertsCalls).toHaveLength(1);
|
|
1491
|
+
expect(result.complete).toBe(false);
|
|
1492
|
+
expect(checkByKey(result.checks, "read-alerts-view")).toMatchObject({
|
|
1493
|
+
status: "warn",
|
|
1494
|
+
message:
|
|
1495
|
+
"3 alerts returned by detection time. The pass was stopped by the per-run record limit after 1 request.",
|
|
1496
|
+
});
|
|
1497
|
+
// A stopped alerts view does not also report the split it never made.
|
|
1498
|
+
expect(result.warnings).toEqual([
|
|
1499
|
+
"Read alerts view by detection time was stopped by the per-run record limit after 1 request.",
|
|
1500
|
+
]);
|
|
1501
|
+
});
|
|
1502
|
+
|
|
1503
|
+
test.each([undefined, Number.NaN, 0])(
|
|
1504
|
+
"a maxEvents of %s falls back to the connector's own record bound",
|
|
1505
|
+
async (maxEvents: number | undefined) => {
|
|
1506
|
+
const fake: FakeClient = makeFakeClient({
|
|
1507
|
+
rule: [page([detection("a"), detection("b")])],
|
|
1508
|
+
});
|
|
1509
|
+
|
|
1510
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1511
|
+
options: { maxEvents: maxEvents as number },
|
|
1512
|
+
});
|
|
1513
|
+
|
|
1514
|
+
expect(result.fetchedCount).toBe(2);
|
|
1515
|
+
expect(result.complete).toBe(true);
|
|
1516
|
+
},
|
|
1517
|
+
);
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
describe("GoogleSecOpsConnector.fetchEvents alerts view and truncation", () => {
|
|
1521
|
+
afterEach(() => {
|
|
1522
|
+
jest.restoreAllMocks();
|
|
1523
|
+
});
|
|
1524
|
+
|
|
1525
|
+
const truncations: Array<[string, Partial<FetchAlertsResult>]> = [
|
|
1526
|
+
["truncatedByCount", { truncatedByCount: true }],
|
|
1527
|
+
["truncatedByBytes", { truncatedByBytes: true }],
|
|
1528
|
+
["a filtered count above what was returned", { filteredAlertsCount: 2 }],
|
|
1529
|
+
["a baseline count above what was returned", { baselineAlertsCount: 2 }],
|
|
1530
|
+
];
|
|
1531
|
+
|
|
1532
|
+
test.each(truncations)(
|
|
1533
|
+
"%s splits the window at its midpoint into contiguous halves and unions the records",
|
|
1534
|
+
async (_label: string, flags: Partial<FetchAlertsResult>) => {
|
|
1535
|
+
const fake: FakeClient = makeFakeClient({
|
|
1536
|
+
alerts: [
|
|
1537
|
+
fetched([detection("a")], flags),
|
|
1538
|
+
fetched([detection("a")]),
|
|
1539
|
+
fetched([detection("b")]),
|
|
1540
|
+
// The late-alert sweep finds nothing.
|
|
1541
|
+
fetched([]),
|
|
1542
|
+
],
|
|
1543
|
+
});
|
|
1544
|
+
|
|
1545
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1546
|
+
|
|
1547
|
+
expect(fake.alertsCalls).toHaveLength(4);
|
|
1548
|
+
expect(windowReadsOf(fake)).toHaveLength(3);
|
|
1549
|
+
const [whole, first, second] = windowReadsOf(fake);
|
|
1550
|
+
const midpoint: number = Math.floor(
|
|
1551
|
+
(WINDOW.startTime.getTime() + WINDOW.endTime.getTime()) / 2,
|
|
1552
|
+
);
|
|
1553
|
+
expect(first!.startTime).toEqual(whole!.startTime);
|
|
1554
|
+
expect(first!.endTime.getTime()).toBe(midpoint);
|
|
1555
|
+
expect(second!.startTime.getTime()).toBe(midpoint);
|
|
1556
|
+
expect(second!.endTime).toEqual(whole!.endTime);
|
|
1557
|
+
// Rule search, curated count and search, three window reads, sweep.
|
|
1558
|
+
expect(result).toMatchObject({
|
|
1559
|
+
complete: true,
|
|
1560
|
+
fetchedCount: 2,
|
|
1561
|
+
requestCount: 7,
|
|
1562
|
+
details: expect.objectContaining({
|
|
1563
|
+
sourceCounts: {
|
|
1564
|
+
ruleDetections: 0,
|
|
1565
|
+
curatedDetections: 0,
|
|
1566
|
+
alertsView: 3,
|
|
1567
|
+
lateAlertsView: 0,
|
|
1568
|
+
},
|
|
1569
|
+
}),
|
|
1570
|
+
});
|
|
1571
|
+
expect(checkByKey(result.checks, "read-alerts-view").status).toBe("pass");
|
|
1572
|
+
expect(result.warnings).toEqual([
|
|
1573
|
+
"Google limited the alerts view response for 2026-09-14T11:54:00.000Z to 2026-09-14T12:00:00.000Z, so it was split into smaller windows 1 time.",
|
|
1574
|
+
]);
|
|
1575
|
+
},
|
|
1576
|
+
);
|
|
1577
|
+
|
|
1578
|
+
test("a one-second window that is still truncated is reported unread, once", async () => {
|
|
1579
|
+
const twoSeconds: ConnectorFetchWindow = {
|
|
1580
|
+
startTime: new Date("2026-09-14T11:59:58.000Z"),
|
|
1581
|
+
endTime: new Date("2026-09-14T12:00:00.000Z"),
|
|
1582
|
+
};
|
|
1583
|
+
const burst: FetchAlertsResult = fetched([detection("burst")], {
|
|
1584
|
+
truncatedByCount: true,
|
|
1585
|
+
});
|
|
1586
|
+
const fake: FakeClient = makeFakeClient({
|
|
1587
|
+
// Three truncated window reads, then a late-alert sweep that finds nothing.
|
|
1588
|
+
alerts: [burst, burst, burst, fetched([])],
|
|
1589
|
+
});
|
|
1590
|
+
|
|
1591
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1592
|
+
window: twoSeconds,
|
|
1593
|
+
});
|
|
1594
|
+
|
|
1595
|
+
// The two-second window splits once; both one-second halves stay truncated.
|
|
1596
|
+
expect(windowReadsOf(fake, twoSeconds)).toHaveLength(3);
|
|
1597
|
+
expect(fake.alertsCalls).toHaveLength(4);
|
|
1598
|
+
expect(result.complete).toBe(false);
|
|
1599
|
+
expect(result.warnings).toEqual([
|
|
1600
|
+
"Google still truncated a one-second window of the alerts view, so some alerts in it were not read.",
|
|
1601
|
+
"Google limited the alerts view response for 2026-09-14T11:59:58.000Z to 2026-09-14T12:00:00.000Z, so it was split into smaller windows 1 time.",
|
|
1602
|
+
]);
|
|
1603
|
+
expect(checkByKey(result.checks, "read-alerts-view")).toMatchObject({
|
|
1604
|
+
status: "warn",
|
|
1605
|
+
message:
|
|
1606
|
+
"3 alerts returned by detection time. Google did not return part of the window.",
|
|
1607
|
+
});
|
|
1608
|
+
});
|
|
1609
|
+
|
|
1610
|
+
test("an alerts-view stream that never completed leaves the window unread without splitting", async () => {
|
|
1611
|
+
const fake: FakeClient = makeFakeClient({
|
|
1612
|
+
alerts: [
|
|
1613
|
+
fetched([detection("partial")], { complete: false }),
|
|
1614
|
+
// The late-alert sweep finds nothing.
|
|
1615
|
+
fetched([]),
|
|
1616
|
+
],
|
|
1617
|
+
});
|
|
1618
|
+
|
|
1619
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1620
|
+
|
|
1621
|
+
expect(windowReadsOf(fake)).toHaveLength(1);
|
|
1622
|
+
expect(fake.alertsCalls).toHaveLength(2);
|
|
1623
|
+
expect(result.complete).toBe(false);
|
|
1624
|
+
expect(result.warnings).toEqual([
|
|
1625
|
+
"Google ended an alerts view response without confirming it was complete.",
|
|
1626
|
+
]);
|
|
1627
|
+
expect(checkByKey(result.checks, "read-alerts-view")).toMatchObject({
|
|
1628
|
+
status: "warn",
|
|
1629
|
+
message:
|
|
1630
|
+
"1 alerts returned by detection time. Google did not return part of the window.",
|
|
1631
|
+
});
|
|
1632
|
+
// What arrived is still returned for import.
|
|
1633
|
+
expect(uidsOf(result)).toEqual(["partial"]);
|
|
1634
|
+
});
|
|
1635
|
+
|
|
1636
|
+
test("a search page truncated by size leaves the window unread and says so once", async () => {
|
|
1637
|
+
const fake: FakeClient = makeFakeClient({
|
|
1638
|
+
rule: [
|
|
1639
|
+
page([detection("t1")], { truncated: true, nextPageToken: "more" }),
|
|
1640
|
+
page([detection("t2")], { truncated: true }),
|
|
1641
|
+
],
|
|
1642
|
+
curated: [page([detection("c1")], { truncated: true })],
|
|
1643
|
+
});
|
|
1644
|
+
|
|
1645
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1646
|
+
|
|
1647
|
+
expect(result.complete).toBe(false);
|
|
1648
|
+
expect(uidsOf(result)).toEqual(["c1", "t1", "t2"]);
|
|
1649
|
+
expect(result.warnings).toEqual([
|
|
1650
|
+
"Google truncated a page of rule detections by size for 2026-09-14T11:54:00.000Z to 2026-09-14T12:00:00.000Z, so part of the window was not read.",
|
|
1651
|
+
"Google truncated a page of curated rule detections by size for 2026-09-14T11:54:00.000Z to 2026-09-14T12:00:00.000Z, so part of the window was not read.",
|
|
1652
|
+
]);
|
|
1653
|
+
expect(checkByKey(result.checks, "read-rule-detections")).toMatchObject({
|
|
1654
|
+
status: "warn",
|
|
1655
|
+
message:
|
|
1656
|
+
"2 rule detections returned for the window by created time. Google did not return part of the window.",
|
|
1657
|
+
});
|
|
1658
|
+
expect(checkByKey(result.checks, "read-curated-detections").status).toBe(
|
|
1659
|
+
"warn",
|
|
1660
|
+
);
|
|
1661
|
+
});
|
|
1662
|
+
|
|
1663
|
+
test("an alerts-view window read in several requests is still one pass check", async () => {
|
|
1664
|
+
const fake: FakeClient = makeFakeClient({
|
|
1665
|
+
alerts: [
|
|
1666
|
+
fetched([detection("a")], { truncatedByBytes: true }),
|
|
1667
|
+
fetched([detection("b")], { truncatedByBytes: true }),
|
|
1668
|
+
fetched([detection("c")]),
|
|
1669
|
+
fetched([detection("d")]),
|
|
1670
|
+
fetched([detection("d")]),
|
|
1671
|
+
// The late-alert sweep finds nothing.
|
|
1672
|
+
fetched([]),
|
|
1673
|
+
],
|
|
1674
|
+
});
|
|
1675
|
+
|
|
1676
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1677
|
+
|
|
1678
|
+
expect(windowReadsOf(fake)).toHaveLength(5);
|
|
1679
|
+
expect(fake.alertsCalls).toHaveLength(6);
|
|
1680
|
+
expect(
|
|
1681
|
+
result.checks!.filter((check: SecurityConnectorCheck): boolean => {
|
|
1682
|
+
return check.key === "read-alerts-view";
|
|
1683
|
+
}),
|
|
1684
|
+
).toHaveLength(1);
|
|
1685
|
+
expect(result.warnings).toEqual([
|
|
1686
|
+
"Google limited the alerts view response for 2026-09-14T11:54:00.000Z to 2026-09-14T12:00:00.000Z, so it was split into smaller windows 2 times.",
|
|
1687
|
+
]);
|
|
1688
|
+
});
|
|
1689
|
+
});
|
|
1690
|
+
|
|
1691
|
+
describe("GoogleSecOpsConnector.fetchEvents samples and creation lag", () => {
|
|
1692
|
+
afterEach(() => {
|
|
1693
|
+
jest.restoreAllMocks();
|
|
1694
|
+
});
|
|
1695
|
+
|
|
1696
|
+
test("a sample carries the rule name as title, both times and the alert state", async () => {
|
|
1697
|
+
const fake: FakeClient = makeFakeClient({
|
|
1698
|
+
rule: [
|
|
1699
|
+
page([
|
|
1700
|
+
detection("alerting"),
|
|
1701
|
+
detection("quiet", {
|
|
1702
|
+
detection: [
|
|
1703
|
+
{
|
|
1704
|
+
ruleName: "Quiet rule",
|
|
1705
|
+
alertState: "NOT_ALERTING",
|
|
1706
|
+
severity: "LOW",
|
|
1707
|
+
},
|
|
1708
|
+
],
|
|
1709
|
+
}),
|
|
1710
|
+
detection("legacy-quiet", {
|
|
1711
|
+
detection: [{ ruleName: "Legacy", alertState: "NON_ALERTING" }],
|
|
1712
|
+
}),
|
|
1713
|
+
detection("boolean", {
|
|
1714
|
+
detection: [{ ruleName: "Boolean", alerting: true }],
|
|
1715
|
+
}),
|
|
1716
|
+
detection("unknown-state", {
|
|
1717
|
+
detection: [{ ruleName: "Unknown", alertState: "SOMETHING" }],
|
|
1718
|
+
}),
|
|
1719
|
+
{
|
|
1720
|
+
id: "snake",
|
|
1721
|
+
type: "RULE_DETECTION",
|
|
1722
|
+
detection_time: "2026-09-14T10:00:00.000Z",
|
|
1723
|
+
created_time: "2026-09-14T10:30:00.000Z",
|
|
1724
|
+
detection: [{ ruleName: "Snake rule", alert_state: "ALERTING" }],
|
|
1725
|
+
},
|
|
1726
|
+
{
|
|
1727
|
+
id: "telemetry",
|
|
1728
|
+
type: "TELEMETRY_ALERT",
|
|
1729
|
+
detectionTime: "2026-09-14T11:30:00.000Z",
|
|
1730
|
+
},
|
|
1731
|
+
]),
|
|
1732
|
+
],
|
|
1733
|
+
});
|
|
1734
|
+
|
|
1735
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1736
|
+
const byId: Map<string, SecurityConnectorSample> = new Map(
|
|
1737
|
+
result.samples.map(
|
|
1738
|
+
(
|
|
1739
|
+
sample: SecurityConnectorSample,
|
|
1740
|
+
): [string, SecurityConnectorSample] => {
|
|
1741
|
+
return [sample.id, sample];
|
|
1742
|
+
},
|
|
1743
|
+
),
|
|
1744
|
+
);
|
|
1745
|
+
|
|
1746
|
+
expect(byId.get("alerting")).toEqual({
|
|
1747
|
+
id: "alerting",
|
|
1748
|
+
title: "Rule for alerting",
|
|
1749
|
+
severity: "High",
|
|
1750
|
+
createdTime: "2026-09-14T11:02:00.000Z",
|
|
1751
|
+
eventTime: "2026-09-14T11:00:00.000Z",
|
|
1752
|
+
isAlert: true,
|
|
1753
|
+
});
|
|
1754
|
+
expect(byId.get("quiet")).toMatchObject({
|
|
1755
|
+
title: "Quiet rule",
|
|
1756
|
+
severity: "Low",
|
|
1757
|
+
isAlert: false,
|
|
1758
|
+
});
|
|
1759
|
+
expect(byId.get("legacy-quiet")!.isAlert).toBe(false);
|
|
1760
|
+
expect(byId.get("boolean")!.isAlert).toBe(true);
|
|
1761
|
+
expect(
|
|
1762
|
+
Object.prototype.hasOwnProperty.call(
|
|
1763
|
+
byId.get("unknown-state"),
|
|
1764
|
+
"isAlert",
|
|
1765
|
+
),
|
|
1766
|
+
).toBe(false);
|
|
1767
|
+
expect(byId.get("snake")).toMatchObject({
|
|
1768
|
+
title: "Snake rule",
|
|
1769
|
+
createdTime: "2026-09-14T10:30:00.000Z",
|
|
1770
|
+
eventTime: "2026-09-14T10:00:00.000Z",
|
|
1771
|
+
isAlert: true,
|
|
1772
|
+
});
|
|
1773
|
+
// A collection with no rule keeps the finding's message as its title.
|
|
1774
|
+
expect(byId.get("telemetry")).toMatchObject({
|
|
1775
|
+
title: "Google SecOps telemetry alert",
|
|
1776
|
+
eventTime: "2026-09-14T11:30:00.000Z",
|
|
1777
|
+
});
|
|
1778
|
+
expect(byId.get("telemetry")!.createdTime).toBeUndefined();
|
|
1779
|
+
});
|
|
1780
|
+
|
|
1781
|
+
test.each([
|
|
1782
|
+
[25, 30, 25],
|
|
1783
|
+
[0, 5, 0],
|
|
1784
|
+
[2.9, 5, 2],
|
|
1785
|
+
[-1, 5, 0],
|
|
1786
|
+
])(
|
|
1787
|
+
"a sampleLimit of %s over %s records keeps %s samples",
|
|
1788
|
+
async (sampleLimit: number, records: number, expected: number) => {
|
|
1789
|
+
const fake: FakeClient = makeFakeClient({
|
|
1790
|
+
rule: [
|
|
1791
|
+
page(
|
|
1792
|
+
Array.from(
|
|
1793
|
+
{ length: records },
|
|
1794
|
+
(_value: unknown, index: number): JSONObject => {
|
|
1795
|
+
return detection(`d-${index}`);
|
|
1796
|
+
},
|
|
1797
|
+
),
|
|
1798
|
+
),
|
|
1799
|
+
],
|
|
1800
|
+
});
|
|
1801
|
+
|
|
1802
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1803
|
+
options: { sampleLimit },
|
|
1804
|
+
});
|
|
1805
|
+
|
|
1806
|
+
expect(result.events).toHaveLength(records);
|
|
1807
|
+
expect(result.samples).toHaveLength(expected);
|
|
1808
|
+
},
|
|
1809
|
+
);
|
|
1810
|
+
|
|
1811
|
+
test("samples are redacted and never carry the source payload", async () => {
|
|
1812
|
+
const fake: FakeClient = makeFakeClient({
|
|
1813
|
+
rule: [
|
|
1814
|
+
page([
|
|
1815
|
+
detection(
|
|
1816
|
+
'leak {"private_key":"-----BEGIN PRIVATE KEY-----leaked-id"}',
|
|
1817
|
+
{
|
|
1818
|
+
private_key: "source-private-key",
|
|
1819
|
+
detection: [
|
|
1820
|
+
{
|
|
1821
|
+
ruleName:
|
|
1822
|
+
'Rule {"private_key":"-----BEGIN PRIVATE KEY-----leaked-title"}',
|
|
1823
|
+
},
|
|
1824
|
+
],
|
|
1825
|
+
},
|
|
1826
|
+
),
|
|
1827
|
+
]),
|
|
1828
|
+
],
|
|
1829
|
+
});
|
|
1830
|
+
|
|
1831
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1832
|
+
|
|
1833
|
+
expect(result.samples).toHaveLength(1);
|
|
1834
|
+
const text: string = JSON.stringify(result.samples);
|
|
1835
|
+
expect(text).not.toContain("leaked-id");
|
|
1836
|
+
expect(text).not.toContain("leaked-title");
|
|
1837
|
+
expect(text).not.toContain("source-private-key");
|
|
1838
|
+
});
|
|
1839
|
+
|
|
1840
|
+
test("creation lag is measured over the union and a lag beyond the poll interval explains the created-time basis", async () => {
|
|
1841
|
+
const fake: FakeClient = makeFakeClient({
|
|
1842
|
+
rule: [
|
|
1843
|
+
page([
|
|
1844
|
+
detection("late", {
|
|
1845
|
+
detectionTime: "2026-09-14T08:00:00.000Z",
|
|
1846
|
+
createdTime: "2026-09-14T11:00:00.000Z",
|
|
1847
|
+
}),
|
|
1848
|
+
detection("prompt", {
|
|
1849
|
+
detectionTime: "2026-09-14T11:00:00.000Z",
|
|
1850
|
+
createdTime: "2026-09-14T11:02:00.000Z",
|
|
1851
|
+
}),
|
|
1852
|
+
detection("no-created", { createdTime: undefined }),
|
|
1853
|
+
]),
|
|
1854
|
+
],
|
|
1855
|
+
// The same late record again from the alerts view is measured once.
|
|
1856
|
+
alerts: [
|
|
1857
|
+
fetched([
|
|
1858
|
+
detection("late", {
|
|
1859
|
+
detectionTime: "2026-09-14T08:00:00.000Z",
|
|
1860
|
+
createdTime: "2026-09-14T11:00:00.000Z",
|
|
1861
|
+
}),
|
|
1862
|
+
]),
|
|
1863
|
+
],
|
|
1864
|
+
});
|
|
1865
|
+
|
|
1866
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1867
|
+
options: { pollIntervalInMinutes: 5 },
|
|
1868
|
+
});
|
|
1869
|
+
|
|
1870
|
+
expect(result.details).toMatchObject({
|
|
1871
|
+
creationLag: { measured: 2, lateCount: 1, maxLagMinutes: 180 },
|
|
1872
|
+
});
|
|
1873
|
+
expect(result.warnings).toEqual([
|
|
1874
|
+
"1 of 2 detections were created more than 6 minutes after their detection time (up to 180 minutes). This is why the connector polls by created time: a cursor over detection time would already have moved past them.",
|
|
1875
|
+
]);
|
|
1876
|
+
// Informational: the fetch is still complete.
|
|
1877
|
+
expect(result.complete).toBe(true);
|
|
1878
|
+
});
|
|
1879
|
+
|
|
1880
|
+
const thresholds: Array<[number | undefined, number, boolean]> = [
|
|
1881
|
+
[undefined, 6, true],
|
|
1882
|
+
[0, 6, true],
|
|
1883
|
+
[5, 6, true],
|
|
1884
|
+
[30, 31, false],
|
|
1885
|
+
[-4, 2, true],
|
|
1886
|
+
];
|
|
1887
|
+
|
|
1888
|
+
test.each(thresholds)(
|
|
1889
|
+
"a pollIntervalInMinutes of %s gives a %s minute threshold (a 7 minute lag is late: %s)",
|
|
1890
|
+
async (
|
|
1891
|
+
pollIntervalInMinutes: number | undefined,
|
|
1892
|
+
threshold: number,
|
|
1893
|
+
late: boolean,
|
|
1894
|
+
) => {
|
|
1895
|
+
const fake: FakeClient = makeFakeClient({
|
|
1896
|
+
rule: [
|
|
1897
|
+
page([
|
|
1898
|
+
detection("seven", {
|
|
1899
|
+
detectionTime: "2026-09-14T11:00:00.000Z",
|
|
1900
|
+
createdTime: "2026-09-14T11:07:00.000Z",
|
|
1901
|
+
}),
|
|
1902
|
+
]),
|
|
1903
|
+
],
|
|
1904
|
+
});
|
|
1905
|
+
|
|
1906
|
+
const result: ConnectorFetchResult = await fetchWith(fake, {
|
|
1907
|
+
options: { pollIntervalInMinutes },
|
|
1908
|
+
});
|
|
1909
|
+
|
|
1910
|
+
expect(result.details).toMatchObject({
|
|
1911
|
+
creationLag: { measured: 1, lateCount: late ? 1 : 0, maxLagMinutes: 7 },
|
|
1912
|
+
});
|
|
1913
|
+
expect(result.warnings).toEqual(
|
|
1914
|
+
late
|
|
1915
|
+
? [
|
|
1916
|
+
`1 of 1 detections were created more than ${threshold} minutes after their detection time (up to 7 minutes). This is why the connector polls by created time: a cursor over detection time would already have moved past them.`,
|
|
1917
|
+
]
|
|
1918
|
+
: [],
|
|
1919
|
+
);
|
|
1920
|
+
},
|
|
1921
|
+
);
|
|
1922
|
+
|
|
1923
|
+
test("creation lag reads snake_case times, ignores unparseable ones and never goes negative", async () => {
|
|
1924
|
+
const fake: FakeClient = makeFakeClient({
|
|
1925
|
+
rule: [
|
|
1926
|
+
page([
|
|
1927
|
+
{
|
|
1928
|
+
id: "snake",
|
|
1929
|
+
type: "RULE_DETECTION",
|
|
1930
|
+
detection_time: "2026-09-14T11:00:00.000Z",
|
|
1931
|
+
created_time: "2026-09-14T11:01:00.000Z",
|
|
1932
|
+
detection: [{ ruleName: "Snake" }],
|
|
1933
|
+
},
|
|
1934
|
+
detection("garbage", { createdTime: "not a time" }),
|
|
1935
|
+
detection("created-before-detected", {
|
|
1936
|
+
detectionTime: "2026-09-14T11:05:00.000Z",
|
|
1937
|
+
createdTime: "2026-09-14T11:00:00.000Z",
|
|
1938
|
+
}),
|
|
1939
|
+
]),
|
|
1940
|
+
],
|
|
1941
|
+
});
|
|
1942
|
+
|
|
1943
|
+
const result: ConnectorFetchResult = await fetchWith(fake);
|
|
1944
|
+
|
|
1945
|
+
expect(result.details).toMatchObject({
|
|
1946
|
+
creationLag: { measured: 2, lateCount: 0, maxLagMinutes: 1 },
|
|
1947
|
+
});
|
|
1948
|
+
expect(result.warnings).toEqual([]);
|
|
1949
|
+
});
|
|
1950
|
+
|
|
1951
|
+
test("an empty window measures nothing and returns empty diagnostics", async () => {
|
|
1952
|
+
// No curated rule fired either, so the count is the only curated request.
|
|
1953
|
+
const result: ConnectorFetchResult = await fetchWith(
|
|
1954
|
+
makeFakeClient({ counts: [[]] }),
|
|
1955
|
+
);
|
|
1956
|
+
|
|
1957
|
+
// Rule search, curated count, alerts view, late-alert sweep.
|
|
1958
|
+
expect(result).toMatchObject({
|
|
1959
|
+
events: [],
|
|
1960
|
+
fetchedCount: 0,
|
|
1961
|
+
samples: [],
|
|
1962
|
+
complete: true,
|
|
1963
|
+
requestCount: 4,
|
|
1964
|
+
});
|
|
1965
|
+
expect(result.details).toEqual({
|
|
1966
|
+
basis: "created-time",
|
|
1967
|
+
sourceCounts: {
|
|
1968
|
+
ruleDetections: 0,
|
|
1969
|
+
curatedDetections: 0,
|
|
1970
|
+
alertsView: 0,
|
|
1971
|
+
lateAlertsView: 0,
|
|
1972
|
+
},
|
|
1973
|
+
curatedRulesWithDetections: 0,
|
|
1974
|
+
creationLag: { measured: 0, lateCount: 0, maxLagMinutes: 0 },
|
|
1975
|
+
includeNonAlertingDetections: false,
|
|
1976
|
+
});
|
|
1977
|
+
});
|
|
1978
|
+
|
|
1979
|
+
test("the default connector builds a real client, so settings are the only input", async () => {
|
|
1980
|
+
// No fetch implementation and no factory: a real client over global fetch.
|
|
1981
|
+
const connector: GoogleSecOpsConnector = new GoogleSecOpsConnector();
|
|
1982
|
+
const error: unknown = await rejectionOf(
|
|
1983
|
+
connector.fetchEvents(
|
|
1984
|
+
secOpsSettings({ secrets: { serviceAccountJson: "{" } }),
|
|
1985
|
+
WINDOW,
|
|
1986
|
+
fetchOptions(),
|
|
1987
|
+
),
|
|
1988
|
+
);
|
|
1989
|
+
|
|
1990
|
+
expect((error as Error).message).toBe(
|
|
1991
|
+
"Service account JSON is not valid JSON.",
|
|
1992
|
+
);
|
|
1993
|
+
});
|
|
1994
|
+
});
|