@oneuptime/common 13.0.5 → 13.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/AuditLog.ts +81 -1
- package/Models/AnalyticsModels/SecurityEvent.ts +4 -4
- package/Models/DatabaseModels/Alert.ts +62 -0
- package/Models/DatabaseModels/GlobalConfig.ts +1 -1
- package/Models/DatabaseModels/Incident.ts +66 -0
- package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +74 -0
- package/Models/DatabaseModels/IncidentPublicNote.ts +74 -0
- package/Models/DatabaseModels/Index.ts +6 -4
- package/Models/DatabaseModels/NetworkDevice.ts +67 -0
- package/Models/DatabaseModels/NetworkDeviceDiagnostic.ts +746 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +151 -0
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +1 -1
- package/Models/DatabaseModels/Project.ts +41 -0
- package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +74 -0
- package/Models/DatabaseModels/SecurityEventConnection.ts +11 -11
- package/Models/DatabaseModels/ServiceLevelObjective.ts +185 -8
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +746 -43
- package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +575 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +582 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +16 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +16 -0
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +75 -0
- package/Models/DatabaseModels/ThreatIntelFeed.ts +1 -1
- package/Server/API/BaseAPI.ts +17 -0
- package/Server/API/BillingInvoiceAPI.ts +343 -30
- package/Server/API/BillingPaymentMethodAPI.ts +126 -5
- package/Server/API/DashboardAPI.ts +96 -2
- package/Server/API/SecurityEventConnectionAPI.ts +141 -11
- package/Server/API/StatusPageAPI.ts +308 -199
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.ts +83 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.ts +36 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.ts +516 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.ts +98 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.ts +97 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
- package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +138 -67
- package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +213 -84
- package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +112 -35
- package/Server/Services/AlertLabelRuleEngineService.ts +299 -217
- package/Server/Services/AlertOwnerRuleEngineService.ts +572 -396
- package/Server/Services/AlertPrivacyRuleEngineService.ts +116 -40
- package/Server/Services/AlertService.ts +111 -4
- package/Server/Services/AuditLogService.ts +612 -59
- package/Server/Services/BillingInvoiceService.ts +112 -102
- package/Server/Services/BillingService.ts +539 -11
- package/Server/Services/CephClusterLabelRuleEngineService.ts +170 -109
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +233 -115
- package/Server/Services/CloudResourceLabelRuleEngineService.ts +163 -100
- package/Server/Services/CloudResourceOwnerRuleEngineService.ts +236 -115
- package/Server/Services/DashboardLabelRuleEngineService.ts +145 -84
- package/Server/Services/DashboardOwnerRuleEngineService.ts +213 -95
- package/Server/Services/DatabaseService.ts +171 -21
- package/Server/Services/DockerHostLabelRuleEngineService.ts +171 -110
- package/Server/Services/DockerHostOwnerRuleEngineService.ts +233 -115
- package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +181 -112
- package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +243 -118
- package/Server/Services/HostLabelRuleEngineService.ts +167 -106
- package/Server/Services/HostOwnerRuleEngineService.ts +229 -111
- package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +141 -67
- package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +272 -72
- package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +112 -35
- package/Server/Services/IncidentEpisodePublicNoteService.ts +24 -0
- package/Server/Services/IncidentLabelRuleEngineService.ts +279 -204
- package/Server/Services/IncidentOwnerRuleEngineService.ts +595 -425
- package/Server/Services/IncidentPrivacyRuleEngineService.ts +117 -44
- package/Server/Services/IncidentPublicNoteService.ts +24 -0
- package/Server/Services/IncidentService.ts +114 -3
- package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +147 -83
- package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +221 -100
- package/Server/Services/Index.ts +6 -4
- package/Server/Services/IoTFleetLabelRuleEngineService.ts +145 -84
- package/Server/Services/IoTFleetOwnerRuleEngineService.ts +213 -95
- package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +181 -112
- package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +243 -118
- package/Server/Services/LabelService.ts +23 -28
- package/Server/Services/MonitorLabelRuleEngineService.ts +152 -92
- package/Server/Services/MonitorOwnerRuleEngineService.ts +220 -104
- package/Server/Services/MonitorProbeService.ts +20 -2
- package/Server/Services/MonitorService.ts +11 -9
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +376 -5
- package/Server/Services/NetworkDeviceDiagnosticService.ts +417 -0
- package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +147 -83
- package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +218 -97
- package/Server/Services/NetworkDeviceService.ts +39 -2
- package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +151 -80
- package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +222 -97
- package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +154 -83
- package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +225 -100
- package/Server/Services/PodmanHostLabelRuleEngineService.ts +171 -110
- package/Server/Services/PodmanHostOwnerRuleEngineService.ts +235 -115
- package/Server/Services/ProjectService.ts +111 -10
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +174 -110
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +239 -116
- package/Server/Services/RumApplicationLabelRuleEngineService.ts +137 -73
- package/Server/Services/RumApplicationOwnerRuleEngineService.ts +200 -83
- package/Server/Services/RunbookLabelRuleEngineService.ts +146 -84
- package/Server/Services/RunbookOwnerRuleEngineService.ts +216 -95
- package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +324 -230
- package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +613 -428
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +24 -0
- package/Server/Services/ScheduledMaintenanceService.ts +43 -14
- package/Server/Services/SecurityEventConnectionService.ts +56 -4
- package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +143 -74
- package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +206 -85
- package/Server/Services/ServiceLabelRuleEngineService.ts +172 -110
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +1057 -18
- package/Server/Services/ServiceLevelObjectiveFeedService.ts +108 -0
- package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +793 -97
- package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +1069 -0
- package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +240 -1
- package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +257 -1
- package/Server/Services/ServiceLevelObjectiveService.ts +1356 -56
- package/Server/Services/ServiceOwnerRuleEngineService.ts +238 -116
- package/Server/Services/StatusPageAnnouncementService.ts +13 -0
- package/Server/Services/StatusPageLabelRuleEngineService.ts +146 -85
- package/Server/Services/StatusPageOwnerRuleEngineService.ts +210 -99
- package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +28 -232
- package/Server/Services/StatusPageSubscriberService.ts +6 -0
- package/Server/Services/TelemetryUsageBillingService.ts +38 -7
- package/Server/Services/ThreatIntelFeedService.ts +1 -1
- package/Server/Services/VMwareVCenterLabelRuleEngineService.ts +173 -110
- package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +238 -116
- package/Server/Services/WorkflowLabelRuleEngineService.ts +145 -84
- package/Server/Services/WorkflowOwnerRuleEngineService.ts +215 -95
- package/Server/Types/Database/UpdateByID.ts +3 -0
- package/Server/Types/Database/UpdateOneBy.ts +7 -0
- package/Server/Utils/AI/AlertAIContextBuilder.ts +19 -0
- package/Server/Utils/AI/IncidentAIContextBuilder.ts +39 -0
- package/Server/Utils/AI/Toolbox/AlertTools.ts +37 -1
- package/Server/Utils/AI/Toolbox/IncidentTools.ts +22 -1
- package/Server/Utils/AI/Toolbox/SloTools.ts +416 -51
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +151 -13
- package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +17 -4
- package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +155 -8
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +16 -0
- package/Server/Utils/Database/RelationValueUtil.ts +106 -0
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +6 -1
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +22 -27
- package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +3 -1
- package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +50 -20
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +13 -1
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +6 -11
- package/Server/Utils/Rules/MonitorRulePatternValidator.ts +51 -0
- package/Server/Utils/Rules/OwnerRuleAssignment.ts +110 -0
- package/Server/Utils/Rules/RuleRun/RuleApplication.ts +81 -0
- package/Server/Utils/Rules/RuleRun/RuleRunPermission.ts +188 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +803 -0
- package/Server/Utils/Rules/RuleRun/RuleRunner.ts +341 -0
- package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +3 -2
- package/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.ts +6 -4
- package/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.ts +263 -16
- package/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.ts +2101 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.ts +194 -14
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.ts +1 -2
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.ts +38 -7
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.ts +2 -0
- package/Server/Utils/SecurityEvent/Connectors/Types.ts +242 -2
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +1 -1
- package/Server/Utils/SecurityEvent/SecurityEventDedupe.ts +3 -3
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +2 -2
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +217 -56
- package/Server/Utils/Slo/SloFeedUtil.ts +200 -0
- package/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.ts +173 -0
- package/Server/Utils/Slo/SloMetricUtil.ts +327 -0
- package/Server/Utils/Slo/SloOwnerReferenceValidator.ts +208 -0
- package/Server/Utils/Slo/SloRecordReferenceValidator.ts +169 -0
- package/Server/Utils/StatusPage/MonitorRulePatternValidator.ts +6 -43
- package/Server/Utils/StatusPageResource.ts +50 -5
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +664 -15
- package/Tests/App/Dashboard/AddWidgetModal.test.tsx +4 -1
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +307 -0
- package/Tests/App/Dashboard/ArchiveResourceCard.test.tsx +289 -0
- package/Tests/App/Dashboard/AuditLogsTable.test.tsx +598 -0
- package/Tests/App/Dashboard/BillingDefaultPaymentMethod.test.tsx +1046 -0
- package/Tests/App/Dashboard/BillingPaidUsageFlow.test.tsx +3 -0
- package/Tests/App/Dashboard/BillingPaymentMethodForm.test.tsx +201 -7
- package/Tests/App/Dashboard/BooleanSeriesCriteriaFilterText.test.ts +82 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +16 -1
- package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +116 -8
- package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +168 -1
- package/Tests/App/Dashboard/ConnectionTestModal.test.tsx +1 -1
- package/Tests/App/Dashboard/ConnectorTestReportView.test.tsx +20 -3
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +1095 -1
- package/Tests/App/Dashboard/CorrelateFilterChips.test.tsx +910 -0
- package/Tests/App/Dashboard/CorrelateGraph.test.tsx +3747 -25
- package/Tests/App/Dashboard/CorrelateGraphHelpers.test.ts +1085 -0
- package/Tests/App/Dashboard/CorrelateInspector.test.tsx +1534 -0
- package/Tests/App/Dashboard/CorrelateNodeCard.test.tsx +965 -0
- package/Tests/App/Dashboard/CorrelateResultSummary.test.tsx +1525 -0
- package/Tests/App/Dashboard/CorrelationGraph.test.ts +1030 -0
- package/Tests/App/Dashboard/CorrelationGraphLayout.test.ts +526 -0
- package/Tests/App/Dashboard/DeviceDiagnostics.test.tsx +787 -0
- package/Tests/App/Dashboard/DeviceLatencyTrend.test.tsx +278 -0
- package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +279 -0
- package/Tests/App/Dashboard/DiscoveryScanEditForm.test.tsx +87 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +443 -8
- package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +340 -0
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +98 -2
- package/Tests/App/Dashboard/ExceptionSegmentedControl.test.tsx +1020 -0
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +268 -47
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1114 -76
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +124 -2
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +279 -176
- package/Tests/App/Dashboard/InvestigationRunDetails.test.tsx +1166 -0
- package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +437 -0
- package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +65 -0
- package/Tests/App/Dashboard/NetworkTopologyLiveView.test.tsx +5 -0
- package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +74 -0
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +125 -5
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +1764 -0
- package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +1000 -64
- package/Tests/App/Dashboard/SecurityEventConnectionsEmptyState.test.tsx +448 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +739 -189
- package/Tests/App/Dashboard/SecurityEventSeverityPill.test.tsx +233 -0
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +282 -0
- package/Tests/App/Dashboard/SloActiveBurnEventsCard.test.tsx +538 -0
- package/Tests/App/Dashboard/SloBulkActionsArchive.test.tsx +252 -0
- package/Tests/App/Dashboard/SloDashboardTemplateWidgets.test.tsx +322 -518
- package/Tests/App/Dashboard/SloElement.test.tsx +194 -0
- package/Tests/App/Dashboard/SloFeed.test.tsx +289 -0
- package/Tests/App/Dashboard/SloHistoryCharts.test.tsx +471 -0
- package/Tests/App/Dashboard/SloHistorySeries.test.tsx +607 -0
- package/Tests/App/Dashboard/SloListWidget.test.tsx +783 -0
- package/Tests/App/Dashboard/SloMetricsPage.test.tsx +346 -0
- package/Tests/App/Dashboard/SloMonitorsPage.test.tsx +661 -0
- package/Tests/App/Dashboard/SloMonitorsSummaryCard.test.tsx +489 -0
- package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +437 -0
- package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +305 -0
- package/Tests/App/Dashboard/SloOverviewData.test.tsx +563 -0
- package/Tests/App/Dashboard/SloOverviewHero.test.tsx +311 -0
- package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +426 -0
- package/Tests/App/Dashboard/SloOverviewSidebarCards.test.tsx +493 -0
- package/Tests/App/Dashboard/SloSettings.test.tsx +633 -0
- package/Tests/App/Dashboard/SloStatusSummaryCards.test.tsx +403 -0
- package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +373 -0
- package/Tests/App/Dashboard/SloWidgetVariableBinding.test.tsx +689 -0
- package/Tests/App/Dashboard/TopologyConnectivitySection.test.tsx +206 -0
- package/Tests/App/Dashboard/TracesEntityNames.test.tsx +47 -15
- package/Tests/App/Dashboard/UseBulkShortenDeviceNames.test.tsx +1312 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +9 -1
- package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +14 -16
- package/Tests/Models/DatabaseModels/AuditLogModelConfiguration.test.ts +442 -0
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +9 -10
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +48 -1
- package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +835 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +3 -2
- package/Tests/Models/DiscoveryScanNetbiosLookupColumn.test.ts +328 -0
- package/Tests/Models/DiscoveryScanShortDeviceNamesColumn.test.ts +335 -0
- package/Tests/Models/NetworkDeviceDiagnosticContract.test.ts +194 -0
- package/Tests/Models/NetworkDeviceDnsNameColumn.test.ts +321 -0
- package/Tests/Models/ProjectDataResidencyColumn.test.ts +154 -0
- package/Tests/Models/SecurityDomainAccessControl.test.ts +181 -50
- package/Tests/Server/API/BaseAPI.test.ts +6 -0
- package/Tests/Server/API/BaseAPIUpdateMiscDataProps.test.ts +217 -0
- package/Tests/Server/API/BillingInvoiceAPI.test.ts +7 -0
- package/Tests/Server/API/BillingInvoiceAPIPaymentStates.test.ts +990 -0
- package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +498 -0
- package/Tests/Server/API/DashboardPublicSloAPI.test.ts +405 -0
- package/Tests/Server/API/SecurityEventConnectionAPI.test.ts +901 -7
- package/Tests/Server/API/SessionReplayAPI.test.ts +116 -0
- package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +857 -0
- package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +1084 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +33 -3
- package/Tests/Server/Infrastructure/Postgres/AddDataResidencyToProjectMigration.test.ts +202 -0
- package/Tests/Server/Infrastructure/Postgres/AddNetbiosLookupToNetworkDeviceDiscoveryScanMigration.test.ts +330 -0
- package/Tests/Server/Infrastructure/Postgres/AddNetworkDeviceDnsNameAndShortDeviceNamesMigration.test.ts +340 -0
- package/Tests/Server/Infrastructure/Postgres/BackfillSloMonitorRulesAndAffectedResourcesMigration.test.ts +343 -0
- package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +801 -0
- package/Tests/Server/Services/AddSubscriberUpdateNotificationStatusMigration.test.ts +307 -0
- package/Tests/Server/Services/AuditLogService.test.ts +1124 -0
- package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +200 -1
- package/Tests/Server/Services/BillingInvoiceServiceMutexRelease.test.ts +254 -0
- package/Tests/Server/Services/BillingService.test.ts +70 -0
- package/Tests/Server/Services/BillingServicePayInvoiceStates.test.ts +723 -0
- package/Tests/Server/Services/BillingServicePaymentMethodReads.test.ts +14 -2
- package/Tests/Server/Services/BillingServiceSubscriptionPaymentMethodSync.test.ts +1634 -0
- package/Tests/Server/Services/DatabaseServiceAuditRelationDiff.test.ts +492 -0
- package/Tests/Server/Services/DatabaseServicePasswordFieldSecrets.test.ts +629 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +431 -0
- package/Tests/Server/Services/IncidentAlertSloReferenceGuard.test.ts +358 -0
- package/Tests/Server/Services/MonitorProbeServicePastDueMonitoring.test.ts +362 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +1460 -1
- package/Tests/Server/Services/NetworkDeviceDiagnosticService.test.ts +962 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +106 -0
- package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +10 -1
- package/Tests/Server/Services/NetworkDeviceServicePastDueMonitoring.test.ts +335 -0
- package/Tests/Server/Services/NetworkDeviceSiteRuleDnsName.test.ts +568 -0
- package/Tests/Server/Services/ProjectDataResidencyPostgres.test.ts +344 -0
- package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +187 -0
- package/Tests/Server/Services/ProjectServiceDataResidency.test.ts +369 -0
- package/Tests/Server/Services/ProjectServiceDataResidencySelfHosted.test.ts +176 -0
- package/Tests/Server/Services/ProjectServicePastDueMonitoring.test.ts +289 -0
- package/Tests/Server/Services/ResourceFeedServices.test.ts +24 -8
- package/Tests/Server/Services/RuleRun/IncidentAlertMaintenanceRuleEnginesRun.test.ts +1396 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupARun.test.ts +917 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +1262 -0
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupARun.test.ts +902 -0
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +1163 -0
- package/Tests/Server/Services/RuleRun/PrivacyRuleEnginesRun.test.ts +843 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +465 -0
- package/Tests/Server/Services/SecurityEventConnectionService.test.ts +525 -4
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +77 -23
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleFeedWrites.test.ts +777 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleOptions.test.ts +1399 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +67 -74
- package/Tests/Server/Services/ServiceLevelObjectiveChildRowTenancy.test.ts +906 -0
- package/Tests/Server/Services/ServiceLevelObjectiveDeleteTenancy.test.ts +1029 -0
- package/Tests/Server/Services/ServiceLevelObjectiveFeedService.test.ts +313 -0
- package/Tests/Server/Services/ServiceLevelObjectiveFeedWrites.test.ts +1214 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMarkdownLink.test.ts +289 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +1455 -430
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleLegacyLabelAdoption.test.ts +634 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +1193 -0
- package/Tests/Server/Services/{SloMonitorLabelRuleHooks.test.ts → ServiceLevelObjectiveMonitorRuleTriggers.test.ts} +135 -41
- package/Tests/Server/Services/ServiceLevelObjectiveOwnerFeedWrites.test.ts +671 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +180 -85
- package/Tests/Server/Services/ServiceLevelObjectiveServiceArchive.test.ts +537 -0
- package/Tests/Server/Services/ServiceLevelObjectiveServiceLegacyMonitorLabelWrite.test.ts +870 -0
- package/Tests/Server/Services/ServiceLevelObjectiveServiceMonitorRuleGuard.test.ts +343 -0
- package/Tests/Server/Services/ServiceLevelObjectiveServiceReEvaluation.test.ts +246 -0
- package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +501 -0
- package/Tests/Server/Services/SloAffectedResourceLinkContract.test.ts +86 -0
- package/Tests/Server/Services/SloAffectedResourceMetricAttributes.test.ts +547 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +10 -4
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +7 -2
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +174 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateServiceVariables.test.ts +40 -0
- package/Tests/Server/Services/SubscriberUpdateNotificationHooks.test.ts +541 -0
- package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +288 -0
- package/Tests/Server/TestingUtils/PastDueMonitoringClaimSql.ts +177 -0
- package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +51 -10
- package/Tests/Server/TestingUtils/__mocks__/Stripe.mock.ts +16 -1
- package/Tests/Server/Types/Database/Permissions/ProjectDataResidencyColumn.test.ts +386 -0
- package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +26 -36
- package/Tests/Server/Utils/AI/SloAffectedResourceAIContext.test.ts +445 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +423 -1
- package/Tests/Server/Utils/AI/SloToolsArchive.test.ts +294 -0
- package/Tests/Server/Utils/AI/SloToolsRuleReadPermissions.test.ts +297 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +255 -10
- package/Tests/Server/Utils/Dashboard/SloTemplatePublicDashboard.test.ts +404 -750
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +45 -0
- package/Tests/Server/Utils/Database/RelationValueUtil.test.ts +157 -0
- package/Tests/Server/Utils/Monitor/Criteria/BooleanSeriesEvaluateOverTime.test.ts +260 -0
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +181 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +147 -30
- package/Tests/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.test.ts +17 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +136 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidatorLoadOrder.test.ts +472 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +48 -2
- package/Tests/Server/Utils/Monitor/SloTemplateMetricEmitterContract.test.ts +435 -475
- package/Tests/Server/Utils/Rules/MonitorRulePatternValidator.test.ts +77 -0
- package/Tests/Server/Utils/Rules/OwnerRuleAssignment.test.ts +177 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +365 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunRegistry.test.ts +173 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunner.test.ts +675 -0
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +8 -8
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorFetchSummary.test.ts +261 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.test.ts +68 -13
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsAuth.test.ts → Connectors/GoogleSecOps/GoogleSecOpsAuth.test.ts} +5 -5
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsClient.test.ts → Connectors/GoogleSecOps/GoogleSecOpsClient.test.ts} +4 -4
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.test.ts +483 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorCuratedAndLateAlerts.test.ts +676 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorFetchEvents.test.ts +1994 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorFixtures.ts +332 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorHttpIntegration.test.ts +680 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorRequestContract.test.ts +1206 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorTestConnection.test.ts +1136 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsCuratedRuleCounts.test.ts +407 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsErrorHandling.test.ts → Connectors/GoogleSecOps/GoogleSecOpsErrorHandling.test.ts} +5 -5
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingAdaptiveCatchUp.test.ts +730 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsClickhouseIntegration.test.ts → Connectors/GoogleSecOps/GoogleSecOpsPollingClickhouseIntegration.test.ts} +130 -35
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingFailureTaxonomy.test.ts +772 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingFixtures.ts +648 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsHttpIntegration.test.ts → Connectors/GoogleSecOps/GoogleSecOpsPollingHttpIntegration.test.ts} +230 -225
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingIntegration.test.ts +1390 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingLoop.test.ts +981 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingNothingImportedRegression.test.ts +290 -0
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsRequestContract.test.ts → Connectors/GoogleSecOps/GoogleSecOpsRequestContract.test.ts} +2 -2
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsResponseParsing.test.ts → Connectors/GoogleSecOps/GoogleSecOpsResponseParsing.test.ts} +5 -5
- package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsSearchDetections.test.ts → Connectors/GoogleSecOps/GoogleSecOpsSearchDetections.test.ts} +38 -5
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsTesterIntegration.test.ts +421 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.test.ts +1445 -3
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.test.ts +14 -4
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.test.ts +313 -4
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +352 -0
- package/Tests/Server/Utils/Slo/SloFeedUtil.test.ts +326 -0
- package/Tests/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.test.ts +260 -0
- package/Tests/Server/Utils/Slo/SloMetricUtil.test.ts +592 -0
- package/Tests/Server/Utils/Slo/SloRecordReferenceValidator.test.ts +311 -0
- package/Tests/Server/Utils/StatusPageResource.test.ts +91 -3
- package/Tests/Types/Billing/SubscriptionStatus.test.ts +176 -0
- package/Tests/Types/Billing/SubscriptionStatusPastDueMonitoring.test.ts +187 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +53 -7
- package/Tests/Types/Dashboard/SloDashboardTemplate.test.ts +816 -792
- package/Tests/Types/Monitor/CriteriaFilter.test.ts +216 -24
- package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +14 -1
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +14 -1
- package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +14 -1
- package/Tests/Types/Monitor/MonitorStepRetriesParsing.test.ts +201 -0
- package/Tests/Types/Rules/RuleRun.test.ts +315 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +60 -0
- package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +29 -4
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +217 -0
- package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +200 -0
- package/Tests/UI/Components/ActiveFilterChipsLockedFilters.test.tsx +141 -87
- package/Tests/UI/Components/AlertBanner.test.tsx +319 -0
- package/Tests/UI/Components/BulkArchiveActionsCopy.test.tsx +310 -0
- package/Tests/UI/Components/Detail/DetailIdIsUnique.test.tsx +87 -0
- package/Tests/UI/Components/Dropdown/DropdownClearable.test.tsx +393 -0
- package/Tests/UI/Components/Dropdown/DropdownMultiSelectChipAccessibleName.test.tsx +64 -0
- package/Tests/UI/Components/EmptyState/EmptyState.test.tsx +335 -4
- package/Tests/UI/Components/EmptyState/EmptyStateGuideLinks.test.tsx +337 -0
- package/Tests/UI/Components/Forms/ModelFormJsonColumns.test.tsx +21 -20
- package/Tests/UI/Components/LabelRuleImportExport.test.tsx +15 -2
- package/Tests/UI/Components/LockedFilterChip.test.tsx +281 -144
- package/Tests/UI/Components/MoreMenu.test.tsx +133 -0
- package/Tests/UI/Components/MoreMenuMotion.test.tsx +84 -3
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/RuleRun/RuleDetailFields.test.tsx +336 -0
- package/Tests/UI/Components/RuleRun/RuleTable.test.tsx +304 -0
- package/Tests/UI/Components/RuleRun/RunRuleNowModal.test.tsx +231 -0
- package/Tests/UI/Components/RuleRun/RunRulesBulkAction.test.ts +213 -0
- package/Tests/UI/Components/TelemetryActiveFilterChipsLockedFilters.test.tsx +124 -61
- package/Tests/UI/Rum/ReplayEngine.test.ts +154 -0
- package/Tests/UI/Rum/ReplayHeader.test.tsx +234 -123
- package/Tests/UI/Rum/ReplayPinControl.test.tsx +122 -0
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +245 -0
- package/Tests/UI/Rum/ReplayRail.test.tsx +294 -0
- package/Tests/UI/Rum/ReplayScrubber.test.tsx +213 -1
- package/Tests/UI/Rum/ReplayStage.test.tsx +565 -172
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +260 -3
- package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +1391 -0
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +222 -0
- package/Tests/UI/Utils/DashboardStackingLayers.test.ts +8 -1
- package/Tests/UI/Utils/RuleRunClient.test.ts +303 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +1 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentDefaults.test.ts +2 -0
- package/Tests/Utils/Dashboard/Components/DashboardSloListComponent.test.ts +206 -0
- package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +36 -2
- package/Tests/Utils/Dashboard/SloTemplateVariableScoping.test.ts +409 -588
- package/Tests/Utils/Dashboard/SloWidgetSource.test.ts +351 -0
- package/Tests/Utils/Markdown/MarkdownEscape.test.ts +361 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +1425 -118
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +188 -3
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +661 -13
- package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +349 -0
- package/Tests/Utils/NetworkDiscovery/RunImportedDeviceNaming.test.ts +656 -0
- package/Tests/Utils/NetworkDiscovery/ShortDeviceNamePlanner.test.ts +1020 -0
- package/Tests/Utils/NetworkDiscovery/ShortHostnameUtil.test.ts +619 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +317 -0
- package/Tests/Utils/Project/DataResidency.test.ts +198 -0
- package/Tests/Utils/Rules/RuleRunSummary.test.ts +394 -0
- package/Tests/Utils/Slo/SloAffectedResourceMarkdown.test.ts +302 -0
- package/Tests/Utils/Slo/SloBurnRateTemplate.test.ts +468 -0
- package/Tests/Utils/Slo/SloEvaluation.test.ts +20 -4
- package/Tests/Utils/Slo/SloFeedMarkdown.test.ts +1185 -0
- package/Tests/Utils/Slo/SloHealth.test.ts +262 -0
- package/Tests/Utils/Slo/SloHistoryMetricName.test.ts +102 -0
- package/Tests/Utils/Slo/SloListWidgetFormat.test.ts +522 -0
- package/Tests/Utils/Slo/SloMetricType.test.ts +355 -0
- package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +387 -0
- package/Tests/Utils/Slo/SloMonitorStatusSummary.test.ts +210 -0
- package/Tests/Utils/Slo/SloOverviewText.test.ts +226 -0
- package/Tests/Utils/Slo/SloProjection.test.ts +1039 -0
- package/Tests/Utils/Slo/SloWidgetFormat.test.ts +47 -0
- package/Tests/Utils/Telemetry/LockedFilterSearch.test.ts +1 -80
- package/Types/BaseDatabase/EnableAuditLogOn.ts +41 -0
- package/Types/Billing/SubscriptionStatus.ts +39 -4
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +5 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +10 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloListComponent.ts +29 -0
- package/Types/Dashboard/DashboardTemplates.ts +290 -297
- package/Types/Database/EnableAuditLog.ts +23 -1
- package/Types/Email/EmailTemplateType.ts +4 -0
- package/Types/Monitor/CriteriaFilter.ts +55 -8
- package/Types/Monitor/MonitorStep.ts +5 -2
- package/Types/Monitor/MonitorStepDnsMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepDnssecMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepDomainMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepExternalStatusPageMonitor.ts +3 -1
- package/Types/Monitor/MonitorStepRetries.ts +59 -0
- package/Types/Monitor/MonitorStepSnmpMonitor.ts +9 -2
- package/Types/NetworkDevice/NetworkDeviceDiagnosticResult.ts +104 -0
- package/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.ts +47 -0
- package/Types/NetworkDevice/NetworkDeviceDiagnosticType.ts +47 -0
- package/Types/NetworkDevice/NetworkDevicePingMetricNames.ts +20 -0
- package/Types/Permission.ts +127 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +5 -0
- package/Types/Rules/RuleRun.ts +518 -0
- package/Types/Rum/SessionReplayApi.ts +18 -0
- package/Types/SecurityEvent/Connectors/ConnectorDiagnostics.ts +6 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.ts +30 -4
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +108 -1
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.ts +6 -2
- package/Types/ServiceLevelObjective/SloHistoryMetricName.ts +25 -0
- package/Types/ServiceLevelObjective/SloMetricType.ts +49 -0
- package/Types/StatusPage/StatusPageSubscriberNotificationEventType.ts +4 -0
- package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +331 -0
- package/Types/StatusPage/SubscriberNotificationTrigger.ts +12 -0
- package/Types/StatusPage/SubscriberUpdateNotification.ts +89 -0
- package/Types/Telemetry/LockedFilterDetail.ts +7 -28
- package/Types/Telemetry/ServiceType.ts +7 -0
- package/Typings/Index.d.ts +53 -3
- package/UI/Components/AlertBanner/AlertBanner.tsx +85 -27
- package/UI/Components/BulkUpdate/BulkArchiveActions.tsx +21 -2
- package/UI/Components/Detail/Detail.tsx +9 -2
- package/UI/Components/Dropdown/Dropdown.tsx +64 -1
- package/UI/Components/EmptyState/EmptyState.tsx +27 -3
- package/UI/Components/EmptyState/EmptyStateGuideLinks.tsx +124 -0
- package/UI/Components/Forms/ModelForm.tsx +6 -5
- package/UI/Components/LabelRule/LabelRuleTable.tsx +8 -2
- package/UI/Components/LogsViewer/LogsViewer.tsx +2 -6
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +2 -13
- package/UI/Components/LogsViewer/types.ts +2 -2
- package/UI/Components/MoreMenu/MoreMenu.tsx +14 -3
- package/UI/Components/RuleRun/RuleDetailFields.tsx +359 -0
- package/UI/Components/RuleRun/RuleTable.tsx +183 -0
- package/UI/Components/RuleRun/RuleView.tsx +170 -0
- package/UI/Components/RuleRun/RunRuleNowModal.tsx +147 -0
- package/UI/Components/RuleRun/RunRulesBulkAction.ts +103 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +2 -6
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +38 -104
- package/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.tsx +2 -18
- package/UI/Components/TelemetryViewer/types.ts +2 -2
- package/UI/Utils/Rules/RuleRunClient.ts +178 -0
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +8 -0
- package/Utils/Dashboard/Components/DashboardSloComponent.ts +19 -2
- package/Utils/Dashboard/Components/DashboardSloListComponent.ts +126 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/Dashboard/SloWidgetSource.ts +188 -0
- package/Utils/Markdown/MarkdownEscape.ts +63 -0
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +161 -36
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +25 -0
- package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +146 -0
- package/Utils/NetworkDiscovery/RunImportedDeviceNaming.ts +390 -0
- package/Utils/NetworkDiscovery/ShortDeviceNamePlanner.ts +291 -0
- package/Utils/NetworkDiscovery/ShortHostnameUtil.ts +91 -0
- package/Utils/NetworkSite/CidrMatchUtil.ts +37 -12
- package/Utils/Project/DataResidency.ts +63 -0
- package/Utils/Rules/RuleRunSummary.ts +323 -0
- package/Utils/Slo/SloAffectedResourceMarkdown.ts +123 -0
- package/Utils/Slo/SloBurnRateTemplate.ts +373 -0
- package/Utils/Slo/SloFeedMarkdown.ts +1507 -0
- package/Utils/Slo/SloHealth.ts +96 -9
- package/Utils/Slo/SloListWidgetFormat.ts +370 -0
- package/Utils/Slo/SloMetricType.ts +237 -0
- package/Utils/Slo/SloMonitorRuleCriteria.ts +364 -0
- package/Utils/Slo/SloMonitorStatusSummary.ts +210 -0
- package/Utils/Slo/SloOverviewText.ts +265 -0
- package/Utils/Slo/SloProjection.ts +967 -0
- package/Utils/Slo/SloWidgetFormat.ts +12 -2
- package/Utils/Telemetry/LockedFilterSearch.ts +3 -49
- package/build/dist/Models/AnalyticsModels/AuditLog.js +70 -1
- package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/SecurityEvent.js +4 -4
- package/build/dist/Models/DatabaseModels/Alert.js +60 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +64 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +75 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +75 -0
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +6 -4
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +68 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiagnostic.js +772 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiagnostic.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +140 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +42 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +75 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js +11 -11
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +192 -10
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +798 -96
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +596 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +590 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +16 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +16 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +75 -0
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +1 -1
- package/build/dist/Server/API/BaseAPI.js +14 -0
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/BillingInvoiceAPI.js +233 -19
- package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
- package/build/dist/Server/API/BillingPaymentMethodAPI.js +86 -5
- package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +72 -2
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/SecurityEventConnectionAPI.js +102 -10
- package/build/dist/Server/API/SecurityEventConnectionAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +236 -154
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.js +21 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.js +207 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.js +72 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.js +46 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +112 -56
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +167 -68
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +87 -26
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js +270 -203
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +498 -354
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +97 -34
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +91 -8
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AuditLogService.js +408 -44
- package/build/dist/Server/Services/AuditLogService.js.map +1 -1
- package/build/dist/Server/Services/BillingInvoiceService.js +94 -85
- package/build/dist/Server/Services/BillingInvoiceService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +406 -14
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +135 -86
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +189 -100
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +125 -18
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +145 -91
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +191 -101
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js +190 -102
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +112 -56
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +220 -63
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +87 -26
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +258 -192
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +519 -376
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +95 -32
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +90 -5
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +113 -65
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +6 -4
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +145 -91
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +191 -101
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +20 -25
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +123 -77
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +167 -82
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +18 -2
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +11 -9
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +287 -5
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiagnosticService.js +333 -0
- package/build/dist/Server/Services/NetworkDeviceDiagnosticService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +36 -2
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +117 -64
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +173 -83
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +116 -65
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +82 -10
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +111 -63
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +161 -77
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +280 -209
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +521 -376
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +24 -0
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +24 -8
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/SecurityEventConnectionService.js +43 -3
- package/build/dist/Server/Services/SecurityEventConnectionService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +115 -62
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +163 -77
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +769 -18
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveFeedService.js +96 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveFeedService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +614 -87
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +844 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +207 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +221 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +997 -50
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +191 -102
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageAnnouncementService.js +12 -0
- package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +118 -70
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +158 -76
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +19 -215
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +6 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +27 -5
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/ThreatIntelFeedService.js +1 -1
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js +141 -92
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +189 -101
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +117 -69
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +171 -83
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js +17 -0
- package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js +31 -0
- package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +24 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +21 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +337 -53
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +108 -15
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +2 -2
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +115 -6
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +13 -0
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/Database/RelationValueUtil.js +82 -0
- package/build/dist/Server/Utils/Database/RelationValueUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +10 -6
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +17 -21
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +5 -4
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +50 -10
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +13 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +6 -10
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Rules/MonitorRulePatternValidator.js +34 -0
- package/build/dist/Server/Utils/Rules/MonitorRulePatternValidator.js.map +1 -0
- package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +69 -0
- package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleApplication.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleApplication.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunPermission.js +128 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunPermission.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +746 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunner.js +221 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunner.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +3 -2
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js +6 -4
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.js +174 -14
- package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.js +1417 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js +138 -18
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js +1 -2
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js +23 -18
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js +2 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js +95 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +1 -1
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js +3 -3
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +2 -2
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +118 -40
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/Slo/SloFeedUtil.js +150 -0
- package/build/dist/Server/Utils/Slo/SloFeedUtil.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.js +136 -0
- package/build/dist/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloMetricUtil.js +269 -0
- package/build/dist/Server/Utils/Slo/SloMetricUtil.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloOwnerReferenceValidator.js +134 -0
- package/build/dist/Server/Utils/Slo/SloOwnerReferenceValidator.js.map +1 -0
- package/build/dist/Server/Utils/Slo/SloRecordReferenceValidator.js +137 -0
- package/build/dist/Server/Utils/Slo/SloRecordReferenceValidator.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js +6 -26
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageResource.js +31 -5
- package/build/dist/Server/Utils/StatusPageResource.js.map +1 -1
- package/build/dist/Types/Billing/SubscriptionStatus.js +37 -3
- package/build/dist/Types/Billing/SubscriptionStatus.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +5 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +275 -286
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Database/EnableAuditLog.js +19 -1
- package/build/dist/Types/Database/EnableAuditLog.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +4 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +45 -6
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +2 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDnsMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepDnsMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepRetries.js +47 -0
- package/build/dist/Types/Monitor/MonitorStepRetries.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js +3 -1
- package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js.map +1 -1
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticResult.js +29 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticResult.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.js +37 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticType.js +42 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticType.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDevicePingMetricNames.js +20 -0
- package/build/dist/Types/NetworkDevice/NetworkDevicePingMetricNames.js.map +1 -0
- package/build/dist/Types/Permission.js +114 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +5 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +267 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js +16 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +65 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js +6 -2
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js.map +1 -1
- package/build/dist/Types/ServiceLevelObjective/SloHistoryMetricName.js +26 -0
- package/build/dist/Types/ServiceLevelObjective/SloHistoryMetricName.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloMetricType.js +45 -0
- package/build/dist/Types/ServiceLevelObjective/SloMetricType.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js +4 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js.map +1 -1
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +295 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTrigger.js +13 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTrigger.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +67 -0
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js.map +1 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js +7 -7
- package/build/dist/Types/Telemetry/ServiceType.js +7 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/AlertBanner/AlertBanner.js +48 -19
- package/build/dist/UI/Components/AlertBanner/AlertBanner.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js +10 -2
- package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +12 -3
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +33 -5
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyState.js +3 -3
- package/build/dist/UI/Components/EmptyState/EmptyState.js.map +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js +47 -0
- package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js.map +1 -0
- package/build/dist/UI/Components/Forms/ModelForm.js +6 -5
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js +6 -2
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +0 -2
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +3 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/RuleRun/RuleDetailFields.js +226 -0
- package/build/dist/UI/Components/RuleRun/RuleDetailFields.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RuleTable.js +97 -0
- package/build/dist/UI/Components/RuleRun/RuleTable.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RuleView.js +83 -0
- package/build/dist/UI/Components/RuleRun/RuleView.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RunRuleNowModal.js +74 -0
- package/build/dist/UI/Components/RuleRun/RunRuleNowModal.js.map +1 -0
- package/build/dist/UI/Components/RuleRun/RunRulesBulkAction.js +78 -0
- package/build/dist/UI/Components/RuleRun/RunRulesBulkAction.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +24 -50
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js +0 -4
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Utils/Rules/RuleRunClient.js +98 -0
- package/build/dist/UI/Utils/Rules/RuleRunClient.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +8 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +16 -2
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardSloListComponent.js +94 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/Dashboard/SloWidgetSource.js +125 -0
- package/build/dist/Utils/Dashboard/SloWidgetSource.js.map +1 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js +49 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +112 -34
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +22 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +129 -0
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/RunImportedDeviceNaming.js +255 -0
- package/build/dist/Utils/NetworkDiscovery/RunImportedDeviceNaming.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ShortDeviceNamePlanner.js +184 -0
- package/build/dist/Utils/NetworkDiscovery/ShortDeviceNamePlanner.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ShortHostnameUtil.js +79 -0
- package/build/dist/Utils/NetworkDiscovery/ShortHostnameUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +21 -12
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -1
- package/build/dist/Utils/Project/DataResidency.js +51 -0
- package/build/dist/Utils/Project/DataResidency.js.map +1 -0
- package/build/dist/Utils/Rules/RuleRunSummary.js +197 -0
- package/build/dist/Utils/Rules/RuleRunSummary.js.map +1 -0
- package/build/dist/Utils/Slo/SloAffectedResourceMarkdown.js +51 -0
- package/build/dist/Utils/Slo/SloAffectedResourceMarkdown.js.map +1 -0
- package/build/dist/Utils/Slo/SloBurnRateTemplate.js +228 -0
- package/build/dist/Utils/Slo/SloBurnRateTemplate.js.map +1 -0
- package/build/dist/Utils/Slo/SloFeedMarkdown.js +934 -0
- package/build/dist/Utils/Slo/SloFeedMarkdown.js.map +1 -0
- package/build/dist/Utils/Slo/SloHealth.js +75 -9
- package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
- package/build/dist/Utils/Slo/SloListWidgetFormat.js +217 -0
- package/build/dist/Utils/Slo/SloListWidgetFormat.js.map +1 -0
- package/build/dist/Utils/Slo/SloMetricType.js +212 -0
- package/build/dist/Utils/Slo/SloMetricType.js.map +1 -0
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +216 -0
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -0
- package/build/dist/Utils/Slo/SloMonitorStatusSummary.js +129 -0
- package/build/dist/Utils/Slo/SloMonitorStatusSummary.js.map +1 -0
- package/build/dist/Utils/Slo/SloOverviewText.js +110 -0
- package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -0
- package/build/dist/Utils/Slo/SloProjection.js +448 -0
- package/build/dist/Utils/Slo/SloProjection.js.map +1 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js +4 -2
- package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -1
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js +1 -26
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js.map +1 -1
- package/package.json +1 -1
- package/Models/DatabaseModels/GoogleSecOpsConnection.ts +0 -447
- package/Models/DatabaseModels/GoogleSecOpsConnectionRun.ts +0 -263
- package/Server/API/GoogleSecOpsConnectionAPI.ts +0 -320
- package/Server/Services/GoogleSecOpsConnectionRunService.ts +0 -10
- package/Server/Services/GoogleSecOpsConnectionService.ts +0 -116
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.ts +0 -777
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +0 -1373
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +0 -512
- package/Tests/App/Dashboard/GoogleSecOpsConnectionForm.test.tsx +0 -838
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +0 -441
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +0 -1001
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +0 -657
- package/Tests/Server/Services/GoogleSecOpsDiagnosticsModel.test.ts +0 -153
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.test.ts +0 -784
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +0 -823
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +0 -918
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +0 -738
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +0 -874
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +0 -1297
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsThreePassPoller.test.ts +0 -1577
- package/Tests/UI/Components/LockedFilterActions.test.tsx +0 -396
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +0 -111
- package/UI/Components/TelemetryViewer/components/LockedFilterActions.tsx +0 -205
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +0 -478
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +0 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js +0 -287
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js.map +0 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +0 -231
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +0 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js +0 -9
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js.map +0 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +0 -70
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js +0 -537
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +0 -1034
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +0 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +0 -410
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +0 -1
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js +0 -2
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js.map +0 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js +0 -88
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js.map +0 -1
|
@@ -1,1297 +0,0 @@
|
|
|
1
|
-
import { generateKeyPairSync } from "crypto";
|
|
2
|
-
import GoogleSecOpsConnection from "../../../../Models/DatabaseModels/GoogleSecOpsConnection";
|
|
3
|
-
import GoogleSecOpsConnectionService from "../../../../Server/Services/GoogleSecOpsConnectionService";
|
|
4
|
-
import OTelIngestService, {
|
|
5
|
-
TelemetryServiceMetadata,
|
|
6
|
-
} from "../../../../Server/Services/OpenTelemetryIngestService";
|
|
7
|
-
import SecurityEventService from "../../../../Server/Services/SecurityEventService";
|
|
8
|
-
import logger from "../../../../Server/Utils/Logger";
|
|
9
|
-
import Semaphore from "../../../../Server/Infrastructure/Semaphore";
|
|
10
|
-
import { GoogleSecOpsRunResult } from "../../../../Types/SecurityEvent/GoogleSecOpsDiagnostics";
|
|
11
|
-
import GoogleSecOpsClient, {
|
|
12
|
-
FetchAlertsResult,
|
|
13
|
-
SearchDetectionsResult,
|
|
14
|
-
FetchLike,
|
|
15
|
-
FetchResponseLike,
|
|
16
|
-
} from "../../../../Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient";
|
|
17
|
-
import GoogleSecOpsPoller from "../../../../Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller";
|
|
18
|
-
import ThreatIntelEnricher, {
|
|
19
|
-
EnrichmentResult,
|
|
20
|
-
} from "../../../../Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher";
|
|
21
|
-
import LIMIT_MAX from "../../../../Types/Database/LimitMax";
|
|
22
|
-
import OneUptimeDate from "../../../../Types/Date";
|
|
23
|
-
import GoogleSecOpsAlertNormalizer from "../../../../Utils/SecurityEvent/GoogleSecOpsAlertNormalizer";
|
|
24
|
-
import { JSONObject } from "../../../../Types/JSON";
|
|
25
|
-
import ObjectID from "../../../../Types/ObjectID";
|
|
26
|
-
import NormalizedSecurityEvent from "../../../../Types/SecurityEvent/NormalizedSecurityEvent";
|
|
27
|
-
import OcsfSeverity from "../../../../Types/SecurityEvent/OcsfSeverity";
|
|
28
|
-
import ServiceType from "../../../../Types/Telemetry/ServiceType";
|
|
29
|
-
import { getJestSpyOn } from "../../../Spy";
|
|
30
|
-
import { afterEach, describe, expect, jest, test } from "@jest/globals";
|
|
31
|
-
|
|
32
|
-
/*
|
|
33
|
-
* The cursor is the only thing standing between a broken Google SecOps
|
|
34
|
-
* poll and permanent, silent data loss.
|
|
35
|
-
*
|
|
36
|
-
* legacyFetchAlertsView is a server-streaming method whose 200 body is an
|
|
37
|
-
* array of chunks with the alerts two levels down at chunk.alerts.alerts[].
|
|
38
|
-
* The client used to look for a top-level `alerts` array, find nothing,
|
|
39
|
-
* and return [] — and the poller read [] as "a quiet window", advanced the
|
|
40
|
-
* cursor past it, and cleared lastError. Every tick, for every tenant, a
|
|
41
|
-
* totally broken connector was byte-identical in the database to a healthy
|
|
42
|
-
* one with nothing to report.
|
|
43
|
-
*
|
|
44
|
-
* So the behaviors pinned here are the ones that decide whether a failure
|
|
45
|
-
* is recoverable: which outcomes may move the cursor forward, which must
|
|
46
|
-
* hold it where it is, what the poll window resolves to when the stored
|
|
47
|
-
* cursor cannot be trusted, and whether the number of events actually
|
|
48
|
-
* ingested is observable from outside the process at all.
|
|
49
|
-
*
|
|
50
|
-
* Everything runs through the real GoogleSecOpsClient over an injected
|
|
51
|
-
* transport wherever the response shape is the thing under test, so the
|
|
52
|
-
* chunk envelope these tests assert on is the one Chronicle sends.
|
|
53
|
-
*/
|
|
54
|
-
|
|
55
|
-
const PROJECT_ID: ObjectID = new ObjectID(
|
|
56
|
-
"11111111-1111-4111-8111-111111111111",
|
|
57
|
-
);
|
|
58
|
-
const CONNECTION_ID: ObjectID = new ObjectID(
|
|
59
|
-
"22222222-2222-4222-8222-222222222222",
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
const INSTANCE_RESOURCE_NAME: string =
|
|
63
|
-
"projects/my-project/locations/us/instances/3f0a-instance";
|
|
64
|
-
|
|
65
|
-
// Not Chronicle: the transport below routes on this to tell the two apart.
|
|
66
|
-
const GOOGLE_TOKEN_URI: string = "https://oauth2.googleapis.com/token";
|
|
67
|
-
|
|
68
|
-
/*
|
|
69
|
-
* A real RS256 key, because the client genuinely signs a JWT assertion on
|
|
70
|
-
* the way to the token endpoint and validates the PEM at construction; a
|
|
71
|
-
* fake key fails there instead of at the behavior under test.
|
|
72
|
-
*/
|
|
73
|
-
const { privateKey } = generateKeyPairSync("rsa", {
|
|
74
|
-
modulusLength: 2048,
|
|
75
|
-
privateKeyEncoding: { type: "pkcs8", format: "pem" },
|
|
76
|
-
publicKeyEncoding: { type: "spki", format: "pem" },
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const SERVICE_ACCOUNT_JSON: string = JSON.stringify({
|
|
80
|
-
client_email: "poller@example.iam.gserviceaccount.com",
|
|
81
|
-
private_key: privateKey,
|
|
82
|
-
token_uri: GOOGLE_TOKEN_URI,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const MINUTE_IN_MS: number = 60 * 1000;
|
|
86
|
-
const HOUR_IN_MS: number = 60 * MINUTE_IN_MS;
|
|
87
|
-
const DAY_IN_MS: number = 24 * HOUR_IN_MS;
|
|
88
|
-
|
|
89
|
-
const DETECTION_FINDING_CLASS_UID: number = 2004;
|
|
90
|
-
|
|
91
|
-
/*
|
|
92
|
-
* Captured at import time, before any spy replaces it.
|
|
93
|
-
* pollAllDueConnections calls `this.pollConnection(connection)` with no
|
|
94
|
-
* client override, so putting an injected transport under a full tick
|
|
95
|
-
* means spying on pollConnection and delegating straight back to the real
|
|
96
|
-
* implementation with a client attached. Everything inside it — the
|
|
97
|
-
* window arithmetic, the alert gate, the insert, the bookkeeping write —
|
|
98
|
-
* still runs for real.
|
|
99
|
-
*/
|
|
100
|
-
const originalPollConnection: (
|
|
101
|
-
connection: GoogleSecOpsConnection,
|
|
102
|
-
clientOverride?: GoogleSecOpsClient | undefined,
|
|
103
|
-
) => Promise<number> =
|
|
104
|
-
GoogleSecOpsPoller.pollConnection.bind(GoogleSecOpsPoller);
|
|
105
|
-
|
|
106
|
-
interface StubbedResponse {
|
|
107
|
-
status: number;
|
|
108
|
-
body: string;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
interface RecordedRequest {
|
|
112
|
-
url: string;
|
|
113
|
-
method: string;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
interface RecordedWindow {
|
|
117
|
-
startTime: Date;
|
|
118
|
-
endTime: Date;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// The shape of one updateOneById call, for readable assertions.
|
|
122
|
-
interface ConnectionUpdateCall {
|
|
123
|
-
id: ObjectID;
|
|
124
|
-
data: JSONObject;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
interface CapturedLogs {
|
|
128
|
-
info: Array<string>;
|
|
129
|
-
warn: Array<string>;
|
|
130
|
-
error: Array<string>;
|
|
131
|
-
debug: Array<string>;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
interface PollHarness {
|
|
135
|
-
updates: Array<ConnectionUpdateCall>;
|
|
136
|
-
insertedBatches: Array<Array<JSONObject>>;
|
|
137
|
-
logs: CapturedLogs;
|
|
138
|
-
telemetrySpy: ReturnType<typeof getJestSpyOn>;
|
|
139
|
-
insertSpy: ReturnType<typeof getJestSpyOn>;
|
|
140
|
-
enricherSpy: ReturnType<typeof getJestSpyOn>;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function makeConnection(): GoogleSecOpsConnection {
|
|
144
|
-
const connection: GoogleSecOpsConnection = new GoogleSecOpsConnection();
|
|
145
|
-
connection._id = CONNECTION_ID.toString();
|
|
146
|
-
connection.projectId = PROJECT_ID;
|
|
147
|
-
connection.name = "Prod tenant";
|
|
148
|
-
connection.region = "us";
|
|
149
|
-
connection.instanceResourceName = INSTANCE_RESOURCE_NAME;
|
|
150
|
-
connection.serviceAccountJson = SERVICE_ACCOUNT_JSON;
|
|
151
|
-
connection.pollIntervalInMinutes = 5;
|
|
152
|
-
// lastPolledAt left unset: never polled, therefore always due.
|
|
153
|
-
return connection;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function makeServiceMetadata(): TelemetryServiceMetadata {
|
|
157
|
-
return {
|
|
158
|
-
serviceName: "Google SecOps",
|
|
159
|
-
primaryEntityId: new ObjectID("33333333-3333-4333-8333-333333333333"),
|
|
160
|
-
primaryEntityType: ServiceType.OpenTelemetry,
|
|
161
|
-
dataRententionInDays: 15,
|
|
162
|
-
serviceRetentionConfig: null,
|
|
163
|
-
serviceRetentionInDays: null,
|
|
164
|
-
projectRetentionConfig: null,
|
|
165
|
-
projectRetentionInDays: 15,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/*
|
|
170
|
-
* One alert with its matched UDM sample event, so the finding row carries
|
|
171
|
-
* the entities the detection fired on rather than an empty shell.
|
|
172
|
-
*/
|
|
173
|
-
function alertOne(): JSONObject {
|
|
174
|
-
return {
|
|
175
|
-
id: "alert-1",
|
|
176
|
-
type: "RULE_DETECTION",
|
|
177
|
-
detectionTime: "2026-08-21T09:30:00.000Z",
|
|
178
|
-
detection: [
|
|
179
|
-
{
|
|
180
|
-
ruleName: "Suspicious PowerShell",
|
|
181
|
-
ruleId: "ru_1a2b",
|
|
182
|
-
severity: "HIGH",
|
|
183
|
-
alertState: "ALERTING",
|
|
184
|
-
},
|
|
185
|
-
],
|
|
186
|
-
collectionElements: [
|
|
187
|
-
{
|
|
188
|
-
label: "e1",
|
|
189
|
-
references: [
|
|
190
|
-
{
|
|
191
|
-
event: {
|
|
192
|
-
metadata: {
|
|
193
|
-
eventType: "PROCESS_LAUNCH",
|
|
194
|
-
eventTimestamp: "2026-08-21T09:29:58.000Z",
|
|
195
|
-
},
|
|
196
|
-
principal: {
|
|
197
|
-
hostname: "workstation-14",
|
|
198
|
-
ip: ["10.1.2.3"],
|
|
199
|
-
user: { userid: "jsmith" },
|
|
200
|
-
},
|
|
201
|
-
target: { ip: ["203.0.113.9"], port: 443 },
|
|
202
|
-
},
|
|
203
|
-
},
|
|
204
|
-
],
|
|
205
|
-
},
|
|
206
|
-
],
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function alertTwo(): JSONObject {
|
|
211
|
-
return {
|
|
212
|
-
id: "alert-2",
|
|
213
|
-
type: "RULE_DETECTION",
|
|
214
|
-
detectionTime: "2026-08-21T09:31:00.000Z",
|
|
215
|
-
detection: [
|
|
216
|
-
{
|
|
217
|
-
ruleName: "Impossible travel",
|
|
218
|
-
ruleId: "ru_9z8y",
|
|
219
|
-
severity: "CRITICAL",
|
|
220
|
-
},
|
|
221
|
-
],
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/*
|
|
226
|
-
* A FetchAlertsViewResponse chunk. Not an alert — it is the envelope the
|
|
227
|
-
* alerts arrive inside, and the client's own gate is what keeps it out of
|
|
228
|
-
* the alerts array in the first place.
|
|
229
|
-
*/
|
|
230
|
-
function streamChunk(): JSONObject {
|
|
231
|
-
return { progress: 0.5, complete: false };
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function okTokenResponse(): StubbedResponse {
|
|
235
|
-
return {
|
|
236
|
-
status: 200,
|
|
237
|
-
body: JSON.stringify({ access_token: "test-token", expires_in: 3600 }),
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/*
|
|
242
|
-
* Transport routed by URL rather than by call order, so a test can read
|
|
243
|
-
* the window off the Chronicle request without counting calls.
|
|
244
|
-
*/
|
|
245
|
-
function makeFetch(responses: {
|
|
246
|
-
token: StubbedResponse;
|
|
247
|
-
alerts: StubbedResponse;
|
|
248
|
-
}): {
|
|
249
|
-
fetchImplementation: FetchLike;
|
|
250
|
-
requests: Array<RecordedRequest>;
|
|
251
|
-
} {
|
|
252
|
-
const requests: Array<RecordedRequest> = [];
|
|
253
|
-
|
|
254
|
-
const fetchImplementation: FetchLike = (
|
|
255
|
-
url: string,
|
|
256
|
-
init: {
|
|
257
|
-
method: string;
|
|
258
|
-
headers: Record<string, string>;
|
|
259
|
-
body?: string | undefined;
|
|
260
|
-
},
|
|
261
|
-
): Promise<FetchResponseLike> => {
|
|
262
|
-
requests.push({ url: url, method: init.method });
|
|
263
|
-
|
|
264
|
-
/*
|
|
265
|
-
* The created-time search passes answer with an empty page so these
|
|
266
|
-
* fixtures keep describing the alerts-view path they were written for.
|
|
267
|
-
*/
|
|
268
|
-
const response: StubbedResponse =
|
|
269
|
-
url === GOOGLE_TOKEN_URI
|
|
270
|
-
? responses.token
|
|
271
|
-
: url.includes("legacySearch")
|
|
272
|
-
? { status: 200, body: "{}" }
|
|
273
|
-
: responses.alerts;
|
|
274
|
-
|
|
275
|
-
return Promise.resolve({
|
|
276
|
-
ok: response.status >= 200 && response.status < 300,
|
|
277
|
-
status: response.status,
|
|
278
|
-
text: (): Promise<string> => {
|
|
279
|
-
return Promise.resolve(response.body);
|
|
280
|
-
},
|
|
281
|
-
});
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
return { fetchImplementation: fetchImplementation, requests: requests };
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function makeClient(alerts: StubbedResponse): {
|
|
288
|
-
client: GoogleSecOpsClient;
|
|
289
|
-
requests: Array<RecordedRequest>;
|
|
290
|
-
} {
|
|
291
|
-
const { fetchImplementation, requests } = makeFetch({
|
|
292
|
-
token: okTokenResponse(),
|
|
293
|
-
alerts: alerts,
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
const client: GoogleSecOpsClient = new GoogleSecOpsClient({
|
|
297
|
-
region: "us",
|
|
298
|
-
instanceResourceName: INSTANCE_RESOURCE_NAME,
|
|
299
|
-
serviceAccountJson: SERVICE_ACCOUNT_JSON,
|
|
300
|
-
fetchImplementation: fetchImplementation,
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
return { client: client, requests: requests };
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/* A 200 whose body is the real streaming envelope. */
|
|
307
|
-
function streamingResponse(chunks: Array<JSONObject>): StubbedResponse {
|
|
308
|
-
return { status: 200, body: JSON.stringify(chunks) };
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function alertsRequestOf(requests: Array<RecordedRequest>): RecordedRequest {
|
|
312
|
-
const alertsRequests: Array<RecordedRequest> = requests.filter(
|
|
313
|
-
(request: RecordedRequest): boolean => {
|
|
314
|
-
return (
|
|
315
|
-
request.url !== GOOGLE_TOKEN_URI &&
|
|
316
|
-
!request.url.includes("legacySearch")
|
|
317
|
-
);
|
|
318
|
-
},
|
|
319
|
-
);
|
|
320
|
-
|
|
321
|
-
expect(alertsRequests).toHaveLength(1);
|
|
322
|
-
|
|
323
|
-
return alertsRequests[0]!;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
function windowSentTo(requests: Array<RecordedRequest>): {
|
|
327
|
-
startTime: string;
|
|
328
|
-
endTime: string;
|
|
329
|
-
} {
|
|
330
|
-
const params: URLSearchParams = new URL(alertsRequestOf(requests).url)
|
|
331
|
-
.searchParams;
|
|
332
|
-
|
|
333
|
-
return {
|
|
334
|
-
startTime: params.get("timeRange.startTime") || "",
|
|
335
|
-
endTime: params.get("timeRange.endTime") || "",
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/*
|
|
340
|
-
* What the client hands back for a window that parsed cleanly. Used where
|
|
341
|
-
* the response SHAPE is not the thing under test.
|
|
342
|
-
*/
|
|
343
|
-
function stubbedFetchResult(alerts: Array<JSONObject>): FetchAlertsResult {
|
|
344
|
-
return {
|
|
345
|
-
alerts: alerts,
|
|
346
|
-
complete: true,
|
|
347
|
-
progress: 1,
|
|
348
|
-
truncatedByCount: false,
|
|
349
|
-
truncatedByBytes: false,
|
|
350
|
-
baselineAlertsCount: alerts.length,
|
|
351
|
-
filteredAlertsCount: alerts.length,
|
|
352
|
-
chunkCount: 1,
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function makeStubClient(result: FetchAlertsResult): {
|
|
357
|
-
client: GoogleSecOpsClient;
|
|
358
|
-
windows: Array<RecordedWindow>;
|
|
359
|
-
} {
|
|
360
|
-
const windows: Array<RecordedWindow> = [];
|
|
361
|
-
|
|
362
|
-
const client: GoogleSecOpsClient = {
|
|
363
|
-
searchDetections: (): Promise<SearchDetectionsResult> => {
|
|
364
|
-
return Promise.resolve({
|
|
365
|
-
detections: [],
|
|
366
|
-
nextPageToken: null,
|
|
367
|
-
truncated: false,
|
|
368
|
-
});
|
|
369
|
-
},
|
|
370
|
-
fetchDetectionAlerts: (data: {
|
|
371
|
-
startTime: Date;
|
|
372
|
-
endTime: Date;
|
|
373
|
-
}): Promise<FetchAlertsResult> => {
|
|
374
|
-
windows.push({ startTime: data.startTime, endTime: data.endTime });
|
|
375
|
-
return Promise.resolve(result);
|
|
376
|
-
},
|
|
377
|
-
} as unknown as GoogleSecOpsClient;
|
|
378
|
-
|
|
379
|
-
return { client: client, windows: windows };
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/*
|
|
383
|
-
* A client that fails the way a normalizer fault does not: the alerts
|
|
384
|
-
* never arrive at all.
|
|
385
|
-
*/
|
|
386
|
-
function makeThrowingStubClient(error: Error): GoogleSecOpsClient {
|
|
387
|
-
return {
|
|
388
|
-
searchDetections: (): Promise<SearchDetectionsResult> => {
|
|
389
|
-
return Promise.resolve({
|
|
390
|
-
detections: [],
|
|
391
|
-
nextPageToken: null,
|
|
392
|
-
truncated: false,
|
|
393
|
-
});
|
|
394
|
-
},
|
|
395
|
-
fetchDetectionAlerts: (): Promise<FetchAlertsResult> => {
|
|
396
|
-
return Promise.reject(error);
|
|
397
|
-
},
|
|
398
|
-
} as unknown as GoogleSecOpsClient;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
function textOf(body: unknown): string {
|
|
402
|
-
if (typeof body === "string") {
|
|
403
|
-
return body;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
if (body instanceof Error) {
|
|
407
|
-
return body.message;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
return String(body);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
function captureLogs(): CapturedLogs {
|
|
414
|
-
const logs: CapturedLogs = { info: [], warn: [], error: [], debug: [] };
|
|
415
|
-
|
|
416
|
-
const levels: Array<"info" | "warn" | "error" | "debug"> = [
|
|
417
|
-
"info",
|
|
418
|
-
"warn",
|
|
419
|
-
"error",
|
|
420
|
-
"debug",
|
|
421
|
-
];
|
|
422
|
-
|
|
423
|
-
for (const level of levels) {
|
|
424
|
-
getJestSpyOn(logger, level).mockImplementation(((body: unknown): void => {
|
|
425
|
-
logs[level].push(textOf(body));
|
|
426
|
-
return undefined;
|
|
427
|
-
}) as never);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
return logs;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/*
|
|
434
|
-
* Poller lines name the connection; the client's own warnings do not. That
|
|
435
|
-
* is the seam these tests use to assert on what the POLLER said.
|
|
436
|
-
*/
|
|
437
|
-
function linesAboutConnection(lines: Array<string>): Array<string> {
|
|
438
|
-
return lines.filter((line: string): boolean => {
|
|
439
|
-
return line.includes(CONNECTION_ID.toString());
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/*
|
|
444
|
-
* Every write the poll would perform, captured instead of performed.
|
|
445
|
-
* Called per test rather than in a beforeEach so no two tests can share a
|
|
446
|
-
* spy or the order they were installed in.
|
|
447
|
-
*/
|
|
448
|
-
function stubPollPath(): PollHarness {
|
|
449
|
-
const updates: Array<ConnectionUpdateCall> = [];
|
|
450
|
-
const insertedBatches: Array<Array<JSONObject>> = [];
|
|
451
|
-
getJestSpyOn(Semaphore, "lock").mockResolvedValue({} as never);
|
|
452
|
-
getJestSpyOn(Semaphore, "release").mockResolvedValue(undefined as never);
|
|
453
|
-
getJestSpyOn(GoogleSecOpsPoller, "findExistingEventUids").mockResolvedValue(
|
|
454
|
-
new Set() as never,
|
|
455
|
-
);
|
|
456
|
-
|
|
457
|
-
const telemetrySpy: ReturnType<typeof getJestSpyOn> = getJestSpyOn(
|
|
458
|
-
OTelIngestService,
|
|
459
|
-
"telemetryServiceFromName",
|
|
460
|
-
).mockResolvedValue(makeServiceMetadata() as never);
|
|
461
|
-
|
|
462
|
-
const insertSpy: ReturnType<typeof getJestSpyOn> = getJestSpyOn(
|
|
463
|
-
SecurityEventService,
|
|
464
|
-
"insertJsonRows",
|
|
465
|
-
).mockImplementation(((rows: Array<JSONObject>): Promise<void> => {
|
|
466
|
-
insertedBatches.push(rows);
|
|
467
|
-
return Promise.resolve();
|
|
468
|
-
}) as never);
|
|
469
|
-
|
|
470
|
-
getJestSpyOn(
|
|
471
|
-
GoogleSecOpsConnectionService,
|
|
472
|
-
"updateOneById",
|
|
473
|
-
).mockImplementation(((call: ConnectionUpdateCall): Promise<void> => {
|
|
474
|
-
updates.push(call);
|
|
475
|
-
return Promise.resolve();
|
|
476
|
-
}) as never);
|
|
477
|
-
|
|
478
|
-
/*
|
|
479
|
-
* Enrichment reaches ClickHouse for its per-project indicator probe and
|
|
480
|
-
* swallows its own failures, so leaving it live would make every test
|
|
481
|
-
* here depend on a database being absent in exactly the right way.
|
|
482
|
-
*/
|
|
483
|
-
const enricherSpy: ReturnType<typeof getJestSpyOn> = getJestSpyOn(
|
|
484
|
-
ThreatIntelEnricher,
|
|
485
|
-
"enrichNormalizedEvents",
|
|
486
|
-
).mockResolvedValue({ eventsMatched: 0, valuesLookedUp: 0 } as never);
|
|
487
|
-
|
|
488
|
-
return {
|
|
489
|
-
updates: updates,
|
|
490
|
-
insertedBatches: insertedBatches,
|
|
491
|
-
logs: captureLogs(),
|
|
492
|
-
telemetrySpy: telemetrySpy,
|
|
493
|
-
insertSpy: insertSpy,
|
|
494
|
-
enricherSpy: enricherSpy,
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
function onlyUpdate(harness: PollHarness): JSONObject {
|
|
499
|
-
expect(harness.updates.length).toBeGreaterThanOrEqual(1);
|
|
500
|
-
expect(harness.updates[0]!.id.toString()).toBe(CONNECTION_ID.toString());
|
|
501
|
-
return (
|
|
502
|
-
harness.updates.find((update: ConnectionUpdateCall): boolean => {
|
|
503
|
-
return Boolean(update.data["lastPollResult"]);
|
|
504
|
-
})?.data || harness.updates[0]!.data
|
|
505
|
-
);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
function rowsByEventUid(rows: Array<JSONObject>): Map<string, JSONObject> {
|
|
509
|
-
const byUid: Map<string, JSONObject> = new Map<string, JSONObject>();
|
|
510
|
-
|
|
511
|
-
for (const row of rows) {
|
|
512
|
-
byUid.set(String(row["eventUid"]), row);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
return byUid;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
describe("GoogleSecOpsPoller over a real streaming response", () => {
|
|
519
|
-
afterEach(() => {
|
|
520
|
-
jest.restoreAllMocks();
|
|
521
|
-
});
|
|
522
|
-
|
|
523
|
-
test("a chunk-array body becomes Detection Finding rows, deduped across chunks", async () => {
|
|
524
|
-
const harness: PollHarness = stubPollPath();
|
|
525
|
-
|
|
526
|
-
/*
|
|
527
|
-
* Three chunks the way Chronicle streams them: alerts nested at
|
|
528
|
-
* chunk.alerts.alerts[], a later chunk restating an earlier alert, and
|
|
529
|
-
* a terminal chunk carrying only the completion flags.
|
|
530
|
-
*/
|
|
531
|
-
const { client } = makeClient(
|
|
532
|
-
streamingResponse([
|
|
533
|
-
{ progress: 0.25, alerts: { alerts: [alertOne()] } },
|
|
534
|
-
{ progress: 0.75, alerts: { alerts: [alertOne(), alertTwo()] } },
|
|
535
|
-
{
|
|
536
|
-
progress: 1,
|
|
537
|
-
complete: true,
|
|
538
|
-
baselineAlertsCount: 2,
|
|
539
|
-
filteredAlertsCount: 2,
|
|
540
|
-
},
|
|
541
|
-
]),
|
|
542
|
-
);
|
|
543
|
-
|
|
544
|
-
const ingested: number = await GoogleSecOpsPoller.pollConnection(
|
|
545
|
-
makeConnection(),
|
|
546
|
-
client,
|
|
547
|
-
);
|
|
548
|
-
|
|
549
|
-
// Two alerts, not three: the restated alert-1 is one alert, not two.
|
|
550
|
-
expect(ingested).toBe(2);
|
|
551
|
-
expect(harness.insertedBatches).toHaveLength(1);
|
|
552
|
-
|
|
553
|
-
const rows: Array<JSONObject> = harness.insertedBatches[0]!;
|
|
554
|
-
expect(rows).toHaveLength(2);
|
|
555
|
-
|
|
556
|
-
const byUid: Map<string, JSONObject> = rowsByEventUid(rows);
|
|
557
|
-
expect(Array.from(byUid.keys()).sort()).toEqual(["alert-1", "alert-2"]);
|
|
558
|
-
|
|
559
|
-
const first: JSONObject = byUid.get("alert-1")!;
|
|
560
|
-
expect(first["classUid"]).toBe(DETECTION_FINDING_CLASS_UID);
|
|
561
|
-
expect(first["className"]).toBe("Detection Finding");
|
|
562
|
-
expect(first["vendorName"]).toBe("Google");
|
|
563
|
-
expect(first["productName"]).toBe("Google SecOps");
|
|
564
|
-
expect(first["projectId"]).toBe(PROJECT_ID.toString());
|
|
565
|
-
expect(first["ruleName"]).toBe("Suspicious PowerShell");
|
|
566
|
-
expect(first["ruleId"]).toBe("ru_1a2b");
|
|
567
|
-
expect(first["severityName"]).toBe("High");
|
|
568
|
-
expect(first["severityId"]).toBe(4);
|
|
569
|
-
expect(first["statusName"]).toBe("ALERTING");
|
|
570
|
-
|
|
571
|
-
// The matched UDM sample event is what puts entities on the finding.
|
|
572
|
-
expect(first["principalHost"]).toBe("workstation-14");
|
|
573
|
-
expect(first["principalIp"]).toBe("10.1.2.3");
|
|
574
|
-
expect(first["principalUser"]).toBe("jsmith");
|
|
575
|
-
expect(first["targetIp"]).toBe("203.0.113.9");
|
|
576
|
-
expect(first["observables"]).toEqual(
|
|
577
|
-
expect.arrayContaining(["jsmith", "workstation-14", "10.1.2.3"]),
|
|
578
|
-
);
|
|
579
|
-
|
|
580
|
-
const second: JSONObject = byUid.get("alert-2")!;
|
|
581
|
-
expect(second["ruleName"]).toBe("Impossible travel");
|
|
582
|
-
expect(second["severityName"]).toBe("Critical");
|
|
583
|
-
expect(second["classUid"]).toBe(DETECTION_FINDING_CLASS_UID);
|
|
584
|
-
|
|
585
|
-
const written: JSONObject = onlyUpdate(harness);
|
|
586
|
-
expect(written).toEqual(
|
|
587
|
-
expect.objectContaining({
|
|
588
|
-
cursor: expect.any(String),
|
|
589
|
-
lastPolledAt: expect.any(Date),
|
|
590
|
-
lastPollResult: expect.any(Object),
|
|
591
|
-
}),
|
|
592
|
-
);
|
|
593
|
-
expect(written["lastError"]).toBeNull();
|
|
594
|
-
});
|
|
595
|
-
|
|
596
|
-
test("the cursor written is exactly the endTime the fetch was made with", async () => {
|
|
597
|
-
const harness: PollHarness = stubPollPath();
|
|
598
|
-
|
|
599
|
-
const { client, requests } = makeClient(
|
|
600
|
-
streamingResponse([
|
|
601
|
-
{ alerts: { alerts: [alertOne()] } },
|
|
602
|
-
{ complete: true, progress: 1 },
|
|
603
|
-
]),
|
|
604
|
-
);
|
|
605
|
-
|
|
606
|
-
await GoogleSecOpsPoller.pollConnection(makeConnection(), client);
|
|
607
|
-
|
|
608
|
-
const sent: { startTime: string; endTime: string } = windowSentTo(requests);
|
|
609
|
-
|
|
610
|
-
// The parameter really is an ISO instant, not some other rendering.
|
|
611
|
-
expect(new Date(sent.endTime).toISOString()).toBe(sent.endTime);
|
|
612
|
-
|
|
613
|
-
const written: JSONObject = onlyUpdate(harness);
|
|
614
|
-
expect(written["cursor"]).toBe(sent.endTime);
|
|
615
|
-
expect((written["lastPolledAt"] as Date).getTime()).toBeGreaterThanOrEqual(
|
|
616
|
-
Date.parse(sent.endTime),
|
|
617
|
-
);
|
|
618
|
-
|
|
619
|
-
// ...and the window it closes really did start earlier than it ends.
|
|
620
|
-
expect(new Date(sent.startTime).getTime()).toBeLessThan(
|
|
621
|
-
new Date(sent.endTime).getTime(),
|
|
622
|
-
);
|
|
623
|
-
});
|
|
624
|
-
|
|
625
|
-
test("a recognized response carrying no alerts advances the cursor and clears lastError", async () => {
|
|
626
|
-
const harness: PollHarness = stubPollPath();
|
|
627
|
-
|
|
628
|
-
// A quiet window: recognized chunk fields, zero alerts, complete.
|
|
629
|
-
const { client, requests } = makeClient(
|
|
630
|
-
streamingResponse([{ complete: true, progress: 1 }]),
|
|
631
|
-
);
|
|
632
|
-
|
|
633
|
-
const ingested: number = await GoogleSecOpsPoller.pollConnection(
|
|
634
|
-
makeConnection(),
|
|
635
|
-
client,
|
|
636
|
-
);
|
|
637
|
-
|
|
638
|
-
expect(ingested).toBe(0);
|
|
639
|
-
expect(harness.telemetrySpy).not.toHaveBeenCalled();
|
|
640
|
-
expect(harness.insertSpy).not.toHaveBeenCalled();
|
|
641
|
-
|
|
642
|
-
const written: JSONObject = onlyUpdate(harness);
|
|
643
|
-
expect(written).toEqual(
|
|
644
|
-
expect.objectContaining({
|
|
645
|
-
cursor: expect.any(String),
|
|
646
|
-
lastPolledAt: expect.any(Date),
|
|
647
|
-
lastPollResult: expect.any(Object),
|
|
648
|
-
}),
|
|
649
|
-
);
|
|
650
|
-
expect(written["cursor"]).toBe(windowSentTo(requests).endTime);
|
|
651
|
-
expect(written["lastError"]).toBeNull();
|
|
652
|
-
|
|
653
|
-
expect(written["lastPollResult"]).toEqual(
|
|
654
|
-
expect.objectContaining({
|
|
655
|
-
status: "empty",
|
|
656
|
-
fetchedCount: 0,
|
|
657
|
-
ingestedCount: 0,
|
|
658
|
-
complete: true,
|
|
659
|
-
}),
|
|
660
|
-
);
|
|
661
|
-
expect(written["lastSuccessfulPollAt"]).toBeInstanceOf(Date);
|
|
662
|
-
});
|
|
663
|
-
|
|
664
|
-
test("persistent truncation reports partial coverage and preserves the first window for retry", async () => {
|
|
665
|
-
const harness: PollHarness = stubPollPath();
|
|
666
|
-
const { client, requests } = makeClient(
|
|
667
|
-
streamingResponse([
|
|
668
|
-
{
|
|
669
|
-
alerts: { alerts: [alertOne()] },
|
|
670
|
-
tooManyAlerts: true,
|
|
671
|
-
memoryLimitExceeded: true,
|
|
672
|
-
complete: true,
|
|
673
|
-
progress: 1,
|
|
674
|
-
},
|
|
675
|
-
]),
|
|
676
|
-
);
|
|
677
|
-
const result: GoogleSecOpsRunResult =
|
|
678
|
-
await GoogleSecOpsPoller.executeConnection(
|
|
679
|
-
makeConnection(),
|
|
680
|
-
{ type: "poll" },
|
|
681
|
-
client,
|
|
682
|
-
);
|
|
683
|
-
expect(result.status).toBe("partial");
|
|
684
|
-
expect(result.complete).toBe(false);
|
|
685
|
-
expect(result.ingestedCount).toBe(1);
|
|
686
|
-
expect(harness.insertedBatches).toHaveLength(1);
|
|
687
|
-
expect(result.requestCount).toBeGreaterThan(1);
|
|
688
|
-
expect(result.warnings.join(" ")).toMatch(/limited|truncated|limit/);
|
|
689
|
-
const written: JSONObject = onlyUpdate(harness);
|
|
690
|
-
expect(Date.parse(String(written["cursor"])) - MINUTE_IN_MS).toBe(
|
|
691
|
-
Date.parse(result.windowStart),
|
|
692
|
-
);
|
|
693
|
-
expect(written["lastError"]).toBeTruthy();
|
|
694
|
-
expect(written["lastSuccessfulPollAt"]).toBeUndefined();
|
|
695
|
-
expect(requests.length).toBeGreaterThan(2);
|
|
696
|
-
/*
|
|
697
|
-
* F1: holding the first window is no longer the whole answer. The next
|
|
698
|
-
* poll keeps the same start and reads half the day, so a window that
|
|
699
|
-
* never fits cannot pin the connection.
|
|
700
|
-
*/
|
|
701
|
-
expect(result.chunkMinutes).toBe(24 * 60);
|
|
702
|
-
expect(result.nextChunkMinutes).toBe(12 * 60);
|
|
703
|
-
expect(String(written["lastError"])).toContain(
|
|
704
|
-
"the next poll reads a 720 minute window from the same starting point",
|
|
705
|
-
);
|
|
706
|
-
});
|
|
707
|
-
});
|
|
708
|
-
|
|
709
|
-
describe("GoogleSecOpsPoller cursor durability", () => {
|
|
710
|
-
afterEach(() => {
|
|
711
|
-
jest.restoreAllMocks();
|
|
712
|
-
});
|
|
713
|
-
|
|
714
|
-
/*
|
|
715
|
-
* THE PIN. This is the failure that has to stay impossible.
|
|
716
|
-
*
|
|
717
|
-
* A body the client cannot recognize must throw rather than report zero
|
|
718
|
-
* alerts, and the throw must leave the cursor exactly where it was. If
|
|
719
|
-
* either half regresses — the client returning [] for an unknown shape,
|
|
720
|
-
* or the poller advancing on the way past a failure — a connector that
|
|
721
|
-
* reads nothing at all becomes indistinguishable from a quiet one, and
|
|
722
|
-
* every alert in every skipped window is lost permanently.
|
|
723
|
-
*/
|
|
724
|
-
test("an unrecognized response body leaves the cursor untouched and records lastError", async () => {
|
|
725
|
-
const harness: PollHarness = stubPollPath();
|
|
726
|
-
|
|
727
|
-
const storedCursor: string = new Date(
|
|
728
|
-
Date.now() - 10 * MINUTE_IN_MS,
|
|
729
|
-
).toISOString();
|
|
730
|
-
|
|
731
|
-
const connection: GoogleSecOpsConnection = makeConnection();
|
|
732
|
-
connection.cursor = storedCursor;
|
|
733
|
-
|
|
734
|
-
// HTTP 200, valid JSON, and not this endpoint's response.
|
|
735
|
-
const { client } = makeClient({ status: 200, body: '{"nope":true}' });
|
|
736
|
-
|
|
737
|
-
getJestSpyOn(GoogleSecOpsConnectionService, "findBy").mockResolvedValue([
|
|
738
|
-
connection,
|
|
739
|
-
] as never);
|
|
740
|
-
|
|
741
|
-
getJestSpyOn(GoogleSecOpsPoller, "pollConnection").mockImplementation(((
|
|
742
|
-
polled: GoogleSecOpsConnection,
|
|
743
|
-
): Promise<number> => {
|
|
744
|
-
return originalPollConnection(polled, client);
|
|
745
|
-
}) as never);
|
|
746
|
-
|
|
747
|
-
await expect(
|
|
748
|
-
GoogleSecOpsPoller.pollAllDueConnections(),
|
|
749
|
-
).resolves.toBeUndefined();
|
|
750
|
-
|
|
751
|
-
expect(harness.insertSpy).not.toHaveBeenCalled();
|
|
752
|
-
|
|
753
|
-
const written: JSONObject = onlyUpdate(harness);
|
|
754
|
-
|
|
755
|
-
/*
|
|
756
|
-
* No `cursor` key at all. Not "the same cursor" — the failure path
|
|
757
|
-
* must not be in the business of writing the column.
|
|
758
|
-
*/
|
|
759
|
-
expect(written["lastPollResult"]).toEqual(
|
|
760
|
-
expect.objectContaining({ complete: false }),
|
|
761
|
-
);
|
|
762
|
-
expect(written["lastSuccessfulPollAt"]).toBeUndefined();
|
|
763
|
-
expect(written["lastPolledAt"]).toBeInstanceOf(Date);
|
|
764
|
-
expect(connection.cursor).toBe(storedCursor);
|
|
765
|
-
expect(written["cursor"]).toBeUndefined();
|
|
766
|
-
|
|
767
|
-
const lastError: unknown = written["lastError"];
|
|
768
|
-
expect(typeof lastError).toBe("string");
|
|
769
|
-
// The body is echoed, so the operator can see what came back.
|
|
770
|
-
expect(lastError as string).toContain('{"nope":true}');
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
test("a fetch that throws before any alert arrives leaves the cursor untouched", async () => {
|
|
774
|
-
const harness: PollHarness = stubPollPath();
|
|
775
|
-
|
|
776
|
-
const connection: GoogleSecOpsConnection = makeConnection();
|
|
777
|
-
|
|
778
|
-
getJestSpyOn(GoogleSecOpsConnectionService, "findBy").mockResolvedValue([
|
|
779
|
-
connection,
|
|
780
|
-
] as never);
|
|
781
|
-
|
|
782
|
-
getJestSpyOn(GoogleSecOpsPoller, "pollConnection").mockImplementation(((
|
|
783
|
-
polled: GoogleSecOpsConnection,
|
|
784
|
-
): Promise<number> => {
|
|
785
|
-
return originalPollConnection(
|
|
786
|
-
polled,
|
|
787
|
-
makeThrowingStubClient(new Error("socket hang up")),
|
|
788
|
-
);
|
|
789
|
-
}) as never);
|
|
790
|
-
|
|
791
|
-
await GoogleSecOpsPoller.pollAllDueConnections();
|
|
792
|
-
|
|
793
|
-
const written: JSONObject = onlyUpdate(harness);
|
|
794
|
-
expect(written["lastPollResult"]).toEqual(
|
|
795
|
-
expect.objectContaining({ complete: false }),
|
|
796
|
-
);
|
|
797
|
-
expect(written["lastSuccessfulPollAt"]).toBeUndefined();
|
|
798
|
-
expect(written["lastError"]).toContain("socket hang up");
|
|
799
|
-
});
|
|
800
|
-
|
|
801
|
-
test("alerts that all fail to normalize hold the cursor rather than skipping the window", async () => {
|
|
802
|
-
const harness: PollHarness = stubPollPath();
|
|
803
|
-
|
|
804
|
-
/*
|
|
805
|
-
* The normalizer is tolerant by design, so a poison alert has to be
|
|
806
|
-
* built out of a hostile getter: the alerts are real as far as
|
|
807
|
-
* Chronicle is concerned and unstorable as far as we are concerned,
|
|
808
|
-
* which is the case where re-fetching the window is the only way the
|
|
809
|
-
* data is ever recovered.
|
|
810
|
-
*/
|
|
811
|
-
const poison: JSONObject = {};
|
|
812
|
-
Object.defineProperty(poison, "detection", {
|
|
813
|
-
get: (): never => {
|
|
814
|
-
throw new Error("poison alert");
|
|
815
|
-
},
|
|
816
|
-
enumerable: true,
|
|
817
|
-
});
|
|
818
|
-
|
|
819
|
-
const alsoPoison: JSONObject = {};
|
|
820
|
-
Object.defineProperty(alsoPoison, "detection", {
|
|
821
|
-
get: (): never => {
|
|
822
|
-
throw new Error("poison alert");
|
|
823
|
-
},
|
|
824
|
-
enumerable: true,
|
|
825
|
-
});
|
|
826
|
-
|
|
827
|
-
const { client } = makeStubClient(stubbedFetchResult([poison, alsoPoison]));
|
|
828
|
-
|
|
829
|
-
const ingested: number = await GoogleSecOpsPoller.pollConnection(
|
|
830
|
-
makeConnection(),
|
|
831
|
-
client,
|
|
832
|
-
);
|
|
833
|
-
|
|
834
|
-
expect(ingested).toBe(0);
|
|
835
|
-
expect(harness.insertSpy).not.toHaveBeenCalled();
|
|
836
|
-
|
|
837
|
-
const written: JSONObject = onlyUpdate(harness);
|
|
838
|
-
expect(written["lastPollResult"]).toEqual(
|
|
839
|
-
expect.objectContaining({ complete: false }),
|
|
840
|
-
);
|
|
841
|
-
expect(written["lastSuccessfulPollAt"]).toBeUndefined();
|
|
842
|
-
|
|
843
|
-
const result: GoogleSecOpsRunResult = written[
|
|
844
|
-
"lastPollResult"
|
|
845
|
-
] as unknown as GoogleSecOpsRunResult;
|
|
846
|
-
expect(result.status).toBe("partial");
|
|
847
|
-
expect(result.failedCount).toBe(2);
|
|
848
|
-
expect(Date.parse(String(written["cursor"])) - MINUTE_IN_MS).toBe(
|
|
849
|
-
Date.parse(result.windowStart),
|
|
850
|
-
);
|
|
851
|
-
});
|
|
852
|
-
|
|
853
|
-
/*
|
|
854
|
-
* THE OTHER PIN. A FetchAlertsViewResponse chunk is not an alert.
|
|
855
|
-
*
|
|
856
|
-
* GoogleSecOpsAlertNormalizer.normalize is a total function whose class,
|
|
857
|
-
* category, vendor and product are constants, so ANY object handed to it
|
|
858
|
-
* comes back as a plausible Detection Finding: severity Unknown, no
|
|
859
|
-
* entities, message "Google SecOps detection". Stored, it is
|
|
860
|
-
* indistinguishable in the UI from a real low-signal detection. The gate
|
|
861
|
-
* in front of the normalizer is the only thing between an envelope chunk
|
|
862
|
-
* and a fabricated security finding.
|
|
863
|
-
*/
|
|
864
|
-
test("a stream chunk that reaches the poller produces no row", async () => {
|
|
865
|
-
const harness: PollHarness = stubPollPath();
|
|
866
|
-
|
|
867
|
-
/*
|
|
868
|
-
* What the gate stands in front of. Handed the chunk directly, the
|
|
869
|
-
* normalizer answers with a fully formed Detection Finding — this is
|
|
870
|
-
* the row the poll below must not write, and the reason "it produced
|
|
871
|
-
* no row" is a real property rather than an accident of the fixture.
|
|
872
|
-
*/
|
|
873
|
-
const wouldBeStored: NormalizedSecurityEvent =
|
|
874
|
-
GoogleSecOpsAlertNormalizer.normalize(streamChunk());
|
|
875
|
-
expect(wouldBeStored.classUid).toBe(DETECTION_FINDING_CLASS_UID);
|
|
876
|
-
expect(wouldBeStored.className).toBe("Detection Finding");
|
|
877
|
-
expect(wouldBeStored.severityName).toBe(OcsfSeverity.Unknown);
|
|
878
|
-
expect(wouldBeStored.message).toBe("Google SecOps detection");
|
|
879
|
-
expect(GoogleSecOpsAlertNormalizer.isGoogleSecOpsAlert(streamChunk())).toBe(
|
|
880
|
-
false,
|
|
881
|
-
);
|
|
882
|
-
|
|
883
|
-
const { client } = makeStubClient(
|
|
884
|
-
stubbedFetchResult([streamChunk(), alertOne()]),
|
|
885
|
-
);
|
|
886
|
-
|
|
887
|
-
const ingested: number = await GoogleSecOpsPoller.pollConnection(
|
|
888
|
-
makeConnection(),
|
|
889
|
-
client,
|
|
890
|
-
);
|
|
891
|
-
|
|
892
|
-
expect(ingested).toBe(1);
|
|
893
|
-
expect(harness.insertedBatches).toHaveLength(1);
|
|
894
|
-
|
|
895
|
-
const rows: Array<JSONObject> = harness.insertedBatches[0]!;
|
|
896
|
-
expect(rows).toHaveLength(1);
|
|
897
|
-
expect(rows[0]!["eventUid"]).toBe("alert-1");
|
|
898
|
-
|
|
899
|
-
/*
|
|
900
|
-
* The fabricated row's fingerprint, from the defect report: a
|
|
901
|
-
* content-hash eventUid, severity Unknown and the fallback message.
|
|
902
|
-
*/
|
|
903
|
-
for (const row of rows) {
|
|
904
|
-
expect(row["message"]).not.toBe("Google SecOps detection");
|
|
905
|
-
expect(String(row["eventUid"]).startsWith("sha256:")).toBe(false);
|
|
906
|
-
expect(row["severityName"]).not.toBe("Unknown");
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
const written: JSONObject = onlyUpdate(harness);
|
|
910
|
-
const result: GoogleSecOpsRunResult = written[
|
|
911
|
-
"lastPollResult"
|
|
912
|
-
] as unknown as GoogleSecOpsRunResult;
|
|
913
|
-
/*
|
|
914
|
-
* Counted and warned, but the cursor moves on: a stream chunk is
|
|
915
|
-
* permanently unrecognizable, so holding the window for it would pin
|
|
916
|
-
* the connector until the 24 hour chunk could never reach the present.
|
|
917
|
-
*/
|
|
918
|
-
expect(result.status).toBe("success");
|
|
919
|
-
expect(result.complete).toBe(true);
|
|
920
|
-
expect(result.rejectedCount).toBe(1);
|
|
921
|
-
expect(result.ingestedCount).toBe(1);
|
|
922
|
-
expect(result.warnings.join(" ")).toMatch(/discarded/);
|
|
923
|
-
expect(
|
|
924
|
-
result.checks.find((check: { name: string }): boolean => {
|
|
925
|
-
return check.name === "Normalize detections";
|
|
926
|
-
})?.status,
|
|
927
|
-
).toBe("warn");
|
|
928
|
-
expect(written["cursor"]).toBe(result.windowEnd);
|
|
929
|
-
});
|
|
930
|
-
});
|
|
931
|
-
|
|
932
|
-
describe("GoogleSecOpsPoller ingest bookkeeping", () => {
|
|
933
|
-
afterEach(() => {
|
|
934
|
-
jest.restoreAllMocks();
|
|
935
|
-
});
|
|
936
|
-
|
|
937
|
-
test("the ingested count is returned and matches the rows written", async () => {
|
|
938
|
-
const harness: PollHarness = stubPollPath();
|
|
939
|
-
|
|
940
|
-
const { client } = makeStubClient(
|
|
941
|
-
stubbedFetchResult([alertOne(), alertTwo(), streamChunk()]),
|
|
942
|
-
);
|
|
943
|
-
|
|
944
|
-
const ingested: number = await GoogleSecOpsPoller.pollConnection(
|
|
945
|
-
makeConnection(),
|
|
946
|
-
client,
|
|
947
|
-
);
|
|
948
|
-
|
|
949
|
-
expect(ingested).toBe(2);
|
|
950
|
-
expect(harness.insertedBatches[0]!).toHaveLength(ingested);
|
|
951
|
-
|
|
952
|
-
expect(onlyUpdate(harness)["lastPollResult"]).toEqual(
|
|
953
|
-
expect.objectContaining({
|
|
954
|
-
fetchedCount: 3,
|
|
955
|
-
ingestedCount: 2,
|
|
956
|
-
rejectedCount: 1,
|
|
957
|
-
}),
|
|
958
|
-
);
|
|
959
|
-
});
|
|
960
|
-
|
|
961
|
-
test("a multi-alert batch is written in a single insert", async () => {
|
|
962
|
-
const harness: PollHarness = stubPollPath();
|
|
963
|
-
|
|
964
|
-
const { client } = makeStubClient(
|
|
965
|
-
stubbedFetchResult([alertOne(), alertTwo()]),
|
|
966
|
-
);
|
|
967
|
-
|
|
968
|
-
await GoogleSecOpsPoller.pollConnection(makeConnection(), client);
|
|
969
|
-
|
|
970
|
-
expect(harness.insertSpy).toHaveBeenCalledTimes(1);
|
|
971
|
-
expect(harness.insertedBatches).toHaveLength(1);
|
|
972
|
-
expect(harness.insertedBatches[0]!).toHaveLength(2);
|
|
973
|
-
});
|
|
974
|
-
|
|
975
|
-
test("threat intel is stamped on polled alerts before the rows are built", async () => {
|
|
976
|
-
const harness: PollHarness = stubPollPath();
|
|
977
|
-
|
|
978
|
-
const enrichCalls: Array<{
|
|
979
|
-
projectId: ObjectID;
|
|
980
|
-
events: Array<NormalizedSecurityEvent>;
|
|
981
|
-
}> = [];
|
|
982
|
-
|
|
983
|
-
/*
|
|
984
|
-
* Replacing the implementation on the spy that is already installed,
|
|
985
|
-
* rather than spying again — a second spy over the first would restore
|
|
986
|
-
* to the first mock instead of the real method.
|
|
987
|
-
*/
|
|
988
|
-
harness.enricherSpy.mockImplementation(((data: {
|
|
989
|
-
projectId: ObjectID;
|
|
990
|
-
events: Array<NormalizedSecurityEvent>;
|
|
991
|
-
}): Promise<EnrichmentResult> => {
|
|
992
|
-
enrichCalls.push(data);
|
|
993
|
-
|
|
994
|
-
for (const event of data.events) {
|
|
995
|
-
event.attributes["threat.matched"] = "true";
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
return Promise.resolve({
|
|
999
|
-
eventsMatched: data.events.length,
|
|
1000
|
-
valuesLookedUp: 1,
|
|
1001
|
-
});
|
|
1002
|
-
}) as never);
|
|
1003
|
-
|
|
1004
|
-
const { client } = makeStubClient(stubbedFetchResult([alertOne()]));
|
|
1005
|
-
|
|
1006
|
-
await GoogleSecOpsPoller.pollConnection(makeConnection(), client);
|
|
1007
|
-
|
|
1008
|
-
expect(enrichCalls).toHaveLength(1);
|
|
1009
|
-
expect(enrichCalls[0]!.projectId.toString()).toBe(PROJECT_ID.toString());
|
|
1010
|
-
expect(enrichCalls[0]!.events).toHaveLength(1);
|
|
1011
|
-
expect(enrichCalls[0]!.events[0]!.classUid).toBe(
|
|
1012
|
-
DETECTION_FINDING_CLASS_UID,
|
|
1013
|
-
);
|
|
1014
|
-
|
|
1015
|
-
/*
|
|
1016
|
-
* The stamp survives into the row, which is only true if enrichment
|
|
1017
|
-
* runs ahead of buildSecurityEventDbRow — the same seam HTTP ingest
|
|
1018
|
-
* uses, and the reason a stamped key is filterable at all.
|
|
1019
|
-
*/
|
|
1020
|
-
const row: JSONObject = harness.insertedBatches[0]![0]!;
|
|
1021
|
-
const attributes: JSONObject = row["attributes"] as JSONObject;
|
|
1022
|
-
expect(attributes["threat.matched"]).toBe("true");
|
|
1023
|
-
expect(row["attributeKeys"] as Array<string>).toContain("threat.matched");
|
|
1024
|
-
});
|
|
1025
|
-
});
|
|
1026
|
-
|
|
1027
|
-
describe("GoogleSecOpsPoller poll window arithmetic", () => {
|
|
1028
|
-
afterEach(() => {
|
|
1029
|
-
jest.restoreAllMocks();
|
|
1030
|
-
});
|
|
1031
|
-
|
|
1032
|
-
/*
|
|
1033
|
-
* Runs one poll and hands back the window it asked Chronicle for. The
|
|
1034
|
-
* caller installs the stubs once; this only reads.
|
|
1035
|
-
*/
|
|
1036
|
-
async function pollWindow(
|
|
1037
|
-
cursor: string | undefined,
|
|
1038
|
-
): Promise<RecordedWindow> {
|
|
1039
|
-
const connection: GoogleSecOpsConnection = makeConnection();
|
|
1040
|
-
|
|
1041
|
-
if (cursor !== undefined) {
|
|
1042
|
-
connection.cursor = cursor;
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
const { client, windows } = makeStubClient(stubbedFetchResult([]));
|
|
1046
|
-
|
|
1047
|
-
await GoogleSecOpsPoller.pollConnection(connection, client);
|
|
1048
|
-
|
|
1049
|
-
expect(windows).toHaveLength(1);
|
|
1050
|
-
|
|
1051
|
-
return windows[0]!;
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
function durationInMs(window: RecordedWindow): number {
|
|
1055
|
-
return window.endTime.getTime() - window.startTime.getTime();
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
test("an unreadable cursor polls the default 24 hour window, exactly like a first poll", async () => {
|
|
1059
|
-
stubPollPath();
|
|
1060
|
-
/*
|
|
1061
|
-
* One clock for all three polls: the end times below are compared to
|
|
1062
|
-
* the millisecond, and a real clock that ticks between polls made this
|
|
1063
|
-
* comparison depend on how long the poll in between took.
|
|
1064
|
-
*/
|
|
1065
|
-
getJestSpyOn(OneUptimeDate, "getCurrentDate").mockReturnValue(
|
|
1066
|
-
new Date(Date.now()),
|
|
1067
|
-
);
|
|
1068
|
-
|
|
1069
|
-
/*
|
|
1070
|
-
* Derived rather than pasted: a first poll IS the default window and a
|
|
1071
|
-
* week-old cursor IS the maximum catch-up chunk, so the bounds move
|
|
1072
|
-
* with the constants instead of going stale against them. Both are a
|
|
1073
|
-
* day now: the first poll reads 24 hours of CREATED detections because
|
|
1074
|
-
* a 15 minute lookback on a tenant whose rules run hourly returned
|
|
1075
|
-
* nothing and read as a broken connector.
|
|
1076
|
-
*/
|
|
1077
|
-
const firstPoll: RecordedWindow = await pollWindow(undefined);
|
|
1078
|
-
const stale: RecordedWindow = await pollWindow(
|
|
1079
|
-
new Date(Date.now() - 7 * DAY_IN_MS).toISOString(),
|
|
1080
|
-
);
|
|
1081
|
-
const garbage: RecordedWindow = await pollWindow("garbage");
|
|
1082
|
-
|
|
1083
|
-
expect(durationInMs(firstPoll)).toBe(DAY_IN_MS);
|
|
1084
|
-
/*
|
|
1085
|
-
* Review finding alerts-view-budget-pins-cursor-forever (F1): a catch-up
|
|
1086
|
-
* chunk is measured from the cursor, so the stale window is a day of new
|
|
1087
|
-
* time plus the one minute overlap in front of the cursor.
|
|
1088
|
-
*/
|
|
1089
|
-
expect(durationInMs(stale)).toBe(DAY_IN_MS + MINUTE_IN_MS);
|
|
1090
|
-
|
|
1091
|
-
/*
|
|
1092
|
-
* An unreadable cursor means "no usable cursor", which is what a first
|
|
1093
|
-
* poll means: it ends now, rather than a day after wherever the
|
|
1094
|
-
* garbage would have pointed.
|
|
1095
|
-
*/
|
|
1096
|
-
expect(durationInMs(garbage)).toBe(durationInMs(firstPoll));
|
|
1097
|
-
expect(garbage.endTime.getTime()).toBe(firstPoll.endTime.getTime());
|
|
1098
|
-
expect(stale.endTime.getTime()).toBeLessThan(firstPoll.endTime.getTime());
|
|
1099
|
-
});
|
|
1100
|
-
|
|
1101
|
-
test("an unreadable cursor is reported in persisted diagnostics", async () => {
|
|
1102
|
-
const harness: PollHarness = stubPollPath();
|
|
1103
|
-
|
|
1104
|
-
await pollWindow("2026-13-45T99:99:99Z");
|
|
1105
|
-
|
|
1106
|
-
const result: GoogleSecOpsRunResult = onlyUpdate(harness)[
|
|
1107
|
-
"lastPollResult"
|
|
1108
|
-
] as unknown as GoogleSecOpsRunResult;
|
|
1109
|
-
expect(result.warnings.join(" ")).toMatch(/cursor is unreadable/);
|
|
1110
|
-
});
|
|
1111
|
-
|
|
1112
|
-
test("a cursor in the future never produces an inverted time range", async () => {
|
|
1113
|
-
const harness: PollHarness = stubPollPath();
|
|
1114
|
-
|
|
1115
|
-
const firstPoll: RecordedWindow = await pollWindow(undefined);
|
|
1116
|
-
|
|
1117
|
-
// Clock skew on the writer, or a restored backup.
|
|
1118
|
-
const future: RecordedWindow = await pollWindow(
|
|
1119
|
-
new Date(Date.now() + HOUR_IN_MS).toISOString(),
|
|
1120
|
-
);
|
|
1121
|
-
|
|
1122
|
-
expect(future.startTime.getTime()).toBeLessThan(future.endTime.getTime());
|
|
1123
|
-
expect(durationInMs(future)).toBe(durationInMs(firstPoll));
|
|
1124
|
-
|
|
1125
|
-
expect(harness.logs.warn.join(" ")).toMatch(/cursor is in the future/);
|
|
1126
|
-
});
|
|
1127
|
-
|
|
1128
|
-
test("a stale cursor catches up from its original boundary without discarding the gap", async () => {
|
|
1129
|
-
const harness: PollHarness = stubPollPath();
|
|
1130
|
-
const cursor: string = new Date(Date.now() - 7 * DAY_IN_MS).toISOString();
|
|
1131
|
-
const stale: RecordedWindow = await pollWindow(cursor);
|
|
1132
|
-
// F1: a day past the cursor, plus the overlap minute before it.
|
|
1133
|
-
expect(durationInMs(stale)).toBe(DAY_IN_MS + MINUTE_IN_MS);
|
|
1134
|
-
expect(stale.endTime.getTime()).toBe(Date.parse(cursor) + DAY_IN_MS);
|
|
1135
|
-
expect(stale.startTime.getTime()).toBe(Date.parse(cursor) - MINUTE_IN_MS);
|
|
1136
|
-
expect(stale.endTime.getTime()).toBeLessThan(Date.now() - 5 * DAY_IN_MS);
|
|
1137
|
-
const written: JSONObject = onlyUpdate(harness);
|
|
1138
|
-
expect(written["cursor"]).toBe(stale.endTime.toISOString());
|
|
1139
|
-
const result: GoogleSecOpsRunResult = written[
|
|
1140
|
-
"lastPollResult"
|
|
1141
|
-
] as unknown as GoogleSecOpsRunResult;
|
|
1142
|
-
expect(result.warnings.join(" ")).toMatch(/Catching up/);
|
|
1143
|
-
});
|
|
1144
|
-
});
|
|
1145
|
-
|
|
1146
|
-
describe("GoogleSecOpsPoller.pollAllDueConnections scheduling", () => {
|
|
1147
|
-
afterEach(() => {
|
|
1148
|
-
jest.restoreAllMocks();
|
|
1149
|
-
});
|
|
1150
|
-
|
|
1151
|
-
function makeDueConnection(id: string): GoogleSecOpsConnection {
|
|
1152
|
-
const connection: GoogleSecOpsConnection = makeConnection();
|
|
1153
|
-
connection._id = id;
|
|
1154
|
-
return connection;
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
function polledIds(spy: ReturnType<typeof getJestSpyOn>): Array<string> {
|
|
1158
|
-
return spy.mock.calls.map((call: Array<unknown>): string => {
|
|
1159
|
-
return String((call[0] as GoogleSecOpsConnection)._id);
|
|
1160
|
-
});
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
test("an unusable pollIntervalInMinutes is clamped rather than making a connection always due", async () => {
|
|
1164
|
-
stubPollPath();
|
|
1165
|
-
|
|
1166
|
-
const justPolledAt: Date = new Date(Date.now() - 30 * 1000);
|
|
1167
|
-
|
|
1168
|
-
/*
|
|
1169
|
-
* Thirty seconds is the discriminating gap: every clamped interval is
|
|
1170
|
-
* at least a minute, so all three of these are still inside their
|
|
1171
|
-
* window. Unclamped, 0 makes the connection due the instant it was
|
|
1172
|
-
* polled and a negative interval puts its next poll ten minutes in the
|
|
1173
|
-
* past — both would hammer Chronicle every tick.
|
|
1174
|
-
*/
|
|
1175
|
-
const zero: GoogleSecOpsConnection = makeDueConnection(
|
|
1176
|
-
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa1",
|
|
1177
|
-
);
|
|
1178
|
-
zero.pollIntervalInMinutes = 0;
|
|
1179
|
-
zero.lastPolledAt = justPolledAt;
|
|
1180
|
-
|
|
1181
|
-
const negative: GoogleSecOpsConnection = makeDueConnection(
|
|
1182
|
-
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa2",
|
|
1183
|
-
);
|
|
1184
|
-
negative.pollIntervalInMinutes = -10;
|
|
1185
|
-
negative.lastPolledAt = justPolledAt;
|
|
1186
|
-
|
|
1187
|
-
const missing: GoogleSecOpsConnection = makeDueConnection(
|
|
1188
|
-
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa3",
|
|
1189
|
-
);
|
|
1190
|
-
delete missing.pollIntervalInMinutes;
|
|
1191
|
-
missing.lastPolledAt = justPolledAt;
|
|
1192
|
-
|
|
1193
|
-
// The controls: one genuinely overdue, one never polled.
|
|
1194
|
-
const overdue: GoogleSecOpsConnection = makeDueConnection(
|
|
1195
|
-
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa4",
|
|
1196
|
-
);
|
|
1197
|
-
overdue.pollIntervalInMinutes = 5;
|
|
1198
|
-
overdue.lastPolledAt = new Date(Date.now() - 10 * MINUTE_IN_MS);
|
|
1199
|
-
|
|
1200
|
-
const neverPolled: GoogleSecOpsConnection = makeDueConnection(
|
|
1201
|
-
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa5",
|
|
1202
|
-
);
|
|
1203
|
-
delete neverPolled.pollIntervalInMinutes;
|
|
1204
|
-
|
|
1205
|
-
getJestSpyOn(GoogleSecOpsConnectionService, "findBy").mockResolvedValue([
|
|
1206
|
-
zero,
|
|
1207
|
-
negative,
|
|
1208
|
-
missing,
|
|
1209
|
-
overdue,
|
|
1210
|
-
neverPolled,
|
|
1211
|
-
] as never);
|
|
1212
|
-
|
|
1213
|
-
const pollSpy: ReturnType<typeof getJestSpyOn> = getJestSpyOn(
|
|
1214
|
-
GoogleSecOpsPoller,
|
|
1215
|
-
"pollConnection",
|
|
1216
|
-
).mockResolvedValue(0 as never);
|
|
1217
|
-
|
|
1218
|
-
await GoogleSecOpsPoller.pollAllDueConnections();
|
|
1219
|
-
|
|
1220
|
-
expect(polledIds(pollSpy)).toEqual([
|
|
1221
|
-
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa4",
|
|
1222
|
-
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa5",
|
|
1223
|
-
]);
|
|
1224
|
-
});
|
|
1225
|
-
|
|
1226
|
-
test("the ingested count of every polled connection is logged, not dropped", async () => {
|
|
1227
|
-
const harness: PollHarness = stubPollPath();
|
|
1228
|
-
|
|
1229
|
-
getJestSpyOn(GoogleSecOpsConnectionService, "findBy").mockResolvedValue([
|
|
1230
|
-
makeConnection(),
|
|
1231
|
-
] as never);
|
|
1232
|
-
|
|
1233
|
-
getJestSpyOn(GoogleSecOpsPoller, "pollConnection").mockResolvedValue(
|
|
1234
|
-
7 as never,
|
|
1235
|
-
);
|
|
1236
|
-
|
|
1237
|
-
await GoogleSecOpsPoller.pollAllDueConnections();
|
|
1238
|
-
|
|
1239
|
-
/*
|
|
1240
|
-
* The one number that distinguishes "polling healthy but quiet" from
|
|
1241
|
-
* "polling silently broken". pollConnection returned it and the caller
|
|
1242
|
-
* used to throw it away.
|
|
1243
|
-
*/
|
|
1244
|
-
const reported: Array<number> = linesAboutConnection(harness.logs.info)
|
|
1245
|
-
.map((line: string): number => {
|
|
1246
|
-
const match: RegExpMatchArray | null = line.match(/ingested (\d+)/);
|
|
1247
|
-
return match ? Number(match[1]) : -1;
|
|
1248
|
-
})
|
|
1249
|
-
.filter((count: number): boolean => {
|
|
1250
|
-
return count >= 0;
|
|
1251
|
-
});
|
|
1252
|
-
|
|
1253
|
-
expect(reported).toEqual([7]);
|
|
1254
|
-
});
|
|
1255
|
-
|
|
1256
|
-
test("only enabled connections are loaded, with every field the poll needs", async () => {
|
|
1257
|
-
stubPollPath();
|
|
1258
|
-
|
|
1259
|
-
const findBySpy: ReturnType<typeof getJestSpyOn> = getJestSpyOn(
|
|
1260
|
-
GoogleSecOpsConnectionService,
|
|
1261
|
-
"findBy",
|
|
1262
|
-
).mockResolvedValue([] as never);
|
|
1263
|
-
|
|
1264
|
-
await GoogleSecOpsPoller.pollAllDueConnections();
|
|
1265
|
-
|
|
1266
|
-
expect(findBySpy).toHaveBeenCalledTimes(1);
|
|
1267
|
-
|
|
1268
|
-
const args: JSONObject = findBySpy.mock.calls[0]![0] as JSONObject;
|
|
1269
|
-
|
|
1270
|
-
expect(args["query"]).toEqual({ isEnabled: true });
|
|
1271
|
-
expect(args["skip"]).toBe(0);
|
|
1272
|
-
expect(args["limit"]).toBe(LIMIT_MAX);
|
|
1273
|
-
expect(args["props"]).toEqual({ isRoot: true });
|
|
1274
|
-
|
|
1275
|
-
/*
|
|
1276
|
-
* Every column pollConnection reads. A field dropped here fails the
|
|
1277
|
-
* connection's own guard at poll time, which reads as a broken
|
|
1278
|
-
* credential rather than a missing select.
|
|
1279
|
-
*/
|
|
1280
|
-
const select: JSONObject = args["select"] as JSONObject;
|
|
1281
|
-
|
|
1282
|
-
for (const field of [
|
|
1283
|
-
"_id",
|
|
1284
|
-
"projectId",
|
|
1285
|
-
"region",
|
|
1286
|
-
"instanceResourceName",
|
|
1287
|
-
"serviceAccountJson",
|
|
1288
|
-
"pollIntervalInMinutes",
|
|
1289
|
-
"lastPolledAt",
|
|
1290
|
-
"cursor",
|
|
1291
|
-
// F1: the previous result carries the next catch-up chunk length.
|
|
1292
|
-
"lastPollResult",
|
|
1293
|
-
]) {
|
|
1294
|
-
expect(select[field]).toBe(true);
|
|
1295
|
-
}
|
|
1296
|
-
});
|
|
1297
|
-
});
|