@oneuptime/common 13.0.0 → 13.0.3
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/RumSession.ts +34 -0
- package/Models/DatabaseModels/Alert.ts +55 -0
- package/Models/DatabaseModels/AlertEpisodeLabelRule.ts +2 -2
- package/Models/DatabaseModels/AlertEpisodeOnCallRule.ts +2 -2
- package/Models/DatabaseModels/AlertEpisodeOwnerRule.ts +2 -2
- package/Models/DatabaseModels/AlertEpisodePrivacyRule.ts +2 -2
- package/Models/DatabaseModels/AlertGroupingRule.ts +2 -2
- package/Models/DatabaseModels/AlertLabelRule.ts +2 -2
- package/Models/DatabaseModels/AlertOnCallRule.ts +2 -2
- package/Models/DatabaseModels/AlertOwnerRule.ts +2 -2
- package/Models/DatabaseModels/AlertPrivacyRule.ts +2 -2
- package/Models/DatabaseModels/AlertReminderRule.ts +6 -4
- package/Models/DatabaseModels/AutoRemediationRule.ts +2 -2
- package/Models/DatabaseModels/CephClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/CephClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/CloudResource.ts +45 -7
- package/Models/DatabaseModels/CloudResourceLabelRule.ts +2 -2
- package/Models/DatabaseModels/CloudResourceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/CodeRepository.ts +85 -0
- package/Models/DatabaseModels/DashboardLabelRule.ts +2 -2
- package/Models/DatabaseModels/DashboardOwnerRule.ts +2 -2
- package/Models/DatabaseModels/DatabaseBaseModel/RelationOnlyRuleBaseModel.ts +11 -0
- package/Models/DatabaseModels/DatabaseBaseModel/RuleBaseModel.ts +44 -0
- package/Models/DatabaseModels/DockerHostLabelRule.ts +2 -2
- package/Models/DatabaseModels/DockerHostOwnerRule.ts +2 -2
- package/Models/DatabaseModels/DockerSwarmClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/DockerSwarmClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/GoogleSecOpsConnection.ts +57 -7
- package/Models/DatabaseModels/GoogleSecOpsConnectionRun.ts +263 -0
- package/Models/DatabaseModels/HostLabelRule.ts +2 -2
- package/Models/DatabaseModels/HostOwnerRule.ts +2 -2
- package/Models/DatabaseModels/Incident.ts +55 -0
- package/Models/DatabaseModels/IncidentEpisodeLabelRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodeOnCallRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodeOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodePrivacyRule.ts +2 -2
- package/Models/DatabaseModels/IncidentGroupingRule.ts +2 -2
- package/Models/DatabaseModels/IncidentLabelRule.ts +2 -2
- package/Models/DatabaseModels/IncidentOnCallRule.ts +2 -2
- package/Models/DatabaseModels/IncidentOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncidentPrivacyRule.ts +2 -2
- package/Models/DatabaseModels/IncidentReminderRule.ts +6 -4
- package/Models/DatabaseModels/IncidentSlaRule.ts +2 -2
- package/Models/DatabaseModels/IncomingCallPolicy.ts +3 -4
- package/Models/DatabaseModels/IncomingCallPolicyLabelRule.ts +2 -2
- package/Models/DatabaseModels/IncomingCallPolicyOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.ts +254 -0
- package/Models/DatabaseModels/Index.ts +18 -0
- package/Models/DatabaseModels/IoTFleetLabelRule.ts +2 -2
- package/Models/DatabaseModels/IoTFleetOwnerRule.ts +2 -2
- package/Models/DatabaseModels/KubernetesClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/KubernetesClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/MonitorLabelRule.ts +2 -2
- package/Models/DatabaseModels/MonitorOwnerRule.ts +2 -2
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +2 -2
- package/Models/DatabaseModels/NetworkDeviceLabelRule.ts +2 -2
- package/Models/DatabaseModels/NetworkDeviceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyLabelRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyOwnerRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleLabelRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerRule.ts +2 -2
- package/Models/DatabaseModels/PodmanHostLabelRule.ts +2 -2
- package/Models/DatabaseModels/PodmanHostOwnerRule.ts +2 -2
- package/Models/DatabaseModels/ProxmoxClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/ProxmoxClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/RumApplicationLabelRule.ts +2 -2
- package/Models/DatabaseModels/RumApplicationOwnerRule.ts +2 -2
- package/Models/DatabaseModels/RunbookLabelRule.ts +2 -2
- package/Models/DatabaseModels/RunbookOwnerRule.ts +2 -2
- package/Models/DatabaseModels/RunbookRule.ts +2 -2
- package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
- package/Models/DatabaseModels/ScheduledMaintenanceLabelRule.ts +2 -2
- package/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/ScheduledMaintenanceReminderRule.ts +6 -4
- package/Models/DatabaseModels/ServerlessFunctionLabelRule.ts +2 -2
- package/Models/DatabaseModels/ServerlessFunctionOwnerRule.ts +2 -2
- package/Models/DatabaseModels/ServiceLabelRule.ts +2 -2
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +283 -4
- package/Models/DatabaseModels/ServiceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/StatusPageLabelRule.ts +2 -2
- package/Models/DatabaseModels/StatusPageMonitorRule.ts +2 -2
- package/Models/DatabaseModels/StatusPageOwnerRule.ts +2 -2
- package/Models/DatabaseModels/User.ts +51 -2
- package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +43 -2
- package/Models/DatabaseModels/UserWebAuthn.ts +17 -0
- package/Models/DatabaseModels/VMwareResource.ts +1149 -0
- package/Models/DatabaseModels/VMwareVCenter.ts +1122 -0
- package/Models/DatabaseModels/VMwareVCenterFeed.ts +625 -0
- package/Models/DatabaseModels/VMwareVCenterLabelRule.ts +514 -0
- package/Models/DatabaseModels/VMwareVCenterOwnerRule.ts +596 -0
- package/Models/DatabaseModels/VMwareVCenterOwnerTeam.ts +485 -0
- package/Models/DatabaseModels/VMwareVCenterOwnerUser.ts +484 -0
- package/Models/DatabaseModels/WorkflowLabelRule.ts +2 -2
- package/Models/DatabaseModels/WorkflowOwnerRule.ts +2 -2
- package/Models/DatabaseModels/WorkflowVariable.ts +22 -1
- package/Server/API/AIAgentDataAPI.ts +79 -4
- package/Server/API/AIAgentGitHubAPI.ts +523 -0
- package/Server/API/AIChatAPI.ts +20 -1
- package/Server/API/BillingAPI.ts +33 -0
- package/Server/API/DashboardAPI.ts +10 -0
- package/Server/API/GitHubAPI.ts +47 -5
- package/Server/API/GoogleSecOpsConnectionAPI.ts +79 -0
- package/Server/API/TelemetryAPI.ts +323 -2
- package/Server/API/UserWebAuthnAPI.ts +21 -1
- package/Server/API/VMwareResourceAPI.ts +143 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791800000000-SplitWebAuthnChallengeByPurpose.ts +68 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791900000000-AddSeverityAndStateToNotificationEmailRollup.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792000000000-AddVMwareTables.ts +636 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792100000000-AddGitHubCommandSettingsToCodeRepository.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792200000000-AddUserWebAuthnPurpose.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792300000000-AddGoogleSecOpsDiagnostics.ts +83 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792400000000-AddSloBurnRateRuleIncidents.ts +111 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792500000000-AddConfigurableRuleCriteria.ts +644 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792600000000-AddIncomingCallPolicyPhoneNumbers.ts +72 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +18 -0
- package/Server/Middleware/IdentityRateLimit.ts +101 -0
- package/Server/Middleware/MultipartFormData.ts +46 -21
- package/Server/Services/AIRunService.ts +13 -0
- package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +21 -0
- package/Server/Services/AlertEpisodeOnCallRuleEngineService.ts +21 -0
- package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +21 -0
- package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +21 -0
- package/Server/Services/AlertGroupingEngineService.ts +27 -0
- package/Server/Services/AlertLabelRuleEngineService.ts +27 -0
- package/Server/Services/AlertOnCallRuleEngineService.ts +27 -0
- package/Server/Services/AlertOwnerRuleEngineService.ts +27 -0
- package/Server/Services/AlertPrivacyRuleEngineService.ts +27 -0
- package/Server/Services/AlertReminderRuleService.ts +65 -33
- package/Server/Services/AutoRemediationRuleEngineService.ts +90 -8
- package/Server/Services/BillingPaymentMethodService.ts +99 -28
- package/Server/Services/BillingService.ts +287 -20
- package/Server/Services/CephClusterLabelRuleEngineService.ts +20 -0
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +20 -0
- package/Server/Services/CloudResourceInstanceService.ts +70 -0
- package/Server/Services/CloudResourceLabelRuleEngineService.ts +20 -0
- package/Server/Services/CloudResourceOwnerRuleEngineService.ts +20 -0
- package/Server/Services/DashboardLabelRuleEngineService.ts +20 -0
- package/Server/Services/DashboardOwnerRuleEngineService.ts +20 -0
- package/Server/Services/DatabaseService.ts +409 -6
- package/Server/Services/DockerHostLabelRuleEngineService.ts +20 -0
- package/Server/Services/DockerHostOwnerRuleEngineService.ts +20 -0
- package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +23 -0
- package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +23 -0
- package/Server/Services/ExceptionAggregationService.ts +1 -0
- package/Server/Services/GoogleSecOpsConnectionRunService.ts +10 -0
- package/Server/Services/GoogleSecOpsConnectionService.ts +12 -0
- package/Server/Services/HostLabelRuleEngineService.ts +13 -0
- package/Server/Services/HostOwnerRuleEngineService.ts +13 -0
- package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +21 -0
- package/Server/Services/IncidentEpisodeOnCallRuleEngineService.ts +21 -0
- package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +21 -0
- package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +21 -0
- package/Server/Services/IncidentGroupingEngineService.ts +64 -13
- package/Server/Services/IncidentLabelRuleEngineService.ts +64 -9
- package/Server/Services/IncidentOnCallRuleEngineService.ts +64 -10
- package/Server/Services/IncidentOwnerRuleEngineService.ts +64 -10
- package/Server/Services/IncidentPrivacyRuleEngineService.ts +64 -10
- package/Server/Services/IncidentReminderRuleService.ts +66 -34
- package/Server/Services/IncidentSlaRuleService.ts +55 -12
- package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +20 -0
- package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +20 -0
- package/Server/Services/IncomingCallPolicyPhoneNumberService.ts +184 -0
- package/Server/Services/IncomingCallPolicyService.ts +276 -5
- package/Server/Services/Index.ts +18 -0
- package/Server/Services/IoTFleetLabelRuleEngineService.ts +20 -0
- package/Server/Services/IoTFleetOwnerRuleEngineService.ts +20 -0
- package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +23 -0
- package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +23 -0
- package/Server/Services/LabelService.ts +50 -7
- package/Server/Services/LogAggregationService.ts +1 -0
- package/Server/Services/MetricAggregationService.ts +1 -0
- package/Server/Services/MobilePasskeyLoginService.ts +216 -0
- package/Server/Services/MonitorLabelRuleEngineService.ts +20 -0
- package/Server/Services/MonitorOwnerRuleEngineService.ts +20 -0
- package/Server/Services/MonitorService.ts +51 -1
- package/Server/Services/MonitorTemplateService.ts +91 -29
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +134 -1
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +269 -3
- package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +26 -0
- package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +25 -0
- package/Server/Services/NetworkDeviceService.ts +2 -0
- package/Server/Services/NetworkSiteAssignmentRuleService.ts +90 -1
- package/Server/Services/NetworkSiteService.ts +242 -29
- package/Server/Services/NetworkSiteTypeService.ts +177 -77
- package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +20 -0
- package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +20 -0
- package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +22 -0
- package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +22 -0
- package/Server/Services/OpenTelemetryIngestService.ts +17 -0
- package/Server/Services/PayAsYouGoBillingService.ts +446 -0
- package/Server/Services/PodmanHostLabelRuleEngineService.ts +20 -0
- package/Server/Services/PodmanHostOwnerRuleEngineService.ts +20 -0
- package/Server/Services/ProjectCallSMSConfigService.ts +156 -7
- package/Server/Services/ProjectService.ts +46 -2
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +25 -0
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +25 -0
- package/Server/Services/RumApplicationLabelRuleEngineService.ts +22 -0
- package/Server/Services/RumApplicationOwnerRuleEngineService.ts +22 -0
- package/Server/Services/RunbookLabelRuleEngineService.ts +20 -0
- package/Server/Services/RunbookOwnerRuleEngineService.ts +20 -0
- package/Server/Services/RunbookRuleEngineService.ts +18 -1
- package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +62 -10
- package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +62 -11
- package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +48 -18
- package/Server/Services/ServerlessFunctionInstanceService.ts +71 -0
- package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +25 -0
- package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +25 -0
- package/Server/Services/ServiceLabelRuleEngineService.ts +20 -0
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +675 -12
- package/Server/Services/ServiceLevelObjectiveService.ts +55 -13
- package/Server/Services/ServiceOwnerRuleEngineService.ts +20 -0
- package/Server/Services/StatusPageLabelRuleEngineService.ts +20 -0
- package/Server/Services/StatusPageMonitorRuleEngineService.ts +31 -2
- package/Server/Services/StatusPageMonitorRuleService.ts +34 -1
- package/Server/Services/StatusPageOwnerRuleEngineService.ts +20 -0
- package/Server/Services/TeamMemberService.ts +96 -36
- package/Server/Services/TelemetryIngestionKeyService.ts +80 -10
- package/Server/Services/TelemetryUsageBillingService.ts +95 -5
- package/Server/Services/TraceAggregationService.ts +5 -4
- package/Server/Services/UserService.ts +23 -50
- package/Server/Services/UserWebAuthnService.ts +592 -133
- package/Server/Services/VMwareResourceService.ts +648 -0
- package/Server/Services/VMwareVCenterFeedService.ts +99 -0
- package/Server/Services/VMwareVCenterLabelRuleEngineService.ts +265 -0
- package/Server/Services/VMwareVCenterLabelRuleService.ts +14 -0
- package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +277 -0
- package/Server/Services/VMwareVCenterOwnerRuleService.ts +14 -0
- package/Server/Services/VMwareVCenterOwnerTeamService.ts +139 -0
- package/Server/Services/VMwareVCenterOwnerUserService.ts +133 -0
- package/Server/Services/VMwareVCenterService.ts +629 -0
- package/Server/Services/WorkflowLabelRuleEngineService.ts +20 -0
- package/Server/Services/WorkflowOwnerRuleEngineService.ts +20 -0
- package/Server/Services/WorkflowVariableService.ts +203 -0
- package/Server/Static/Brand/README.md +10 -5
- package/Server/Static/Brand/favicons/oneuptime-up-v1.svg +8 -0
- package/Server/Types/Billing/MeteredPlan/ActiveMonitoringMeteredPlan.ts +17 -0
- package/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.ts +31 -1
- package/Server/Types/Database/QueryHelper.ts +88 -0
- package/Server/Utils/AI/Toolbox/SloTools.ts +19 -2
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +7 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubAgentTaskTrigger.ts +341 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubCommandAuthorizer.ts +274 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubCommandParser.ts +375 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubConversation.ts +846 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubReplyComposer.ts +360 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubRunReply.ts +421 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.ts +140 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubWebhookHandler.ts +906 -0
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +143 -0
- package/Server/Utils/DataSource/EgressGuard.ts +160 -15
- package/Server/Utils/Database/TruncateColumnValue.ts +1 -1
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +2 -0
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +33 -0
- package/Server/Utils/EmailRollup/EmailRollupWriter.ts +44 -0
- package/Server/Utils/IncomingCallPhoneNumber.ts +29 -16
- package/Server/Utils/LogRedaction.ts +2 -1
- package/Server/Utils/Monitor/MonitorAlert.ts +1 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +302 -3
- package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +26 -4
- package/Server/Utils/Monitor/MonitorResourceContext.ts +5 -3
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +14 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +26 -0
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +28 -5
- package/Server/Utils/Profiling.ts +13 -1
- package/Server/Utils/ResourceFeed/ResourceFeedUtil.ts +3 -3
- package/Server/Utils/Rules/MonitorRuleCriteriaCache.ts +38 -0
- package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +14 -9
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +116 -84
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +594 -195
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +466 -0
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +498 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +5 -0
- package/Server/Utils/Telemetry/ResourceHeartbeat.ts +2 -1
- package/Server/Utils/Telemetry/TelemetryEntity.ts +181 -1
- package/Server/Utils/Telemetry/VMwareSnapshotScan.ts +1352 -0
- package/Server/Utils/Telemetry.ts +3 -1
- package/Server/Utils/VendorAssets.ts +3 -0
- package/Tests/App/Accounts/LoginPasskey.test.tsx +529 -0
- package/Tests/App/Accounts/MobilePasskey.test.tsx +620 -0
- package/Tests/App/Accounts/PasswordRequirements.test.tsx +254 -0
- package/Tests/App/Accounts/RegisterPassword.test.tsx +553 -0
- package/Tests/App/Dashboard/AIInsightViewTriage.test.tsx +348 -0
- package/Tests/App/Dashboard/ArchiveResourceCard.test.tsx +476 -0
- package/Tests/App/Dashboard/AskAiAvailability.test.ts +224 -0
- package/Tests/App/Dashboard/AskAiDisabled.test.tsx +432 -0
- package/Tests/App/Dashboard/BackupCodes.test.tsx +414 -0
- package/Tests/App/Dashboard/BillingPaidUsageFlow.test.tsx +530 -0
- package/Tests/App/Dashboard/BillingPaymentMethodForm.test.tsx +195 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +199 -0
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +223 -0
- package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +215 -0
- package/Tests/App/Dashboard/CloudFleetSummary.test.ts +183 -0
- package/Tests/App/Dashboard/CloudFleetSummaryComponent.test.tsx +248 -0
- package/Tests/App/Dashboard/CloudResourceTelemetryScope.test.ts +215 -0
- package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +3 -0
- package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +441 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +883 -0
- package/Tests/App/Dashboard/DashboardPersistentSideMenuLayouts.test.tsx +702 -0
- package/Tests/App/Dashboard/DashboardToolbarPopupLayering.test.tsx +566 -0
- package/Tests/App/Dashboard/DiscoveryScanLivePage.test.tsx +376 -0
- package/Tests/App/Dashboard/DiscoveryScanLiveUpdates.test.tsx +642 -0
- package/Tests/App/Dashboard/DiscoveryScanProgress.test.tsx +267 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +69 -231
- package/Tests/App/Dashboard/ExceptionsLandingRedirect.test.tsx +63 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +150 -0
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +423 -0
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +724 -0
- package/Tests/App/Dashboard/InventoryItemSideMenu.test.tsx +155 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +11 -0
- package/Tests/App/Dashboard/MonitorTemplateSyncFields.test.tsx +539 -0
- package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +24 -7
- package/Tests/App/Dashboard/OnCallOverridePresentation.test.ts +496 -0
- package/Tests/App/Dashboard/OnCallScheduleOverrideClarity.test.tsx +677 -0
- package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +31 -3
- package/Tests/App/Dashboard/PaidUsageConsent.test.tsx +180 -0
- package/Tests/App/Dashboard/PasskeySettings.test.tsx +1364 -0
- package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +176 -275
- package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +380 -233
- package/Tests/App/Dashboard/ProductMenuBreadcrumbs.test.tsx +3 -23
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +347 -0
- package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +263 -0
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +414 -17
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +138 -0
- package/Tests/App/Dashboard/SloDashboardTemplateWidgets.test.tsx +940 -0
- package/Tests/App/Dashboard/TelemetryIngestionKeyEdit.test.tsx +378 -0
- package/Tests/App/Dashboard/TelemetryIngestionKeyForm.test.tsx +735 -0
- package/Tests/App/Dashboard/TwoFactorStatus.test.tsx +427 -0
- package/Tests/App/Dashboard/VMwareDashboardWidgets.test.ts +573 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +2 -0
- package/Tests/App/Dashboard/WorkflowVariablesTable.test.tsx +768 -0
- package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +13 -3
- package/Tests/App/StatusPage/StatusPageOverviewLiveAndSearch.test.tsx +532 -40
- package/Tests/App/StatusPage/StatusPageResourceSearchBox.test.tsx +19 -2
- package/Tests/Fixtures/MobilePasskeyUser.json +8 -0
- package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +127 -4
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +5 -4
- package/Tests/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.test.ts +362 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +25 -6
- package/Tests/Models/DatabaseModels/RuleBaseModel.test.ts +69 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +181 -0
- package/Tests/Models/DatabaseModels/VMwareModels.test.ts +1134 -0
- package/Tests/Models/RunnerVersionLabel.test.ts +4 -2
- package/Tests/Server/API/AIChatProvidersAIEnabled.test.ts +259 -0
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +31 -2
- package/Tests/Server/API/BillingPayAsYouGoStatus.test.ts +116 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +29 -1
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +13 -2
- package/Tests/Server/API/GitHubWebhookSignature.test.ts +368 -0
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +248 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +1303 -145
- package/Tests/Server/API/UserTwoFactorSelfService.test.ts +407 -0
- package/Tests/Server/API/UserWebAuthnAuthenticationOptionsRoute.test.ts +330 -0
- package/Tests/Server/API/UserWebAuthnPasskeyAPI.test.ts +172 -0
- package/Tests/Server/API/VMwareResourceAPI.test.ts +546 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +611 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupMetadataMigration.test.ts +85 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +34 -3
- package/Tests/Server/Middleware/MultipartFormData.test.ts +61 -3
- package/Tests/Server/Middleware/PasskeyRateLimit.test.ts +141 -0
- package/Tests/Server/Middleware/TelemetryIngestionDisabled.test.ts +211 -0
- package/Tests/Server/Services/AlertIncidentRuleCriteriaEngineServices.test.ts +651 -0
- package/Tests/Server/Services/AutoImportRuleRearmRecentScans.test.ts +343 -0
- package/Tests/Server/Services/AutoImportRuleWriteRearmsScans.test.ts +381 -0
- package/Tests/Server/Services/AutoRemediationRuleEngineService.test.ts +79 -0
- package/Tests/Server/Services/BillingPaymentMethodServiceSync.test.ts +175 -0
- package/Tests/Server/Services/BillingService.test.ts +26 -11
- package/Tests/Server/Services/BillingServiceMeteredPaymentAuthorization.test.ts +245 -0
- package/Tests/Server/Services/BillingServicePaymentMethodReads.test.ts +362 -0
- package/Tests/Server/Services/CloudResourceInstanceStalePrune.test.ts +188 -0
- package/Tests/Server/Services/DatabaseServiceRelationOnlyRuleRollout.test.ts +330 -0
- package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +522 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +16 -2
- package/Tests/Server/Services/GoogleSecOpsDiagnosticsModel.test.ts +153 -0
- package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +13 -0
- package/Tests/Server/Services/IncidentSlaRuleCriteriaCorrelation.test.ts +99 -0
- package/Tests/Server/Services/IncomingCallPolicyPhoneNumberService.test.ts +1540 -0
- package/Tests/Server/Services/InventoryItemPromotionGate.test.ts +5 -0
- package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +36 -0
- package/Tests/Server/Services/InventoryUpsertTruncationGuard.test.ts +151 -0
- package/Tests/Server/Services/MobilePasskeyLoginIntegration.test.ts +231 -0
- package/Tests/Server/Services/MobilePasskeyLoginService.test.ts +315 -0
- package/Tests/Server/Services/MonitorPayAsYouGoBilling.test.ts +302 -0
- package/Tests/Server/Services/MonitorTemplateServiceFieldSync.test.ts +994 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +22 -0
- package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +179 -2
- package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +170 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +559 -53
- package/Tests/Server/Services/NetworkSiteTypeService.test.ts +122 -55
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +7 -1
- package/Tests/Server/Services/PayAsYouGoBillingService.test.ts +857 -0
- package/Tests/Server/Services/PayAsYouGoStripeRateLimitBudget.test.ts +379 -0
- package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +99 -1
- package/Tests/Server/Services/ProjectServiceSubscriptionSeats.test.ts +134 -0
- package/Tests/Server/Services/ReminderRuleCriteria.test.ts +173 -0
- package/Tests/Server/Services/ResourceFeedServices.test.ts +3 -2
- package/Tests/Server/Services/ResourceRuleCriteriaEngineServices.test.ts +170 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +32 -6
- package/Tests/Server/Services/ScheduledMaintenanceRuleCriteriaCorrelation.test.ts +154 -0
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +363 -175
- package/Tests/Server/Services/ServerlessFunctionInstanceStalePrune.test.ts +200 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +2450 -470
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +464 -121
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +281 -0
- package/Tests/Server/Services/StatusPageMonitorRuleEngineService.test.ts +132 -0
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +159 -14
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +3 -0
- package/Tests/Server/Services/TeamMemberBillingSeatSync.test.ts +762 -0
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +3 -0
- package/Tests/Server/Services/TelemetryIngestionKeyPolicyResolution.test.ts +72 -0
- package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +17 -4
- package/Tests/Server/Services/TelemetryPayAsYouGoBilling.test.ts +355 -0
- package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +41 -4
- package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +6 -8
- package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +37 -0
- package/Tests/Server/Services/UserTwoFactorAuthAdmin.test.ts +203 -34
- package/Tests/Server/Services/UserWebAuthnPasskeyIntegration.test.ts +401 -0
- package/Tests/Server/Services/UserWebAuthnPasskeyService.test.ts +769 -0
- package/Tests/Server/Services/UserWebAuthnUserVerification.test.ts +649 -0
- package/Tests/Server/Services/VMwareResourceService.test.ts +945 -0
- package/Tests/Server/Services/VMwareVCenterService.test.ts +722 -0
- package/Tests/Server/Services/WorkflowVariableRenameUniqueness.test.ts +842 -0
- package/Tests/Server/TestingUtils/PasskeyHttpIntegration.ts +102 -0
- package/Tests/Server/TestingUtils/SecurityKey.ts +464 -0
- package/Tests/Server/TestingUtils/WebAuthnServiceMocks.ts +60 -0
- package/Tests/Server/Types/Billing/PayAsYouGoMeteredAuthorization.test.ts +573 -0
- package/Tests/Server/Types/Database/Permissions/ProjectCustomerSupportAccessColumn.test.ts +261 -0
- package/Tests/Server/Types/Database/Permissions/WorkflowVariableColumnPermission.test.ts +95 -0
- package/Tests/Server/Types/Database/QueryHelperJsonArrayObjects.test.ts +128 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +190 -1
- package/Tests/Server/Utils/AI/Toolbox/AIToolbox.test.ts +461 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +25 -0
- package/Tests/Server/Utils/Billing/BillingFailureNoticeThrottle.test.ts +359 -0
- package/Tests/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.test.ts +318 -0
- package/Tests/Server/Utils/CodeRepository/GitHubAgentTaskTrigger.test.ts +2101 -0
- package/Tests/Server/Utils/CodeRepository/GitHubCommandAuthorizer.test.ts +883 -0
- package/Tests/Server/Utils/CodeRepository/GitHubCommandParser.test.ts +1474 -0
- package/Tests/Server/Utils/CodeRepository/GitHubConversation.test.ts +1526 -0
- package/Tests/Server/Utils/CodeRepository/GitHubReplyComposer.test.ts +1389 -0
- package/Tests/Server/Utils/CodeRepository/GitHubRunReply.test.ts +1707 -0
- package/Tests/Server/Utils/CodeRepository/GitHubWebhookHandler.test.ts +2202 -0
- package/Tests/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.test.ts +220 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +345 -0
- package/Tests/Server/Utils/Dashboard/SloTemplatePublicDashboard.test.ts +1043 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +896 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupMetadataIntegration.test.ts +246 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +299 -1
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +6 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +185 -0
- package/Tests/Server/Utils/Execute.test.ts +302 -0
- package/Tests/Server/Utils/GracefulShutdown.test.ts +565 -0
- package/Tests/Server/Utils/IncomingCallPhoneNumber.test.ts +36 -20
- package/Tests/Server/Utils/LogRedaction.test.ts +33 -0
- package/Tests/Server/Utils/Monitor/CapturedMetricAttributeUtil.test.ts +2 -1
- package/Tests/Server/Utils/Monitor/Criteria/TelemetryStepMetricAlias.test.ts +10 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +66 -1
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +362 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +60 -1
- package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +60 -0
- package/Tests/Server/Utils/Monitor/MonitorRootCauseTargetResolution.test.ts +423 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +6 -0
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +46 -2
- package/Tests/Server/Utils/Monitor/SloTemplateMetricEmitterContract.test.ts +750 -0
- package/Tests/Server/Utils/ProductAnalytics.test.ts +404 -0
- package/Tests/Server/Utils/Profiling.test.ts +366 -0
- package/Tests/Server/Utils/Rules/MonitorRuleCriteriaCache.test.ts +99 -0
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +81 -45
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +711 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClickhouseIntegration.test.ts +223 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +69 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +838 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsErrorHandling.test.ts +241 -28
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsHttpIntegration.test.ts +651 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +11 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +13 -12
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +112 -127
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsRequestContract.test.ts +12 -18
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsResponseParsing.test.ts +43 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +558 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +580 -0
- package/Tests/Server/Utils/Telemetry/VMwareSnapshotScan.test.ts +1748 -0
- package/Tests/Server/Utils/VendorAssets.test.ts +17 -0
- package/Tests/Types/Cloud/CloudPlatform.test.ts +574 -0
- package/Tests/Types/Dashboard/DashboardTemplateEditorialInvariants.test.ts +659 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +97 -0
- package/Tests/Types/Dashboard/SloDashboardTemplate.test.ts +1179 -0
- package/Tests/Types/Database/AccessControl/OwnedThrough.test.ts +136 -0
- package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +2 -0
- package/Tests/Types/Monitor/MonitorCriteriaMetricVariables.test.ts +9 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorStepInfraMonitorUtils.test.ts +53 -8
- package/Tests/Types/Monitor/MonitorStepInfrastructureMonitors.test.ts +97 -0
- package/Tests/Types/Monitor/MonitorStepMetricViewConfigUtil.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorStepTemplateSyncFields.test.ts +107 -0
- package/Tests/Types/Monitor/MonitorTemplateSyncField.test.ts +172 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +2 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationAlertDebuggability.test.ts +1 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +9 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
- package/Tests/Types/Monitor/SeriesContext/SeriesDebugHints.test.ts +131 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +10 -0
- package/Tests/Types/Monitor/VMwareAlertTemplates.test.ts +1608 -0
- package/Tests/Types/Monitor/VMwareMetricCatalog.test.ts +488 -0
- package/Tests/Types/OnCallDutyPolicy/OverrideProvenance.test.ts +295 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +180 -1
- package/Tests/Types/Runner/RunnerLiveStatus.test.ts +2 -2
- package/Tests/Types/SignupPassword.test.ts +205 -0
- package/Tests/Types/StatusPage/StatusPageLanguage.test.ts +44 -0
- package/Tests/Types/SupportedLanguages.test.ts +119 -0
- package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +19 -0
- package/Tests/UI/ColorPickerBuild.test.ts +86 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +13 -6
- package/Tests/UI/Components/Alert.test.tsx +532 -93
- package/Tests/UI/Components/Breadcrumbs.test.tsx +32 -0
- package/Tests/UI/Components/Feed.test.tsx +241 -0
- package/Tests/UI/Components/Forms/BasicFormStepNavigation.test.tsx +368 -0
- package/Tests/UI/Components/Forms/FormSummary.test.tsx +454 -0
- package/Tests/UI/Components/Forms/ModelFormJsonColumns.test.tsx +290 -0
- package/Tests/UI/Components/Forms/ModelFormPreservesUserInput.test.tsx +937 -0
- package/Tests/UI/Components/Forms/ModelFormRuleCriteria.test.tsx +331 -0
- package/Tests/UI/Components/Forms/ModelFormWriteOnlyColumnSelect.test.tsx +230 -0
- package/Tests/UI/Components/Forms/ValidationFormSteps.test.ts +3 -4
- package/Tests/UI/Components/IconOpticalSize.test.tsx +79 -31
- package/Tests/UI/Components/LabelRuleImportExport.test.tsx +907 -0
- package/Tests/UI/Components/ModelTable/ModelTableCreateAfterEdit.test.tsx +514 -0
- package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +6 -6
- package/Tests/UI/Components/MonitorGraphs/Uptime.test.tsx +301 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +2 -1
- package/Tests/UI/Components/NavBar.test.tsx +91 -2
- package/Tests/UI/Components/PencilButton.test.tsx +211 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaBuilder.test.tsx +510 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +350 -0
- package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +50 -0
- package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +329 -0
- package/Tests/UI/Components/TooltipLazyContent.test.tsx +373 -0
- package/Tests/UI/Components/useFeedItems.test.tsx +107 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsMessagingEndpointGuidance.test.tsx +43 -12
- package/Tests/UI/ReactDomBuild.test.ts +104 -0
- package/Tests/UI/ReactRouterSingletonBuild.test.ts +11 -1
- package/Tests/UI/Rum/ChunkLoader.test.ts +401 -0
- package/Tests/UI/Rum/RecordingHealthCard.test.tsx +1 -1
- package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +7 -1
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +2 -0
- package/Tests/UI/Rum/ReplayEngine.test.ts +1069 -5
- package/Tests/UI/Rum/ReplayHeader.test.tsx +579 -2
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +23 -5
- package/Tests/UI/Rum/ReplayRail.test.tsx +143 -1
- package/Tests/UI/Rum/ReplayRenderBudget.test.tsx +338 -0
- package/Tests/UI/Rum/ReplaySignals.test.ts +179 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +210 -3
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +180 -1
- package/Tests/UI/Rum/ReplayUserSessionsMenu.test.tsx +405 -0
- package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +13 -16
- package/Tests/UI/Rum/SessionReplayFacets.test.tsx +199 -0
- package/Tests/UI/Rum/SessionReplaySearchBar.test.tsx +58 -21
- package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +2 -0
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +717 -4
- package/Tests/UI/Rum/SessionReplayUsersPage.test.tsx +435 -0
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +577 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +149 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +30 -1
- package/Tests/UI/Utils/DashboardStackingLayers.test.ts +197 -0
- package/Tests/UI/Utils/LabelRuleImportExport.test.ts +738 -0
- package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +109 -2
- package/Tests/UI/Utils/Navigation.test.ts +30 -0
- package/Tests/UI/Utils/UseDashboardGridDnd.test.tsx +7 -2
- package/Tests/UI/Utils/UserEmailRegistrationStatus.test.tsx +295 -0
- package/Tests/UI/Utils/WebAuthn.test.ts +265 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentDefaults.test.ts +5 -0
- package/Tests/Utils/Dashboard/Components/DashboardVMwareListComponents.test.ts +548 -0
- package/Tests/Utils/Dashboard/DashboardResourceListSharedArgs.test.ts +17 -3
- package/Tests/Utils/Dashboard/SloTemplateVariableScoping.test.ts +880 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +741 -0
- package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
- package/Tests/Utils/Monitor/MonitorTemplateSyncUtil.test.ts +590 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +93 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +138 -0
- package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +174 -0
- package/Tests/Utils/RequestFailedDetails.test.ts +325 -0
- package/Tests/Utils/Rules/RuleCriteriaMatcher.test.ts +1424 -0
- package/Tests/Utils/Rum/SessionIdentity.test.ts +72 -0
- package/Tests/Utils/Slo/SloBurnRateRuleState.test.ts +374 -28
- package/Tests/Utils/Telemetry/CloudInstanceIdentity.test.ts +255 -0
- package/Tests/Utils/Telemetry/EntityRelationship.test.ts +167 -0
- package/Tests/Utils/Telemetry/OriginAllowList.test.ts +118 -0
- package/Tests/Utils/WebAuthnTestUtil.ts +79 -0
- package/Tests/__mocks__/simplewebauthn.js +33 -4
- package/Types/AI/CodeFixTaskContext.ts +122 -0
- package/Types/AI/CodeFixTaskType.ts +62 -0
- package/Types/Accounts/AccountsLanguage.ts +1 -0
- package/Types/AdminDashboard/AdminDashboardLanguage.ts +1 -0
- package/Types/Calendar/CalendarEvent.ts +16 -0
- package/Types/Cloud/CloudPlatform.ts +372 -0
- package/Types/CodeRepository/GitHubCommand.ts +69 -0
- package/Types/Dashboard/DashboardComponentType.ts +2 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardVMwareHostListComponent.ts +23 -0
- package/Types/Dashboard/DashboardComponents/DashboardVMwareVirtualMachineListComponent.ts +30 -0
- package/Types/Dashboard/DashboardLanguage.ts +1 -0
- package/Types/Dashboard/DashboardTemplates.ts +779 -0
- package/Types/Docs/DocsLanguage.ts +1 -0
- package/Types/Exception/EgressGuardException.ts +65 -0
- package/Types/Icon/IconProp.ts +1 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +36 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +1 -0
- package/Types/Monitor/MonitorStep.ts +78 -17
- package/Types/Monitor/MonitorStepMetricViewConfigUtil.ts +1 -0
- package/Types/Monitor/MonitorStepVMwareMonitor.ts +127 -0
- package/Types/Monitor/MonitorTemplateSyncField.ts +291 -0
- package/Types/Monitor/MonitorType.ts +24 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +33 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +2 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +3 -0
- package/Types/Monitor/SeriesContext/SeriesDebugHints.ts +158 -0
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +61 -0
- package/Types/Monitor/VMwareAlertTemplates.ts +1070 -0
- package/Types/Monitor/VMwareMetricCatalog.ts +914 -0
- package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +29 -0
- package/Types/OnCallDutyPolicy/UserOverrideUtil.ts +16 -0
- package/Types/Password.ts +84 -5
- package/Types/Permission.ts +265 -0
- package/Types/Probe/RequestFailedDetails.ts +7 -0
- package/Types/Rules/RuleCriteria.ts +51 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +437 -0
- package/Types/Rum/SessionReplay.ts +75 -0
- package/Types/Rum/SessionReplayApi.ts +93 -0
- package/Types/Runner/RunnerLiveStatus.ts +1 -1
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +56 -0
- package/Types/StatusPage/StatusPageLanguage.ts +1 -0
- package/Types/Telemetry/EntityType.ts +21 -0
- package/Types/Telemetry/ServiceType.ts +1 -0
- package/Typings/Index.d.ts +63 -0
- package/UI/Components/Alerts/Alert.tsx +102 -72
- package/UI/Components/Breadcrumbs/Breadcrumbs.tsx +2 -2
- package/UI/Components/Button/Button.tsx +4 -1
- package/UI/Components/Calendar/Calendar.css +78 -0
- package/UI/Components/Calendar/Calendar.tsx +28 -3
- package/UI/Components/Dropdown/Dropdown.tsx +2 -0
- package/UI/Components/Feed/Feed.tsx +15 -0
- package/UI/Components/Feed/useFeedItems.ts +227 -0
- package/UI/Components/Forms/BasicForm.tsx +86 -23
- package/UI/Components/Forms/Fields/ColorPicker.tsx +2 -1
- package/UI/Components/Forms/Fields/FormField.tsx +16 -3
- package/UI/Components/Forms/ModelForm.tsx +239 -6
- package/UI/Components/Forms/Types/Field.ts +8 -1
- package/UI/Components/Graphs/DayUptimeGraph.tsx +8 -10
- package/UI/Components/Icon/Icon.tsx +19 -35
- package/UI/Components/Input/Input.tsx +42 -7
- package/UI/Components/LabelRule/ImportLabelRulesModal.tsx +441 -0
- package/UI/Components/LabelRule/LabelRuleTable.tsx +142 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +22 -5
- package/UI/Components/ModelTable/ModelTable.tsx +33 -6
- package/UI/Components/MonitorGraphs/Uptime.tsx +17 -27
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +3 -1
- package/UI/Components/Navbar/NavBar.tsx +1 -0
- package/UI/Components/RuleCriteria/RuleCriteriaBuilder.tsx +735 -0
- package/UI/Components/RuleCriteria/RuleCriteriaModelForm.tsx +209 -0
- package/UI/Components/RuleCriteria/RuleCriteriaModelTable.tsx +205 -0
- package/UI/Components/RuleCriteria/RuleCriteriaSummary.tsx +123 -0
- package/UI/Components/Table/Table.tsx +3 -0
- package/UI/Components/Table/TableBody.tsx +3 -0
- package/UI/Components/Table/TableRow.tsx +8 -2
- package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +14 -2
- package/UI/Components/Tooltip/Tooltip.tsx +52 -6
- package/UI/Styles/Theme.css +1 -0
- package/UI/Utils/DashboardStackingLayers.ts +85 -0
- package/UI/Utils/LabelRuleImportExport.ts +418 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +4 -3
- package/UI/Utils/Navigation.ts +1 -2
- package/UI/Utils/TelemetryService.ts +4 -3
- package/UI/Utils/UseDashboardGridDnd.ts +4 -1
- package/UI/Utils/UserEmailRegistrationStatus.ts +33 -5
- package/UI/Utils/WebAuthn.ts +220 -0
- package/UI/esbuild-config.js +50 -0
- package/Utils/API.ts +34 -0
- package/Utils/Dashboard/Components/DashboardVMwareHostListComponent.ts +38 -0
- package/Utils/Dashboard/Components/DashboardVMwareResourceListShared.ts +70 -0
- package/Utils/Dashboard/Components/DashboardVMwareVirtualMachineListComponent.ts +76 -0
- package/Utils/Dashboard/Components/Index.ts +16 -0
- package/Utils/Faker.ts +93 -6
- package/Utils/LabelRuleImportExport.ts +789 -0
- package/Utils/Monitor/MonitorTemplateSyncUtil.ts +164 -0
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +108 -8
- package/Utils/NetworkDiscovery/DiscoveryScanStatus.ts +8 -0
- package/Utils/NetworkSite/CidrMatchUtil.ts +102 -0
- package/Utils/NetworkSite/TypeHierarchyUtil.ts +152 -2
- package/Utils/Rules/RuleCriteriaMatcher.ts +931 -0
- package/Utils/Rum/SessionIdentity.ts +16 -0
- package/Utils/Slo/SloBurnRateRuleState.ts +87 -33
- package/Utils/Telemetry/CloudInstanceIdentity.ts +94 -0
- package/Utils/Telemetry/EntityKey.ts +19 -0
- package/Utils/Telemetry/EntityRelationship.ts +19 -0
- package/Utils/Telemetry/OriginAllowList.ts +74 -0
- package/build/dist/Models/AnalyticsModels/RumSession.js +32 -0
- package/build/dist/Models/AnalyticsModels/RumSession.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Alert.js +54 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodeLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodeOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodePrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodePrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertPrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertPrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertReminderRule.js +6 -5
- package/build/dist/Models/DatabaseModels/AlertReminderRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AutoRemediationRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AutoRemediationRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResource.js +44 -7
- package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResourceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CloudResourceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResourceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CloudResourceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CodeRepository.js +87 -0
- package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DashboardLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DashboardLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DashboardOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DashboardOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RelationOnlyRuleBaseModel.js +12 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RelationOnlyRuleBaseModel.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RuleBaseModel.js +50 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RuleBaseModel.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DockerHostLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerHostLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHostOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerHostOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +60 -7
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js +287 -0
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js.map +1 -0
- package/build/dist/Models/DatabaseModels/HostLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/HostLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/HostOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/HostOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +54 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodeLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodePrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentPrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentReminderRule.js +6 -5
- package/build/dist/Models/DatabaseModels/IncidentReminderRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentSlaRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentSlaRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js +3 -4
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.js +277 -0
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +18 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/KubernetesClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/MonitorLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/MonitorOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHostLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/PodmanHostLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHostOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/PodmanHostOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplicationLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RumApplicationLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplicationOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RumApplicationOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RunbookLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RunbookOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RunbookRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceReminderRule.js +6 -5
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceReminderRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunctionLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServerlessFunctionLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServiceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +281 -4
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServiceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/StatusPageLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js +2 -2
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/StatusPageOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +57 -4
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +47 -2
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js +18 -0
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareResource.js +1201 -0
- package/build/dist/Models/DatabaseModels/VMwareResource.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +1149 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js +503 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js +502 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/WorkflowLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/WorkflowLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/WorkflowOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js +22 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +63 -3
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIAgentGitHubAPI.js +363 -0
- package/build/dist/Server/API/AIAgentGitHubAPI.js.map +1 -0
- package/build/dist/Server/API/AIChatAPI.js +19 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/BillingAPI.js +22 -0
- package/build/dist/Server/API/BillingAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +10 -0
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/GitHubAPI.js +33 -5
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +56 -0
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +1 -0
- package/build/dist/Server/API/TelemetryAPI.js +211 -4
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js +17 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
- package/build/dist/Server/API/VMwareResourceAPI.js +106 -0
- package/build/dist/Server/API/VMwareResourceAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791800000000-SplitWebAuthnChallengeByPurpose.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791800000000-SplitWebAuthnChallengeByPurpose.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791900000000-AddSeverityAndStateToNotificationEmailRollup.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791900000000-AddSeverityAndStateToNotificationEmailRollup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792000000000-AddVMwareTables.js +241 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792000000000-AddVMwareTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792100000000-AddGitHubCommandSettingsToCodeRepository.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792100000000-AddGitHubCommandSettingsToCodeRepository.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792200000000-AddUserWebAuthnPurpose.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792200000000-AddUserWebAuthnPurpose.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792300000000-AddGoogleSecOpsDiagnostics.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792300000000-AddGoogleSecOpsDiagnostics.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792400000000-AddSloBurnRateRuleIncidents.js +60 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792400000000-AddSloBurnRateRuleIncidents.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792500000000-AddConfigurableRuleCriteria.js +301 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792500000000-AddConfigurableRuleCriteria.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792600000000-AddIncomingCallPolicyPhoneNumbers.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792600000000-AddIncomingCallPolicyPhoneNumbers.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/IdentityRateLimit.js +80 -0
- package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
- package/build/dist/Server/Middleware/MultipartFormData.js +38 -21
- package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +14 -1
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertGroupingEngineService.js +21 -0
- package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOnCallRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js +44 -26
- package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +54 -11
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/BillingPaymentMethodService.js +71 -21
- package/build/dist/Server/Services/BillingPaymentMethodService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +210 -22
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceInstanceService.js +66 -0
- package/build/dist/Server/Services/CloudResourceInstanceService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +235 -10
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ExceptionAggregationService.js +1 -0
- package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js +9 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js.map +1 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +7 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +1 -1
- package/build/dist/Server/Services/HostLabelRuleEngineService.js +12 -0
- package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js +12 -0
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +39 -13
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +39 -9
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js +39 -10
- package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +39 -10
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +39 -10
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentReminderRuleService.js +44 -26
- package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSlaRuleService.js +33 -12
- package/build/dist/Server/Services/IncidentSlaRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyPhoneNumberService.js +127 -0
- package/build/dist/Server/Services/IncomingCallPolicyPhoneNumberService.js.map +1 -0
- package/build/dist/Server/Services/IncomingCallPolicyService.js +187 -4
- package/build/dist/Server/Services/IncomingCallPolicyService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +18 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +39 -7
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +1 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +1 -0
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MobilePasskeyLoginService.js +137 -0
- package/build/dist/Server/Services/MobilePasskeyLoginService.js.map +1 -0
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +34 -1
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +64 -26
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +126 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +199 -3
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +17 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +2 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +56 -1
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +187 -22
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteTypeService.js +126 -51
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +28 -13
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PayAsYouGoBillingService.js +297 -0
- package/build/dist/Server/Services/PayAsYouGoBillingService.js.map +1 -0
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js +115 -6
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +38 -2
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookRuleEngineService.js +12 -0
- package/build/dist/Server/Services/RunbookRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +38 -9
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +38 -10
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +32 -14
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionInstanceService.js +66 -0
- package/build/dist/Server/Services/ServerlessFunctionInstanceService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +554 -12
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +50 -14
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +25 -2
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js +19 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +85 -28
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +61 -10
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +62 -5
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceAggregationService.js +5 -4
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +14 -49
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/UserWebAuthnService.js +345 -113
- package/build/dist/Server/Services/UserWebAuthnService.js.map +1 -1
- package/build/dist/Server/Services/VMwareResourceService.js +395 -0
- package/build/dist/Server/Services/VMwareResourceService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterFeedService.js +89 -0
- package/build/dist/Server/Services/VMwareVCenterFeedService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js +213 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleService.js +13 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +230 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerTeamService.js +129 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerUserService.js +122 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterService.js +533 -0
- package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -0
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowVariableService.js +169 -0
- package/build/dist/Server/Services/WorkflowVariableService.js.map +1 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/ActiveMonitoringMeteredPlan.js +12 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/ActiveMonitoringMeteredPlan.js.map +1 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.js +25 -2
- package/build/dist/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +67 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +21 -4
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubAgentTaskTrigger.js +275 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubAgentTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandAuthorizer.js +226 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandAuthorizer.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandParser.js +297 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandParser.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubConversation.js +582 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubConversation.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubReplyComposer.js +275 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubReplyComposer.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubRunReply.js +365 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubRunReply.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.js +103 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookHandler.js +661 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookHandler.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +113 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +99 -15
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +2 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +18 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +31 -2
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -1
- package/build/dist/Server/Utils/IncomingCallPhoneNumber.js +9 -3
- package/build/dist/Server/Utils/IncomingCallPhoneNumber.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +2 -1
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +219 -4
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +12 -4
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +5 -3
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +22 -9
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +21 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +21 -6
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/Profiling.js +10 -1
- package/build/dist/Server/Utils/Profiling.js.map +1 -1
- package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js +3 -3
- package/build/dist/Server/Utils/Rules/MonitorRuleCriteriaCache.js +30 -0
- package/build/dist/Server/Utils/Rules/MonitorRuleCriteriaCache.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +9 -9
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +92 -71
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +428 -143
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +376 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +344 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +5 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +136 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/VMwareSnapshotScan.js +933 -0
- package/build/dist/Server/Utils/Telemetry/VMwareSnapshotScan.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry.js +1 -1
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +2 -0
- package/build/dist/Server/Utils/VendorAssets.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskContext.js +40 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskType.js +57 -0
- package/build/dist/Types/AI/CodeFixTaskType.js.map +1 -1
- package/build/dist/Types/Accounts/AccountsLanguage.js +1 -0
- package/build/dist/Types/Accounts/AccountsLanguage.js.map +1 -1
- package/build/dist/Types/AdminDashboard/AdminDashboardLanguage.js +1 -0
- package/build/dist/Types/AdminDashboard/AdminDashboardLanguage.js.map +1 -1
- package/build/dist/Types/Cloud/CloudPlatform.js +277 -0
- package/build/dist/Types/Cloud/CloudPlatform.js.map +1 -0
- package/build/dist/Types/CodeRepository/GitHubCommand.js +52 -0
- package/build/dist/Types/CodeRepository/GitHubCommand.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareHostListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareHostListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareVirtualMachineListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareVirtualMachineListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardLanguage.js +1 -0
- package/build/dist/Types/Dashboard/DashboardLanguage.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +711 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Docs/DocsLanguage.js +1 -0
- package/build/dist/Types/Docs/DocsLanguage.js.map +1 -1
- package/build/dist/Types/Exception/EgressGuardException.js +59 -0
- package/build/dist/Types/Exception/EgressGuardException.js.map +1 -0
- package/build/dist/Types/Icon/IconProp.js +1 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +61 -18
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js +1 -0
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepVMwareMonitor.js +71 -0
- package/build/dist/Types/Monitor/MonitorStepVMwareMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorTemplateSyncField.js +211 -0
- package/build/dist/Types/Monitor/MonitorTemplateSyncField.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorType.js +23 -0
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +28 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +2 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js +120 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +60 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
- package/build/dist/Types/Monitor/VMwareAlertTemplates.js +775 -0
- package/build/dist/Types/Monitor/VMwareAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/VMwareMetricCatalog.js +799 -0
- package/build/dist/Types/Monitor/VMwareMetricCatalog.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +25 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js +5 -0
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js.map +1 -1
- package/build/dist/Types/Password.js +63 -5
- package/build/dist/Types/Password.js.map +1 -1
- package/build/dist/Types/Permission.js +234 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Probe/RequestFailedDetails.js +7 -0
- package/build/dist/Types/Probe/RequestFailedDetails.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteria.js +18 -0
- package/build/dist/Types/Rules/RuleCriteria.js.map +1 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +426 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplay.js +64 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js +2 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageLanguage.js +1 -0
- package/build/dist/Types/StatusPage/StatusPageLanguage.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +21 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ServiceType.js +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Alerts/Alert.js +63 -41
- package/build/dist/UI/Components/Alerts/Alert.js.map +1 -1
- package/build/dist/UI/Components/Breadcrumbs/Breadcrumbs.js +2 -2
- package/build/dist/UI/Components/Breadcrumbs/Breadcrumbs.js.map +1 -1
- package/build/dist/UI/Components/Button/Button.js +3 -1
- package/build/dist/UI/Components/Button/Button.js.map +1 -1
- package/build/dist/UI/Components/Calendar/Calendar.js +24 -4
- package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/Feed/Feed.js +4 -1
- package/build/dist/UI/Components/Feed/Feed.js.map +1 -1
- package/build/dist/UI/Components/Feed/useFeedItems.js +137 -0
- package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -0
- package/build/dist/UI/Components/Forms/BasicForm.js +66 -22
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js +1 -1
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +10 -3
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +154 -7
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +5 -6
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +17 -35
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +37 -8
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js +228 -0
- package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js.map +1 -0
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js +102 -0
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +15 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +25 -6
- package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +14 -15
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +2 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +1 -0
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js +383 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelForm.js +124 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelForm.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelTable.js +126 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelTable.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaSummary.js +63 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaSummary.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +1 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +4 -2
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +3 -2
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +14 -2
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +33 -4
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/UI/Utils/DashboardStackingLayers.js +44 -0
- package/build/dist/UI/Utils/DashboardStackingLayers.js.map +1 -0
- package/build/dist/UI/Utils/LabelRuleImportExport.js +271 -0
- package/build/dist/UI/Utils/LabelRuleImportExport.js.map +1 -0
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +4 -4
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/TelemetryService.js +3 -2
- package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js +2 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js.map +1 -1
- package/build/dist/UI/Utils/UserEmailRegistrationStatus.js +21 -4
- package/build/dist/UI/Utils/UserEmailRegistrationStatus.js.map +1 -1
- package/build/dist/UI/Utils/WebAuthn.js +121 -0
- package/build/dist/UI/Utils/WebAuthn.js.map +1 -0
- package/build/dist/Utils/API.js +29 -0
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareHostListComponent.js +33 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareHostListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareResourceListShared.js +54 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareResourceListShared.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareVirtualMachineListComponent.js +60 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareVirtualMachineListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +8 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/Faker.js +76 -6
- package/build/dist/Utils/Faker.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +510 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorTemplateSyncUtil.js +110 -0
- package/build/dist/Utils/Monitor/MonitorTemplateSyncUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +81 -5
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js +6 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js.map +1 -1
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +77 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +109 -2
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -1
- package/build/dist/Utils/Rules/RuleCriteriaMatcher.js +526 -0
- package/build/dist/Utils/Rules/RuleCriteriaMatcher.js.map +1 -0
- package/build/dist/Utils/Rum/SessionIdentity.js +13 -1
- package/build/dist/Utils/Rum/SessionIdentity.js.map +1 -1
- package/build/dist/Utils/Slo/SloBurnRateRuleState.js +28 -15
- package/build/dist/Utils/Slo/SloBurnRateRuleState.js.map +1 -1
- package/build/dist/Utils/Telemetry/CloudInstanceIdentity.js +88 -0
- package/build/dist/Utils/Telemetry/CloudInstanceIdentity.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +15 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityRelationship.js +13 -0
- package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
- package/build/dist/Utils/Telemetry/OriginAllowList.js +61 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -1
- package/package.json +20 -20
|
@@ -9,7 +9,10 @@ import RumSessionChunkService from "../../../Server/Services/RumSessionChunkServ
|
|
|
9
9
|
import ExceptionInstanceService from "../../../Server/Services/ExceptionInstanceService";
|
|
10
10
|
import { Statement } from "../../../Server/Utils/AnalyticsDatabase/Statement";
|
|
11
11
|
import SessionReplayIdentity from "../../../Server/Utils/SessionReplay/SessionReplayIdentity";
|
|
12
|
-
import SessionReplayReadService
|
|
12
|
+
import SessionReplayReadService, {
|
|
13
|
+
DEFAULT_SESSION_REPLAY_USERS_LIMIT,
|
|
14
|
+
SessionReplayUsersRequest,
|
|
15
|
+
} from "../../../Server/Utils/SessionReplay/SessionReplayReadService";
|
|
13
16
|
import NotFoundException from "../../../Types/Exception/NotFoundException";
|
|
14
17
|
import {
|
|
15
18
|
MAX_SESSION_REPLAY_CHUNKS_PER_READ,
|
|
@@ -39,6 +42,7 @@ import Permission, {
|
|
|
39
42
|
} from "../../../Types/Permission";
|
|
40
43
|
import PermissionScope from "../../../Types/Database/AccessControl/PermissionScope";
|
|
41
44
|
import UserType from "../../../Types/UserType";
|
|
45
|
+
import zlib from "zlib";
|
|
42
46
|
import {
|
|
43
47
|
afterEach,
|
|
44
48
|
beforeAll,
|
|
@@ -133,6 +137,10 @@ const FOR_EXCEPTION_ROUTE: string =
|
|
|
133
137
|
const INGEST_STATUS_ROUTE: string =
|
|
134
138
|
"/telemetry/rum/session-replay/ingest-status";
|
|
135
139
|
const VIEWS_ROUTE: string = "/telemetry/rum/session-replay/views";
|
|
140
|
+
const USERS_ROUTE: string = "/telemetry/rum/session-replay/users";
|
|
141
|
+
|
|
142
|
+
/* A visitor id as the recorder mints it: 32 lowercase hex characters. */
|
|
143
|
+
const VISITOR_ID: string = "0123456789abcdef0123456789abcdef";
|
|
136
144
|
|
|
137
145
|
function findRoute(uri: string): RecordedRoute {
|
|
138
146
|
const route: RecordedRoute | undefined = recordedRoutes.find(
|
|
@@ -175,6 +183,12 @@ async function callRoute(data: {
|
|
|
175
183
|
uri: string;
|
|
176
184
|
request: JSONObject;
|
|
177
185
|
body: JSONObject;
|
|
186
|
+
/*
|
|
187
|
+
* Extra request headers (e.g. accept-encoding). Absent by default so
|
|
188
|
+
* every test that does not name one runs the identity path exactly as
|
|
189
|
+
* before the chunk route learned to gzip.
|
|
190
|
+
*/
|
|
191
|
+
headers?: Dictionary<string>;
|
|
178
192
|
}): Promise<CallResult> {
|
|
179
193
|
const route: RecordedRoute = findRoute(data.uri);
|
|
180
194
|
|
|
@@ -186,7 +200,7 @@ async function callRoute(data: {
|
|
|
186
200
|
body: data.body,
|
|
187
201
|
params: {},
|
|
188
202
|
query: {},
|
|
189
|
-
headers: { "user-agent": "jest-agent" },
|
|
203
|
+
headers: { "user-agent": "jest-agent", ...(data.headers ?? {}) },
|
|
190
204
|
} as unknown as ExpressRequest;
|
|
191
205
|
|
|
192
206
|
const res: ExpressResponse = {
|
|
@@ -549,9 +563,10 @@ describe("Session replay playback API", () => {
|
|
|
549
563
|
}
|
|
550
564
|
|
|
551
565
|
describe("guard shape", () => {
|
|
552
|
-
test("all
|
|
566
|
+
test("all eight routes are registered and every one carries the three-middleware guard", () => {
|
|
553
567
|
for (const uri of [
|
|
554
568
|
LIST_ROUTE,
|
|
569
|
+
USERS_ROUTE,
|
|
555
570
|
MANIFEST_ROUTE,
|
|
556
571
|
CHUNKS_ROUTE,
|
|
557
572
|
HEARTBEAT_ROUTE,
|
|
@@ -596,6 +611,8 @@ describe("Session replay playback API", () => {
|
|
|
596
611
|
}
|
|
597
612
|
|
|
598
613
|
expect(findRoute(FOR_EXCEPTION_ROUTE).handlers[2]).toBe(listGuard);
|
|
614
|
+
/* The rollup projects nothing the list does not: same guard instance. */
|
|
615
|
+
expect(findRoute(USERS_ROUTE).handlers[2]).toBe(listGuard);
|
|
599
616
|
});
|
|
600
617
|
});
|
|
601
618
|
|
|
@@ -1342,6 +1359,152 @@ describe("Session replay playback API", () => {
|
|
|
1342
1359
|
* wrong recording, and each opening writes an audit row against a real
|
|
1343
1360
|
* end user. The Dashboard already reads this field and shows a notice.
|
|
1344
1361
|
*/
|
|
1362
|
+
/*
|
|
1363
|
+
* The visitor id is the recorder's own random per-browser token, and
|
|
1364
|
+
* the list already hands it to every caller on every row - so filtering
|
|
1365
|
+
* by it discloses nothing the caller does not have, and it is NOT gated
|
|
1366
|
+
* like identifiedUserRef. A TelemetryAdmin denied the label can still
|
|
1367
|
+
* ask for "every session from this browser", and the filter is applied,
|
|
1368
|
+
* not dropped and named in ignoredFilters.
|
|
1369
|
+
*/
|
|
1370
|
+
test("filters.visitorId is bound into the query for a caller without the identity permission, never dropped", async () => {
|
|
1371
|
+
const principal: {
|
|
1372
|
+
request: JSONObject;
|
|
1373
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
1374
|
+
} = buildPrincipal({
|
|
1375
|
+
projectId: projectId,
|
|
1376
|
+
userId: userId,
|
|
1377
|
+
permissions: [Permission.TelemetryAdmin],
|
|
1378
|
+
});
|
|
1379
|
+
|
|
1380
|
+
mockProps(principal.databaseProps);
|
|
1381
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
1382
|
+
|
|
1383
|
+
const result: CallResult = await callRoute({
|
|
1384
|
+
uri: LIST_ROUTE,
|
|
1385
|
+
request: principal.request,
|
|
1386
|
+
body: {
|
|
1387
|
+
rumApplicationId: applicationAId.toString(),
|
|
1388
|
+
filters: { visitorId: VISITOR_ID },
|
|
1389
|
+
},
|
|
1390
|
+
});
|
|
1391
|
+
|
|
1392
|
+
expect(result.deniedWith).toBeUndefined();
|
|
1393
|
+
expect(headerQuerySpy).toHaveBeenCalledTimes(1);
|
|
1394
|
+
|
|
1395
|
+
const statement: Statement = headerQuerySpy.mock
|
|
1396
|
+
.calls[0]![0] as Statement;
|
|
1397
|
+
const having: string = statement.query.substring(
|
|
1398
|
+
statement.query.indexOf("HAVING 1 = 1"),
|
|
1399
|
+
);
|
|
1400
|
+
|
|
1401
|
+
expect(having).toMatch(/AND aggVisitorId = \{p\d+:String\}/);
|
|
1402
|
+
expect(statement.query).not.toContain(`'${VISITOR_ID}'`);
|
|
1403
|
+
expect(Object.values(statement.query_params)).toContain(VISITOR_ID);
|
|
1404
|
+
/* Nothing identity-gated was named for it. */
|
|
1405
|
+
expect(statement.query).not.toContain("identifiedUserLabel");
|
|
1406
|
+
expect(result.jsonBody?.["ignoredFilters"]).toEqual([]);
|
|
1407
|
+
});
|
|
1408
|
+
|
|
1409
|
+
/*
|
|
1410
|
+
* A visitor id that is not one can match nothing, and an unfiltered
|
|
1411
|
+
* list with a 200 is the wrong answer to "every session from this
|
|
1412
|
+
* browser" - the same reasoning as an unusable identifiedUserRef.
|
|
1413
|
+
*/
|
|
1414
|
+
test.each([
|
|
1415
|
+
"0123456789ABCDEF0123456789ABCDEF",
|
|
1416
|
+
"0123456789abcdef",
|
|
1417
|
+
"",
|
|
1418
|
+
42,
|
|
1419
|
+
true,
|
|
1420
|
+
{ visitorId: VISITOR_ID },
|
|
1421
|
+
[VISITOR_ID],
|
|
1422
|
+
])(
|
|
1423
|
+
"filters.visitorId %p is a bad request, never an unfiltered list",
|
|
1424
|
+
async (value: unknown) => {
|
|
1425
|
+
const principal: {
|
|
1426
|
+
request: JSONObject;
|
|
1427
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
1428
|
+
} = ownerPrincipal();
|
|
1429
|
+
|
|
1430
|
+
const result: CallResult = await callRoute({
|
|
1431
|
+
uri: LIST_ROUTE,
|
|
1432
|
+
request: principal.request,
|
|
1433
|
+
body: {
|
|
1434
|
+
rumApplicationId: applicationAId.toString(),
|
|
1435
|
+
filters: { visitorId: value as string },
|
|
1436
|
+
},
|
|
1437
|
+
});
|
|
1438
|
+
|
|
1439
|
+
expect(result.deniedWith).toBeInstanceOf(BadDataException);
|
|
1440
|
+
expect(result.deniedWith?.message).toContain("visitorId");
|
|
1441
|
+
expect(headerQuerySpy).not.toHaveBeenCalled();
|
|
1442
|
+
},
|
|
1443
|
+
);
|
|
1444
|
+
|
|
1445
|
+
test("a null visitorId filter is 'no filter', like an absent one", async () => {
|
|
1446
|
+
const principal: {
|
|
1447
|
+
request: JSONObject;
|
|
1448
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
1449
|
+
} = ownerPrincipal();
|
|
1450
|
+
|
|
1451
|
+
const result: CallResult = await callRoute({
|
|
1452
|
+
uri: LIST_ROUTE,
|
|
1453
|
+
request: principal.request,
|
|
1454
|
+
body: {
|
|
1455
|
+
rumApplicationId: applicationAId.toString(),
|
|
1456
|
+
filters: { visitorId: null },
|
|
1457
|
+
},
|
|
1458
|
+
});
|
|
1459
|
+
|
|
1460
|
+
expect(result.deniedWith).toBeUndefined();
|
|
1461
|
+
|
|
1462
|
+
const statement: Statement = headerQuerySpy.mock
|
|
1463
|
+
.calls[0]![0] as Statement;
|
|
1464
|
+
expect(statement.query).not.toContain("aggVisitorId =");
|
|
1465
|
+
});
|
|
1466
|
+
|
|
1467
|
+
test("the list projects each session's digest and visitor id for every caller", async () => {
|
|
1468
|
+
const principal: {
|
|
1469
|
+
request: JSONObject;
|
|
1470
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
1471
|
+
} = buildPrincipal({
|
|
1472
|
+
projectId: projectId,
|
|
1473
|
+
userId: userId,
|
|
1474
|
+
permissions: [Permission.TelemetryAdmin],
|
|
1475
|
+
});
|
|
1476
|
+
|
|
1477
|
+
mockProps(principal.databaseProps);
|
|
1478
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
1479
|
+
|
|
1480
|
+
headerQuerySpy.mockResolvedValue(
|
|
1481
|
+
fakeResultSet([
|
|
1482
|
+
{
|
|
1483
|
+
sessionId: "a",
|
|
1484
|
+
applicationId: applicationAId.toString(),
|
|
1485
|
+
aggIdentifiedUserKey: "hmac-1",
|
|
1486
|
+
aggVisitorId: VISITOR_ID,
|
|
1487
|
+
},
|
|
1488
|
+
{ sessionId: "b", applicationId: applicationAId.toString() },
|
|
1489
|
+
]) as never,
|
|
1490
|
+
);
|
|
1491
|
+
|
|
1492
|
+
const result: CallResult = await callRoute({
|
|
1493
|
+
uri: LIST_ROUTE,
|
|
1494
|
+
request: principal.request,
|
|
1495
|
+
body: { rumApplicationId: applicationAId.toString() },
|
|
1496
|
+
});
|
|
1497
|
+
|
|
1498
|
+
const sessions: Array<JSONObject> = (result.jsonBody as JSONObject)[
|
|
1499
|
+
"sessions"
|
|
1500
|
+
] as unknown as Array<JSONObject>;
|
|
1501
|
+
|
|
1502
|
+
expect(sessions[0]!["identifiedUserKey"]).toBe("hmac-1");
|
|
1503
|
+
expect(sessions[0]!["visitorId"]).toBe(VISITOR_ID);
|
|
1504
|
+
/* An older recorder's session: "", never undefined. */
|
|
1505
|
+
expect(sessions[1]!["visitorId"]).toBe("");
|
|
1506
|
+
});
|
|
1507
|
+
|
|
1345
1508
|
test("a dropped identity filter is NAMED in the response, not silently ignored", async () => {
|
|
1346
1509
|
const principal: {
|
|
1347
1510
|
request: JSONObject;
|
|
@@ -2195,154 +2358,723 @@ describe("Session replay playback API", () => {
|
|
|
2195
2358
|
});
|
|
2196
2359
|
});
|
|
2197
2360
|
|
|
2198
|
-
|
|
2199
|
-
|
|
2361
|
+
/*
|
|
2362
|
+
* The per-user rollup: /list grouped by person. It shares the list's
|
|
2363
|
+
* guard, prologue and identity decision, and pins its own cursor shape.
|
|
2364
|
+
* Everything about the statement itself is pinned in
|
|
2365
|
+
* SessionReplayReadServiceQueries.test.ts; here it is the handler's
|
|
2366
|
+
* contract - what reaches the service and what leaves the route.
|
|
2367
|
+
*/
|
|
2368
|
+
describe("users", () => {
|
|
2369
|
+
function rollupRow(overrides: JSONObject = {}): JSONObject {
|
|
2370
|
+
return {
|
|
2371
|
+
rollupKey: "u:hmac-1",
|
|
2372
|
+
rollupIdentifiedUserKey: "hmac-1",
|
|
2373
|
+
rollupVisitorId: VISITOR_ID,
|
|
2374
|
+
rollupSessionCount: 3,
|
|
2375
|
+
rollupLiveSessionCount: 1,
|
|
2376
|
+
rollupFirstSeenUnixMs: 1700000000000,
|
|
2377
|
+
rollupLastSeenUnixMs: 1700000900000,
|
|
2378
|
+
rollupTotalDurationMs: 180000,
|
|
2379
|
+
rollupErrorCount: 2,
|
|
2380
|
+
rollupFrustrationCount: 4,
|
|
2381
|
+
rollupErrorSessionCount: 1,
|
|
2382
|
+
rollupPageCount: 9,
|
|
2383
|
+
rollupLastSessionId: "session-3",
|
|
2384
|
+
rollupLastEntryUrl: "https://example.com/checkout",
|
|
2385
|
+
rollupBrowserName: "Chrome",
|
|
2386
|
+
rollupBrowserVersion: "128",
|
|
2387
|
+
rollupOsName: "macOS",
|
|
2388
|
+
rollupDeviceType: "desktop",
|
|
2389
|
+
rollupCountryCode: "GB",
|
|
2390
|
+
rollupIdentifiedUserLabel: "jane@example.com",
|
|
2391
|
+
rollupIdentifiedUserTraits: { plan: "pro" },
|
|
2392
|
+
...overrides,
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
function principalWith(permissions: Array<Permission>): {
|
|
2397
|
+
request: JSONObject;
|
|
2398
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2399
|
+
} {
|
|
2200
2400
|
const principal: {
|
|
2201
2401
|
request: JSONObject;
|
|
2202
2402
|
databaseProps: DatabaseCommonInteractionProps;
|
|
2203
2403
|
} = buildPrincipal({
|
|
2204
2404
|
projectId: projectId,
|
|
2205
2405
|
userId: userId,
|
|
2206
|
-
permissions:
|
|
2406
|
+
permissions: permissions,
|
|
2207
2407
|
});
|
|
2208
2408
|
|
|
2209
2409
|
mockProps(principal.databaseProps);
|
|
2210
|
-
mockSessionHeader(applicationAId);
|
|
2211
2410
|
mockApplication({ id: applicationAId, labelIds: [] });
|
|
2212
|
-
const viewId: ObjectID = mockRecordedView();
|
|
2213
2411
|
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
errorCount: 2,
|
|
2225
|
-
rageClickCount: 1,
|
|
2226
|
-
deadClickCount: 4,
|
|
2227
|
-
errorClickCount: 6,
|
|
2228
|
-
refreshRageCount: 5,
|
|
2229
|
-
routeCount: 3,
|
|
2230
|
-
},
|
|
2231
|
-
{
|
|
2232
|
-
tabId: "tab-1",
|
|
2233
|
-
chunkIndex: 3,
|
|
2234
|
-
chunkStartOffsetMs: 45000,
|
|
2235
|
-
chunkEndOffsetMs: 60000,
|
|
2236
|
-
eventCount: 100,
|
|
2237
|
-
hasFullSnapshot: false,
|
|
2238
|
-
chunkPayloadBytes: 1024,
|
|
2239
|
-
errorCount: 0,
|
|
2240
|
-
rageClickCount: 0,
|
|
2241
|
-
deadClickCount: 0,
|
|
2242
|
-
errorClickCount: 0,
|
|
2243
|
-
refreshRageCount: 0,
|
|
2244
|
-
routeCount: 0,
|
|
2245
|
-
},
|
|
2246
|
-
]) as never,
|
|
2247
|
-
);
|
|
2412
|
+
return principal;
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
test("a caller with the list permission reaches the handler and gets the rollup", async () => {
|
|
2416
|
+
const principal: {
|
|
2417
|
+
request: JSONObject;
|
|
2418
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2419
|
+
} = principalWith([Permission.ReadRumSessionReplay]);
|
|
2420
|
+
|
|
2421
|
+
headerQuerySpy.mockResolvedValue(fakeResultSet([rollupRow()]) as never);
|
|
2248
2422
|
|
|
2249
2423
|
const result: CallResult = await callRoute({
|
|
2250
|
-
uri:
|
|
2424
|
+
uri: USERS_ROUTE,
|
|
2251
2425
|
request: principal.request,
|
|
2252
|
-
body: {
|
|
2426
|
+
body: { rumApplicationId: applicationAId.toString() },
|
|
2253
2427
|
});
|
|
2254
2428
|
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
expect(
|
|
2258
|
-
expect(
|
|
2259
|
-
expect(statement.query).toContain("LIMIT 1 BY tabId, chunkIndex");
|
|
2260
|
-
|
|
2261
|
-
/*
|
|
2262
|
-
* The signal counters must be projected: the player's error,
|
|
2263
|
-
* frustration and route timeline lanes and the "next error" jump are
|
|
2264
|
-
* fed exclusively by these per-chunk columns. Dropping one from the
|
|
2265
|
-
* SELECT silently blanks a lane — it parses as 0 client-side.
|
|
2266
|
-
*/
|
|
2267
|
-
for (const counterColumn of [
|
|
2268
|
-
"errorCount",
|
|
2269
|
-
"rageClickCount",
|
|
2270
|
-
"deadClickCount",
|
|
2271
|
-
"errorClickCount",
|
|
2272
|
-
"refreshRageCount",
|
|
2273
|
-
"routeCount",
|
|
2274
|
-
]) {
|
|
2275
|
-
expect(statement.query).toContain(counterColumn);
|
|
2276
|
-
}
|
|
2429
|
+
expect(result.reachedHandler).toBe(true);
|
|
2430
|
+
expect(result.deniedWith).toBeUndefined();
|
|
2431
|
+
expect(result.thrownToNext).toBeUndefined();
|
|
2432
|
+
expect(headerQuerySpy).toHaveBeenCalledTimes(1);
|
|
2277
2433
|
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
expect(
|
|
2282
|
-
projectId
|
|
2434
|
+
const statement: Statement = headerQuerySpy.mock
|
|
2435
|
+
.calls[0]![0] as Statement;
|
|
2436
|
+
expect(statement.query).toContain("GROUP BY rollupKey");
|
|
2437
|
+
expect(statement.query).toContain(
|
|
2438
|
+
"GROUP BY projectId, rumApplicationId, sessionId",
|
|
2283
2439
|
);
|
|
2284
|
-
expect((
|
|
2440
|
+
expect(statement.query).toContain("retentionDate >= now()");
|
|
2441
|
+
expect(statement.query).toContain("timeout_overflow_mode = 'throw'");
|
|
2442
|
+
expect(statement.query).not.toContain(" FINAL");
|
|
2443
|
+
expect(Object.values(statement.query_params)).toContain(
|
|
2285
2444
|
applicationAId.toString(),
|
|
2286
2445
|
);
|
|
2287
|
-
expect(auditArgs["sessionId"]).toBe("session-1");
|
|
2288
|
-
expect(auditArgs["accessReason"]).toBe("incident triage");
|
|
2289
|
-
expect(auditArgs["ipAddress"]).toBe("203.0.113.7");
|
|
2290
2446
|
|
|
2291
2447
|
const body: JSONObject = result.jsonBody as JSONObject;
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
const tabs: Array<JSONObject> = body[
|
|
2295
|
-
"tabs"
|
|
2296
|
-
] as unknown as Array<JSONObject>;
|
|
2297
|
-
expect(tabs).toHaveLength(1);
|
|
2298
|
-
expect(tabs[0]!["chunkIndexes"]).toEqual([0, 3]);
|
|
2299
|
-
expect(tabs[0]!["fullSnapshotChunkIndexes"]).toEqual([0]);
|
|
2300
|
-
|
|
2301
|
-
/*
|
|
2302
|
-
* Every counter gets a DISTINCT nonzero value, asserted individually:
|
|
2303
|
-
* the client parses missing keys to 0, so a counter dropped from the
|
|
2304
|
-
* SELECT (or two counters cross-wired in the row mapping) fails
|
|
2305
|
-
* loudly here instead of silently blanking a timeline lane.
|
|
2306
|
-
*/
|
|
2307
|
-
const manifestChunks: Array<JSONObject> = tabs[0]![
|
|
2308
|
-
"chunks"
|
|
2448
|
+
const users: Array<JSONObject> = body[
|
|
2449
|
+
"users"
|
|
2309
2450
|
] as unknown as Array<JSONObject>;
|
|
2310
|
-
expect(manifestChunks[0]!["errorCount"]).toBe(2);
|
|
2311
|
-
expect(manifestChunks[0]!["rageClickCount"]).toBe(1);
|
|
2312
|
-
expect(manifestChunks[0]!["deadClickCount"]).toBe(4);
|
|
2313
|
-
expect(manifestChunks[0]!["errorClickCount"]).toBe(6);
|
|
2314
|
-
expect(manifestChunks[0]!["refreshRageCount"]).toBe(5);
|
|
2315
|
-
expect(manifestChunks[0]!["routeCount"]).toBe(3);
|
|
2316
|
-
expect(manifestChunks[1]!["errorCount"]).toBe(0);
|
|
2317
2451
|
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
]
|
|
2325
|
-
expect(
|
|
2326
|
-
expect(
|
|
2327
|
-
expect(
|
|
2328
|
-
expect(
|
|
2452
|
+
expect(users).toHaveLength(1);
|
|
2453
|
+
expect(users[0]!["groupKey"]).toBe("u:hmac-1");
|
|
2454
|
+
expect(users[0]!["kind"]).toBe("identified");
|
|
2455
|
+
expect(users[0]!["identifiedUserKey"]).toBe("hmac-1");
|
|
2456
|
+
expect(users[0]!["visitorId"]).toBe(VISITOR_ID);
|
|
2457
|
+
expect(users[0]!["sessionCount"]).toBe(3);
|
|
2458
|
+
expect(users[0]!["liveSessionCount"]).toBe(1);
|
|
2459
|
+
expect(users[0]!["lastSessionId"]).toBe("session-3");
|
|
2460
|
+
expect(users[0]!["lastEntryUrl"]).toBe("https://example.com/checkout");
|
|
2461
|
+
expect(users[0]!["lastSeenUnixMs"]).toBe(1700000900000);
|
|
2462
|
+
expect(body["nextCursor"]).toBeNull();
|
|
2329
2463
|
});
|
|
2330
2464
|
|
|
2331
|
-
test("a
|
|
2332
|
-
const
|
|
2465
|
+
test("a caller with only the watch permission can read the rollup, a Viewer cannot", async () => {
|
|
2466
|
+
const watcher: {
|
|
2333
2467
|
request: JSONObject;
|
|
2334
2468
|
databaseProps: DatabaseCommonInteractionProps;
|
|
2335
|
-
} =
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2469
|
+
} = principalWith([Permission.ReadRumSessionReplayPayload]);
|
|
2470
|
+
|
|
2471
|
+
const allowed: CallResult = await callRoute({
|
|
2472
|
+
uri: USERS_ROUTE,
|
|
2473
|
+
request: watcher.request,
|
|
2474
|
+
body: { rumApplicationId: applicationAId.toString() },
|
|
2339
2475
|
});
|
|
2340
2476
|
|
|
2341
|
-
|
|
2342
|
-
headerQuerySpy.
|
|
2477
|
+
expect(allowed.deniedWith).toBeUndefined();
|
|
2478
|
+
expect(headerQuerySpy).toHaveBeenCalledTimes(1);
|
|
2343
2479
|
|
|
2344
|
-
|
|
2345
|
-
|
|
2480
|
+
jest.clearAllMocks();
|
|
2481
|
+
|
|
2482
|
+
const viewer: {
|
|
2483
|
+
request: JSONObject;
|
|
2484
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2485
|
+
} = principalWith([Permission.Viewer]);
|
|
2486
|
+
|
|
2487
|
+
const denied: CallResult = await callRoute({
|
|
2488
|
+
uri: USERS_ROUTE,
|
|
2489
|
+
request: viewer.request,
|
|
2490
|
+
body: { rumApplicationId: applicationAId.toString() },
|
|
2491
|
+
});
|
|
2492
|
+
|
|
2493
|
+
expect(denied.deniedWith).toBeInstanceOf(NotAuthorizedException);
|
|
2494
|
+
expect(denied.reachedHandler).toBe(false);
|
|
2495
|
+
expect(headerQuerySpy).not.toHaveBeenCalled();
|
|
2496
|
+
});
|
|
2497
|
+
|
|
2498
|
+
test("a caller scoped to another application is refused before any query", async () => {
|
|
2499
|
+
const principal: {
|
|
2500
|
+
request: JSONObject;
|
|
2501
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2502
|
+
} = buildPrincipal({
|
|
2503
|
+
projectId: projectId,
|
|
2504
|
+
userId: userId,
|
|
2505
|
+
permissions: [Permission.ReadRumSessionReplay],
|
|
2506
|
+
labelIds: [labelAId],
|
|
2507
|
+
});
|
|
2508
|
+
|
|
2509
|
+
mockProps(principal.databaseProps);
|
|
2510
|
+
mockApplication({ id: applicationBId, labelIds: [labelBId] });
|
|
2511
|
+
|
|
2512
|
+
const result: CallResult = await callRoute({
|
|
2513
|
+
uri: USERS_ROUTE,
|
|
2514
|
+
request: principal.request,
|
|
2515
|
+
body: { rumApplicationId: applicationBId.toString() },
|
|
2516
|
+
});
|
|
2517
|
+
|
|
2518
|
+
expect(result.thrownToNext).toBeInstanceOf(NotAuthorizedException);
|
|
2519
|
+
expect(headerQuerySpy).not.toHaveBeenCalled();
|
|
2520
|
+
});
|
|
2521
|
+
|
|
2522
|
+
test("a malformed rumApplicationId is a bad request, not a database error", async () => {
|
|
2523
|
+
const principal: {
|
|
2524
|
+
request: JSONObject;
|
|
2525
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2526
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2527
|
+
|
|
2528
|
+
const result: CallResult = await callRoute({
|
|
2529
|
+
uri: USERS_ROUTE,
|
|
2530
|
+
request: principal.request,
|
|
2531
|
+
body: { rumApplicationId: "not-a-uuid" },
|
|
2532
|
+
});
|
|
2533
|
+
|
|
2534
|
+
expect(result.thrownToNext).toBeInstanceOf(BadDataException);
|
|
2535
|
+
expect(headerQuerySpy).not.toHaveBeenCalled();
|
|
2536
|
+
});
|
|
2537
|
+
|
|
2538
|
+
/*
|
|
2539
|
+
* A cursor that is present but not {lastSeenUnixMs: finite >= 0,
|
|
2540
|
+
* groupKey: bounded string} is a 400 before any query - a non-finite
|
|
2541
|
+
* or negative clock cannot be bound, and an unbounded key would reach
|
|
2542
|
+
* ClickHouse as a parameter on a per-group predicate.
|
|
2543
|
+
*/
|
|
2544
|
+
test.each([
|
|
2545
|
+
{ nonsense: true },
|
|
2546
|
+
{ lastSeenUnixMs: "1700000000000", groupKey: "u:hmac-1" },
|
|
2547
|
+
{ lastSeenUnixMs: -1, groupKey: "u:hmac-1" },
|
|
2548
|
+
{ lastSeenUnixMs: Number.NaN, groupKey: "u:hmac-1" },
|
|
2549
|
+
{ lastSeenUnixMs: Number.POSITIVE_INFINITY, groupKey: "u:hmac-1" },
|
|
2550
|
+
{ lastSeenUnixMs: 1700000000000 },
|
|
2551
|
+
{ lastSeenUnixMs: 1700000000000, groupKey: 7 },
|
|
2552
|
+
{ lastSeenUnixMs: 1700000000000, groupKey: "k".repeat(129) },
|
|
2553
|
+
"u:hmac-1",
|
|
2554
|
+
[1700000000000, "u:hmac-1"],
|
|
2555
|
+
])(
|
|
2556
|
+
"cursor %p is a bad request without a query",
|
|
2557
|
+
async (cursor: unknown) => {
|
|
2558
|
+
const principal: {
|
|
2559
|
+
request: JSONObject;
|
|
2560
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2561
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2562
|
+
|
|
2563
|
+
const result: CallResult = await callRoute({
|
|
2564
|
+
uri: USERS_ROUTE,
|
|
2565
|
+
request: principal.request,
|
|
2566
|
+
body: {
|
|
2567
|
+
rumApplicationId: applicationAId.toString(),
|
|
2568
|
+
cursor: cursor as JSONObject,
|
|
2569
|
+
},
|
|
2570
|
+
});
|
|
2571
|
+
|
|
2572
|
+
expect(result.deniedWith).toBeInstanceOf(BadDataException);
|
|
2573
|
+
expect(result.deniedWith?.message).toContain("cursor");
|
|
2574
|
+
expect(headerQuerySpy).not.toHaveBeenCalled();
|
|
2575
|
+
},
|
|
2576
|
+
);
|
|
2577
|
+
|
|
2578
|
+
/*
|
|
2579
|
+
* The anonymous bucket's key is "" and it can be the last row of a
|
|
2580
|
+
* page, so the empty key is a VALID tiebreak - accepted and bound as
|
|
2581
|
+
* itself, not read as "no cursor".
|
|
2582
|
+
*/
|
|
2583
|
+
test("the anonymous bucket's empty group key is an accepted cursor", async () => {
|
|
2584
|
+
const principal: {
|
|
2585
|
+
request: JSONObject;
|
|
2586
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2587
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2588
|
+
|
|
2589
|
+
const result: CallResult = await callRoute({
|
|
2590
|
+
uri: USERS_ROUTE,
|
|
2591
|
+
request: principal.request,
|
|
2592
|
+
body: {
|
|
2593
|
+
rumApplicationId: applicationAId.toString(),
|
|
2594
|
+
cursor: { lastSeenUnixMs: 1700000700000, groupKey: "" },
|
|
2595
|
+
},
|
|
2596
|
+
});
|
|
2597
|
+
|
|
2598
|
+
expect(result.deniedWith).toBeUndefined();
|
|
2599
|
+
|
|
2600
|
+
const statement: Statement = headerQuerySpy.mock
|
|
2601
|
+
.calls[0]![0] as Statement;
|
|
2602
|
+
expect(statement.query).toMatch(
|
|
2603
|
+
/AND \(rollupLastSeenUnixMs < \{p\d+:Double\} OR \(rollupLastSeenUnixMs = \{p\d+:Double\} AND rollupKey < \{p\d+:String\}\)\)/,
|
|
2604
|
+
);
|
|
2605
|
+
expect(Object.values(statement.query_params)).toContain("");
|
|
2606
|
+
});
|
|
2607
|
+
|
|
2608
|
+
test("an inverted window, or an unparseable bound, is a bad request without a query", async () => {
|
|
2609
|
+
const principal: {
|
|
2610
|
+
request: JSONObject;
|
|
2611
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2612
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2613
|
+
|
|
2614
|
+
const inverted: CallResult = await callRoute({
|
|
2615
|
+
uri: USERS_ROUTE,
|
|
2616
|
+
request: principal.request,
|
|
2617
|
+
body: {
|
|
2618
|
+
rumApplicationId: applicationAId.toString(),
|
|
2619
|
+
startTime: "2026-08-08T00:00:00.000Z",
|
|
2620
|
+
endTime: "2026-08-01T00:00:00.000Z",
|
|
2621
|
+
},
|
|
2622
|
+
});
|
|
2623
|
+
|
|
2624
|
+
expect(inverted.deniedWith).toBeInstanceOf(BadDataException);
|
|
2625
|
+
expect(inverted.deniedWith?.message).toContain("startTime");
|
|
2626
|
+
expect(headerQuerySpy).not.toHaveBeenCalled();
|
|
2627
|
+
|
|
2628
|
+
jest.clearAllMocks();
|
|
2629
|
+
mockProps(principal.databaseProps);
|
|
2630
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
2631
|
+
|
|
2632
|
+
const garbage: CallResult = await callRoute({
|
|
2633
|
+
uri: USERS_ROUTE,
|
|
2634
|
+
request: principal.request,
|
|
2635
|
+
body: {
|
|
2636
|
+
rumApplicationId: applicationAId.toString(),
|
|
2637
|
+
endTime: "last tuesday",
|
|
2638
|
+
},
|
|
2639
|
+
});
|
|
2640
|
+
|
|
2641
|
+
expect(garbage.thrownToNext).toBeInstanceOf(BadDataException);
|
|
2642
|
+
expect(headerQuerySpy).not.toHaveBeenCalled();
|
|
2643
|
+
});
|
|
2644
|
+
|
|
2645
|
+
test.each([2.5, 0, -1, "20"])(
|
|
2646
|
+
"limit %p is a bad request rather than a ClickHouse error",
|
|
2647
|
+
async (limit: unknown) => {
|
|
2648
|
+
const principal: {
|
|
2649
|
+
request: JSONObject;
|
|
2650
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2651
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2652
|
+
|
|
2653
|
+
const result: CallResult = await callRoute({
|
|
2654
|
+
uri: USERS_ROUTE,
|
|
2655
|
+
request: principal.request,
|
|
2656
|
+
body: {
|
|
2657
|
+
rumApplicationId: applicationAId.toString(),
|
|
2658
|
+
limit: limit as number,
|
|
2659
|
+
},
|
|
2660
|
+
});
|
|
2661
|
+
|
|
2662
|
+
expect(result.thrownToNext).toBeInstanceOf(BadDataException);
|
|
2663
|
+
expect((result.thrownToNext as Exception).message).toContain("limit");
|
|
2664
|
+
expect(headerQuerySpy).not.toHaveBeenCalled();
|
|
2665
|
+
},
|
|
2666
|
+
);
|
|
2667
|
+
|
|
2668
|
+
/*
|
|
2669
|
+
* The identity decision is made per principal against the application
|
|
2670
|
+
* the access check loaded - exactly as on /list - and handed to the
|
|
2671
|
+
* service, which enforces it by not naming the columns.
|
|
2672
|
+
*/
|
|
2673
|
+
test("hands the service includeIdentifiedUserLabel true for an owner and false for a TelemetryAdmin, with the defaults", async () => {
|
|
2674
|
+
const listUsersSpy: jest.SpyInstance = jest
|
|
2675
|
+
.spyOn(SessionReplayReadService, "listUsers")
|
|
2676
|
+
.mockResolvedValue({ users: [], nextCursor: null });
|
|
2677
|
+
|
|
2678
|
+
const owner: {
|
|
2679
|
+
request: JSONObject;
|
|
2680
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2681
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2682
|
+
|
|
2683
|
+
const before: number = Date.now();
|
|
2684
|
+
|
|
2685
|
+
await callRoute({
|
|
2686
|
+
uri: USERS_ROUTE,
|
|
2687
|
+
request: owner.request,
|
|
2688
|
+
body: { rumApplicationId: applicationAId.toString() },
|
|
2689
|
+
});
|
|
2690
|
+
|
|
2691
|
+
expect(listUsersSpy).toHaveBeenCalledTimes(1);
|
|
2692
|
+
|
|
2693
|
+
const ownerRequest: SessionReplayUsersRequest = listUsersSpy.mock
|
|
2694
|
+
.calls[0]![0] as SessionReplayUsersRequest;
|
|
2695
|
+
|
|
2696
|
+
expect(ownerRequest.includeIdentifiedUserLabel).toBe(true);
|
|
2697
|
+
expect(ownerRequest.projectId.toString()).toBe(projectId.toString());
|
|
2698
|
+
expect(ownerRequest.rumApplicationId.toString()).toBe(
|
|
2699
|
+
applicationAId.toString(),
|
|
2700
|
+
);
|
|
2701
|
+
expect(ownerRequest.limit).toBe(DEFAULT_SESSION_REPLAY_USERS_LIMIT);
|
|
2702
|
+
expect(ownerRequest.cursor).toBeUndefined();
|
|
2703
|
+
/* The 7-day default window, like /list (a DST edge may shift it an hour). */
|
|
2704
|
+
const windowMs: number =
|
|
2705
|
+
ownerRequest.endTime.getTime() - ownerRequest.startTime.getTime();
|
|
2706
|
+
expect(windowMs).toBeGreaterThan(6.9 * 24 * 60 * 60 * 1000);
|
|
2707
|
+
expect(windowMs).toBeLessThan(7.1 * 24 * 60 * 60 * 1000);
|
|
2708
|
+
expect(ownerRequest.endTime.getTime()).toBeGreaterThanOrEqual(before);
|
|
2709
|
+
|
|
2710
|
+
jest.clearAllMocks();
|
|
2711
|
+
listUsersSpy.mockResolvedValue({ users: [], nextCursor: null });
|
|
2712
|
+
|
|
2713
|
+
const telemetryAdmin: {
|
|
2714
|
+
request: JSONObject;
|
|
2715
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2716
|
+
} = principalWith([Permission.TelemetryAdmin]);
|
|
2717
|
+
|
|
2718
|
+
await callRoute({
|
|
2719
|
+
uri: USERS_ROUTE,
|
|
2720
|
+
request: telemetryAdmin.request,
|
|
2721
|
+
body: { rumApplicationId: applicationAId.toString() },
|
|
2722
|
+
});
|
|
2723
|
+
|
|
2724
|
+
const adminRequest: SessionReplayUsersRequest = listUsersSpy.mock
|
|
2725
|
+
.calls[0]![0] as SessionReplayUsersRequest;
|
|
2726
|
+
|
|
2727
|
+
expect(adminRequest.includeIdentifiedUserLabel).toBe(false);
|
|
2728
|
+
});
|
|
2729
|
+
|
|
2730
|
+
test("includeIdentifiedUserLabel follows the identity grant's label scope", async () => {
|
|
2731
|
+
const listUsersSpy: jest.SpyInstance = jest
|
|
2732
|
+
.spyOn(SessionReplayReadService, "listUsers")
|
|
2733
|
+
.mockResolvedValue({ users: [], nextCursor: null });
|
|
2734
|
+
|
|
2735
|
+
/* Identity grant scoped to label B; the application carries label A. */
|
|
2736
|
+
const principal: {
|
|
2737
|
+
request: JSONObject;
|
|
2738
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2739
|
+
} = buildPrincipal({
|
|
2740
|
+
projectId: projectId,
|
|
2741
|
+
userId: userId,
|
|
2742
|
+
permissions: [Permission.ReadRumSessionReplayPayload],
|
|
2743
|
+
labelIds: [labelBId],
|
|
2744
|
+
});
|
|
2745
|
+
grantUnscopedListPermission(principal.databaseProps, projectId);
|
|
2746
|
+
|
|
2747
|
+
mockProps(principal.databaseProps);
|
|
2748
|
+
mockApplication({ id: applicationAId, labelIds: [labelAId] });
|
|
2749
|
+
|
|
2750
|
+
await callRoute({
|
|
2751
|
+
uri: USERS_ROUTE,
|
|
2752
|
+
request: principal.request,
|
|
2753
|
+
body: { rumApplicationId: applicationAId.toString() },
|
|
2754
|
+
});
|
|
2755
|
+
|
|
2756
|
+
const request: SessionReplayUsersRequest = listUsersSpy.mock
|
|
2757
|
+
.calls[0]![0] as SessionReplayUsersRequest;
|
|
2758
|
+
|
|
2759
|
+
expect(request.includeIdentifiedUserLabel).toBe(false);
|
|
2760
|
+
});
|
|
2761
|
+
|
|
2762
|
+
test("the window, limit and cursor reach the service as given", async () => {
|
|
2763
|
+
const listUsersSpy: jest.SpyInstance = jest
|
|
2764
|
+
.spyOn(SessionReplayReadService, "listUsers")
|
|
2765
|
+
.mockResolvedValue({ users: [], nextCursor: null });
|
|
2766
|
+
|
|
2767
|
+
const principal: {
|
|
2768
|
+
request: JSONObject;
|
|
2769
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2770
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2771
|
+
|
|
2772
|
+
await callRoute({
|
|
2773
|
+
uri: USERS_ROUTE,
|
|
2774
|
+
request: principal.request,
|
|
2775
|
+
body: {
|
|
2776
|
+
rumApplicationId: applicationAId.toString(),
|
|
2777
|
+
startTime: "2026-08-01T00:00:00.000Z",
|
|
2778
|
+
endTime: "2026-08-08T00:00:00.000Z",
|
|
2779
|
+
limit: 7,
|
|
2780
|
+
cursor: { lastSeenUnixMs: 1700000900000, groupKey: "u:hmac-1" },
|
|
2781
|
+
},
|
|
2782
|
+
});
|
|
2783
|
+
|
|
2784
|
+
const request: SessionReplayUsersRequest = listUsersSpy.mock
|
|
2785
|
+
.calls[0]![0] as SessionReplayUsersRequest;
|
|
2786
|
+
|
|
2787
|
+
expect(request.startTime.toISOString()).toBe("2026-08-01T00:00:00.000Z");
|
|
2788
|
+
expect(request.endTime.toISOString()).toBe("2026-08-08T00:00:00.000Z");
|
|
2789
|
+
expect(request.limit).toBe(7);
|
|
2790
|
+
expect(request.cursor).toEqual({
|
|
2791
|
+
lastSeenUnixMs: 1700000900000,
|
|
2792
|
+
groupKey: "u:hmac-1",
|
|
2793
|
+
});
|
|
2794
|
+
});
|
|
2795
|
+
|
|
2796
|
+
test("omits the label and traits, and never names them, for a caller without the identity permission", async () => {
|
|
2797
|
+
const principal: {
|
|
2798
|
+
request: JSONObject;
|
|
2799
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2800
|
+
} = principalWith([Permission.TelemetryAdmin]);
|
|
2801
|
+
|
|
2802
|
+
/* The row carries them; the handler must not have asked for them. */
|
|
2803
|
+
headerQuerySpy.mockResolvedValue(fakeResultSet([rollupRow()]) as never);
|
|
2804
|
+
|
|
2805
|
+
const result: CallResult = await callRoute({
|
|
2806
|
+
uri: USERS_ROUTE,
|
|
2807
|
+
request: principal.request,
|
|
2808
|
+
body: { rumApplicationId: applicationAId.toString() },
|
|
2809
|
+
});
|
|
2810
|
+
|
|
2811
|
+
const statement: Statement = headerQuerySpy.mock
|
|
2812
|
+
.calls[0]![0] as Statement;
|
|
2813
|
+
expect(statement.query).not.toContain("identifiedUserLabel");
|
|
2814
|
+
expect(statement.query).not.toContain("identifiedUserTraits");
|
|
2815
|
+
|
|
2816
|
+
const users: Array<JSONObject> = (result.jsonBody as JSONObject)[
|
|
2817
|
+
"users"
|
|
2818
|
+
] as unknown as Array<JSONObject>;
|
|
2819
|
+
|
|
2820
|
+
expect(users[0]!["identifiedUserLabel"]).toBeUndefined();
|
|
2821
|
+
expect(users[0]!["identifiedUserTraits"]).toBeUndefined();
|
|
2822
|
+
/* The ungated keys are still there. */
|
|
2823
|
+
expect(users[0]!["identifiedUserKey"]).toBe("hmac-1");
|
|
2824
|
+
expect(users[0]!["visitorId"]).toBe(VISITOR_ID);
|
|
2825
|
+
});
|
|
2826
|
+
|
|
2827
|
+
test("includes the label and traits, named at both levels, for a ProjectOwner", async () => {
|
|
2828
|
+
const principal: {
|
|
2829
|
+
request: JSONObject;
|
|
2830
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2831
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2832
|
+
|
|
2833
|
+
headerQuerySpy.mockResolvedValue(fakeResultSet([rollupRow()]) as never);
|
|
2834
|
+
|
|
2835
|
+
const result: CallResult = await callRoute({
|
|
2836
|
+
uri: USERS_ROUTE,
|
|
2837
|
+
request: principal.request,
|
|
2838
|
+
body: { rumApplicationId: applicationAId.toString() },
|
|
2839
|
+
});
|
|
2840
|
+
|
|
2841
|
+
const statement: Statement = headerQuerySpy.mock
|
|
2842
|
+
.calls[0]![0] as Statement;
|
|
2843
|
+
expect(statement.query).toContain(
|
|
2844
|
+
"argMax(identifiedUserLabel, version) AS aggIdentifiedUserLabel",
|
|
2845
|
+
);
|
|
2846
|
+
expect(statement.query).toContain(
|
|
2847
|
+
"argMax(aggIdentifiedUserLabel, aggStartTime) AS rollupIdentifiedUserLabel",
|
|
2848
|
+
);
|
|
2849
|
+
|
|
2850
|
+
const users: Array<JSONObject> = (result.jsonBody as JSONObject)[
|
|
2851
|
+
"users"
|
|
2852
|
+
] as unknown as Array<JSONObject>;
|
|
2853
|
+
|
|
2854
|
+
expect(users[0]!["identifiedUserLabel"]).toBe("jane@example.com");
|
|
2855
|
+
expect(users[0]!["identifiedUserTraits"]).toEqual({ plan: "pro" });
|
|
2856
|
+
});
|
|
2857
|
+
|
|
2858
|
+
test("pages by the last row's clock and key, keeping the anonymous bucket as a row", async () => {
|
|
2859
|
+
const principal: {
|
|
2860
|
+
request: JSONObject;
|
|
2861
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2862
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2863
|
+
|
|
2864
|
+
headerQuerySpy.mockResolvedValue(
|
|
2865
|
+
fakeResultSet([
|
|
2866
|
+
rollupRow(),
|
|
2867
|
+
rollupRow({
|
|
2868
|
+
rollupKey: "",
|
|
2869
|
+
rollupIdentifiedUserKey: "",
|
|
2870
|
+
rollupVisitorId: "",
|
|
2871
|
+
rollupLastSeenUnixMs: 1700000700000,
|
|
2872
|
+
rollupSessionCount: 12,
|
|
2873
|
+
}),
|
|
2874
|
+
rollupRow({
|
|
2875
|
+
rollupKey: `v:${VISITOR_ID}`,
|
|
2876
|
+
rollupIdentifiedUserKey: "",
|
|
2877
|
+
rollupLastSeenUnixMs: 1700000600000,
|
|
2878
|
+
}),
|
|
2879
|
+
]) as never,
|
|
2880
|
+
);
|
|
2881
|
+
|
|
2882
|
+
const result: CallResult = await callRoute({
|
|
2883
|
+
uri: USERS_ROUTE,
|
|
2884
|
+
request: principal.request,
|
|
2885
|
+
body: { rumApplicationId: applicationAId.toString(), limit: 2 },
|
|
2886
|
+
});
|
|
2887
|
+
|
|
2888
|
+
const body: JSONObject = result.jsonBody as JSONObject;
|
|
2889
|
+
const users: Array<JSONObject> = body[
|
|
2890
|
+
"users"
|
|
2891
|
+
] as unknown as Array<JSONObject>;
|
|
2892
|
+
|
|
2893
|
+
expect(users).toHaveLength(2);
|
|
2894
|
+
expect(users[1]!["kind"]).toBe("anonymous");
|
|
2895
|
+
expect(users[1]!["groupKey"]).toBe("");
|
|
2896
|
+
expect(users[1]!["identifiedUserKey"]).toBe("");
|
|
2897
|
+
expect(users[1]!["sessionCount"]).toBe(12);
|
|
2898
|
+
expect(body["nextCursor"]).toEqual({
|
|
2899
|
+
lastSeenUnixMs: 1700000700000,
|
|
2900
|
+
groupKey: "",
|
|
2901
|
+
});
|
|
2902
|
+
});
|
|
2903
|
+
|
|
2904
|
+
test("the tenant comes from databaseProps, not from the body", async () => {
|
|
2905
|
+
const principal: {
|
|
2906
|
+
request: JSONObject;
|
|
2907
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2908
|
+
} = principalWith([Permission.ProjectOwner]);
|
|
2909
|
+
|
|
2910
|
+
const otherProjectId: ObjectID = ObjectID.generate();
|
|
2911
|
+
|
|
2912
|
+
await callRoute({
|
|
2913
|
+
uri: USERS_ROUTE,
|
|
2914
|
+
request: principal.request,
|
|
2915
|
+
body: {
|
|
2916
|
+
rumApplicationId: applicationAId.toString(),
|
|
2917
|
+
projectId: otherProjectId.toString(),
|
|
2918
|
+
},
|
|
2919
|
+
});
|
|
2920
|
+
|
|
2921
|
+
const statement: Statement = headerQuerySpy.mock
|
|
2922
|
+
.calls[0]![0] as Statement;
|
|
2923
|
+
const bound: Array<unknown> = Object.values(statement.query_params);
|
|
2924
|
+
|
|
2925
|
+
expect(bound).toContain(projectId.toString());
|
|
2926
|
+
expect(bound).not.toContain(otherProjectId.toString());
|
|
2927
|
+
});
|
|
2928
|
+
});
|
|
2929
|
+
|
|
2930
|
+
describe("manifest", () => {
|
|
2931
|
+
test("never names the payload column and writes the read audit row", async () => {
|
|
2932
|
+
const principal: {
|
|
2933
|
+
request: JSONObject;
|
|
2934
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
2935
|
+
} = buildPrincipal({
|
|
2936
|
+
projectId: projectId,
|
|
2937
|
+
userId: userId,
|
|
2938
|
+
permissions: [Permission.ReadRumSessionReplayPayload],
|
|
2939
|
+
});
|
|
2940
|
+
|
|
2941
|
+
mockProps(principal.databaseProps);
|
|
2942
|
+
mockSessionHeader(applicationAId);
|
|
2943
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
2944
|
+
const viewId: ObjectID = mockRecordedView();
|
|
2945
|
+
|
|
2946
|
+
chunkQuerySpy.mockResolvedValue(
|
|
2947
|
+
fakeResultSet([
|
|
2948
|
+
{
|
|
2949
|
+
tabId: "tab-1",
|
|
2950
|
+
chunkIndex: 0,
|
|
2951
|
+
chunkStartOffsetMs: 0,
|
|
2952
|
+
chunkEndOffsetMs: 15000,
|
|
2953
|
+
eventCount: 100,
|
|
2954
|
+
hasFullSnapshot: true,
|
|
2955
|
+
chunkPayloadBytes: 1024,
|
|
2956
|
+
errorCount: 2,
|
|
2957
|
+
rageClickCount: 1,
|
|
2958
|
+
deadClickCount: 4,
|
|
2959
|
+
errorClickCount: 6,
|
|
2960
|
+
refreshRageCount: 5,
|
|
2961
|
+
routeCount: 3,
|
|
2962
|
+
},
|
|
2963
|
+
{
|
|
2964
|
+
tabId: "tab-1",
|
|
2965
|
+
chunkIndex: 3,
|
|
2966
|
+
chunkStartOffsetMs: 45000,
|
|
2967
|
+
chunkEndOffsetMs: 60000,
|
|
2968
|
+
eventCount: 100,
|
|
2969
|
+
hasFullSnapshot: false,
|
|
2970
|
+
chunkPayloadBytes: 1024,
|
|
2971
|
+
errorCount: 0,
|
|
2972
|
+
rageClickCount: 0,
|
|
2973
|
+
deadClickCount: 0,
|
|
2974
|
+
errorClickCount: 0,
|
|
2975
|
+
refreshRageCount: 0,
|
|
2976
|
+
routeCount: 0,
|
|
2977
|
+
},
|
|
2978
|
+
]) as never,
|
|
2979
|
+
);
|
|
2980
|
+
|
|
2981
|
+
const result: CallResult = await callRoute({
|
|
2982
|
+
uri: MANIFEST_ROUTE,
|
|
2983
|
+
request: principal.request,
|
|
2984
|
+
body: { sessionId: "session-1", accessReason: "incident triage" },
|
|
2985
|
+
});
|
|
2986
|
+
|
|
2987
|
+
const statement: Statement = chunkQuerySpy.mock.calls[0]![0] as Statement;
|
|
2988
|
+
|
|
2989
|
+
expect(statement.query).not.toContain("payload,");
|
|
2990
|
+
expect(statement.query).not.toMatch(/\bpayload\b(?!Bytes)/);
|
|
2991
|
+
expect(statement.query).toContain("LIMIT 1 BY tabId, chunkIndex");
|
|
2992
|
+
|
|
2993
|
+
/*
|
|
2994
|
+
* The signal counters must be projected: the player's error,
|
|
2995
|
+
* frustration and route timeline lanes and the "next error" jump are
|
|
2996
|
+
* fed exclusively by these per-chunk columns. Dropping one from the
|
|
2997
|
+
* SELECT silently blanks a lane — it parses as 0 client-side.
|
|
2998
|
+
*/
|
|
2999
|
+
for (const counterColumn of [
|
|
3000
|
+
"errorCount",
|
|
3001
|
+
"rageClickCount",
|
|
3002
|
+
"deadClickCount",
|
|
3003
|
+
"errorClickCount",
|
|
3004
|
+
"refreshRageCount",
|
|
3005
|
+
"routeCount",
|
|
3006
|
+
]) {
|
|
3007
|
+
expect(statement.query).toContain(counterColumn);
|
|
3008
|
+
}
|
|
3009
|
+
|
|
3010
|
+
expect(recordViewSpy).toHaveBeenCalledTimes(1);
|
|
3011
|
+
const auditArgs: JSONObject = recordViewSpy.mock
|
|
3012
|
+
.calls[0]![0] as JSONObject;
|
|
3013
|
+
expect((auditArgs["projectId"] as ObjectID).toString()).toBe(
|
|
3014
|
+
projectId.toString(),
|
|
3015
|
+
);
|
|
3016
|
+
expect((auditArgs["rumApplicationId"] as ObjectID).toString()).toBe(
|
|
3017
|
+
applicationAId.toString(),
|
|
3018
|
+
);
|
|
3019
|
+
expect(auditArgs["sessionId"]).toBe("session-1");
|
|
3020
|
+
expect(auditArgs["accessReason"]).toBe("incident triage");
|
|
3021
|
+
expect(auditArgs["ipAddress"]).toBe("203.0.113.7");
|
|
3022
|
+
|
|
3023
|
+
const body: JSONObject = result.jsonBody as JSONObject;
|
|
3024
|
+
expect(body["viewId"]).toBe(viewId.toString());
|
|
3025
|
+
|
|
3026
|
+
const tabs: Array<JSONObject> = body[
|
|
3027
|
+
"tabs"
|
|
3028
|
+
] as unknown as Array<JSONObject>;
|
|
3029
|
+
expect(tabs).toHaveLength(1);
|
|
3030
|
+
expect(tabs[0]!["chunkIndexes"]).toEqual([0, 3]);
|
|
3031
|
+
expect(tabs[0]!["fullSnapshotChunkIndexes"]).toEqual([0]);
|
|
3032
|
+
|
|
3033
|
+
/*
|
|
3034
|
+
* Every counter gets a DISTINCT nonzero value, asserted individually:
|
|
3035
|
+
* the client parses missing keys to 0, so a counter dropped from the
|
|
3036
|
+
* SELECT (or two counters cross-wired in the row mapping) fails
|
|
3037
|
+
* loudly here instead of silently blanking a timeline lane.
|
|
3038
|
+
*/
|
|
3039
|
+
const manifestChunks: Array<JSONObject> = tabs[0]![
|
|
3040
|
+
"chunks"
|
|
3041
|
+
] as unknown as Array<JSONObject>;
|
|
3042
|
+
expect(manifestChunks[0]!["errorCount"]).toBe(2);
|
|
3043
|
+
expect(manifestChunks[0]!["rageClickCount"]).toBe(1);
|
|
3044
|
+
expect(manifestChunks[0]!["deadClickCount"]).toBe(4);
|
|
3045
|
+
expect(manifestChunks[0]!["errorClickCount"]).toBe(6);
|
|
3046
|
+
expect(manifestChunks[0]!["refreshRageCount"]).toBe(5);
|
|
3047
|
+
expect(manifestChunks[0]!["routeCount"]).toBe(3);
|
|
3048
|
+
expect(manifestChunks[1]!["errorCount"]).toBe(0);
|
|
3049
|
+
|
|
3050
|
+
/*
|
|
3051
|
+
* The hole between chunk 0 and chunk 3 must be reported. Playback
|
|
3052
|
+
* that silently crosses a gap renders a DOM the user never saw.
|
|
3053
|
+
*/
|
|
3054
|
+
const gaps: Array<JSONObject> = tabs[0]![
|
|
3055
|
+
"gaps"
|
|
3056
|
+
] as unknown as Array<JSONObject>;
|
|
3057
|
+
expect(gaps).toHaveLength(1);
|
|
3058
|
+
expect(gaps[0]!["fromIndex"]).toBe(0);
|
|
3059
|
+
expect(gaps[0]!["toIndex"]).toBe(3);
|
|
3060
|
+
expect(gaps[0]!["missingMs"]).toBe(30000);
|
|
3061
|
+
});
|
|
3062
|
+
|
|
3063
|
+
test("a session that does not exist in this tenant is refused before any audit row", async () => {
|
|
3064
|
+
const principal: {
|
|
3065
|
+
request: JSONObject;
|
|
3066
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
3067
|
+
} = buildPrincipal({
|
|
3068
|
+
projectId: projectId,
|
|
3069
|
+
userId: userId,
|
|
3070
|
+
permissions: [Permission.ProjectOwner],
|
|
3071
|
+
});
|
|
3072
|
+
|
|
3073
|
+
mockProps(principal.databaseProps);
|
|
3074
|
+
headerQuerySpy.mockResolvedValue(fakeResultSet([]) as never);
|
|
3075
|
+
|
|
3076
|
+
const result: CallResult = await callRoute({
|
|
3077
|
+
uri: MANIFEST_ROUTE,
|
|
2346
3078
|
request: principal.request,
|
|
2347
3079
|
body: { sessionId: "does-not-exist" },
|
|
2348
3080
|
});
|
|
@@ -2499,8 +3231,134 @@ describe("Session replay playback API", () => {
|
|
|
2499
3231
|
clickCount: 2,
|
|
2500
3232
|
url: "https://example.com/help",
|
|
2501
3233
|
},
|
|
2502
|
-
]) as never,
|
|
2503
|
-
);
|
|
3234
|
+
]) as never,
|
|
3235
|
+
);
|
|
3236
|
+
|
|
3237
|
+
const result: CallResult = await callRoute({
|
|
3238
|
+
uri: MANIFEST_ROUTE,
|
|
3239
|
+
request: principal.request,
|
|
3240
|
+
body: { sessionId: "session-1" },
|
|
3241
|
+
});
|
|
3242
|
+
|
|
3243
|
+
const body: JSONObject = result.jsonBody as JSONObject;
|
|
3244
|
+
const header: JSONObject = body["header"] as JSONObject;
|
|
3245
|
+
|
|
3246
|
+
expect(header["startTimeUnixMs"]).toBe(1700000000000);
|
|
3247
|
+
expect(header["endTimeUnixMs"]).toBe(1700000060000);
|
|
3248
|
+
expect(header["clientReportedStartUnixMs"]).toBe(1699999999500);
|
|
3249
|
+
expect(header["tags"]).toEqual({ build: "1.2.3" });
|
|
3250
|
+
expect(header["expiresAtUnixMs"]).toBe(1700604800000);
|
|
3251
|
+
expect(header["clickCount"]).toBe(41);
|
|
3252
|
+
expect(header["customEventCount"]).toBe(3);
|
|
3253
|
+
expect(header["activeMs"]).toBe(36000);
|
|
3254
|
+
expect(header["firstErrorOffsetMs"]).toBe(12000);
|
|
3255
|
+
expect(header["recorderCapabilities"]).toEqual(["click-events", "tags"]);
|
|
3256
|
+
|
|
3257
|
+
const tabs: Array<JSONObject> = body[
|
|
3258
|
+
"tabs"
|
|
3259
|
+
] as unknown as Array<JSONObject>;
|
|
3260
|
+
expect(tabs[0]!["firstChunkStartOffsetMs"]).toBe(134000);
|
|
3261
|
+
const chunks: Array<JSONObject> = tabs[0]![
|
|
3262
|
+
"chunks"
|
|
3263
|
+
] as unknown as Array<JSONObject>;
|
|
3264
|
+
expect(chunks[0]!["clickCount"]).toBe(2);
|
|
3265
|
+
expect(chunks[0]!["url"]).toBe("https://example.com/help");
|
|
3266
|
+
});
|
|
3267
|
+
|
|
3268
|
+
/*
|
|
3269
|
+
* The pseudonymous digest and the visitor id are what the player hands
|
|
3270
|
+
* back to /list for "this person's other sessions". Neither names
|
|
3271
|
+
* anyone and the list already returns both to every list-capable
|
|
3272
|
+
* caller, so they ride on the header read itself for a caller WITHOUT
|
|
3273
|
+
* the identity permission - not on the separate, gated identity read.
|
|
3274
|
+
*/
|
|
3275
|
+
test("the header carries identifiedUserKey and visitorId for a caller without the identity permission", async () => {
|
|
3276
|
+
const principal: {
|
|
3277
|
+
request: JSONObject;
|
|
3278
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
3279
|
+
} = buildPrincipal({
|
|
3280
|
+
projectId: projectId,
|
|
3281
|
+
userId: userId,
|
|
3282
|
+
permissions: [Permission.TelemetryAdmin],
|
|
3283
|
+
});
|
|
3284
|
+
|
|
3285
|
+
mockProps(principal.databaseProps);
|
|
3286
|
+
headerQuerySpy.mockResolvedValue(
|
|
3287
|
+
fakeResultSet([
|
|
3288
|
+
{
|
|
3289
|
+
...buildHeaderRow({
|
|
3290
|
+
sessionId: "session-1",
|
|
3291
|
+
projectId: projectId,
|
|
3292
|
+
rumApplicationId: applicationAId,
|
|
3293
|
+
}),
|
|
3294
|
+
aggVisitorId: VISITOR_ID,
|
|
3295
|
+
},
|
|
3296
|
+
]) as never,
|
|
3297
|
+
);
|
|
3298
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
3299
|
+
mockRecordedView();
|
|
3300
|
+
|
|
3301
|
+
const result: CallResult = await callRoute({
|
|
3302
|
+
uri: MANIFEST_ROUTE,
|
|
3303
|
+
request: principal.request,
|
|
3304
|
+
body: { sessionId: "session-1" },
|
|
3305
|
+
});
|
|
3306
|
+
|
|
3307
|
+
/* One header read, and it is the one that projected both keys. */
|
|
3308
|
+
expect(headerQuerySpy).toHaveBeenCalledTimes(1);
|
|
3309
|
+
const statement: Statement = headerQuerySpy.mock
|
|
3310
|
+
.calls[0]![0] as Statement;
|
|
3311
|
+
expect(statement.query).toContain(
|
|
3312
|
+
"argMax(identifiedUserKey, version) AS aggIdentifiedUserKey",
|
|
3313
|
+
);
|
|
3314
|
+
expect(statement.query).toContain(
|
|
3315
|
+
"argMax(visitorId, version) AS aggVisitorId",
|
|
3316
|
+
);
|
|
3317
|
+
expect(statement.query).not.toContain("identifiedUserLabel");
|
|
3318
|
+
|
|
3319
|
+
const header: JSONObject = (result.jsonBody as JSONObject)[
|
|
3320
|
+
"header"
|
|
3321
|
+
] as JSONObject;
|
|
3322
|
+
expect(header["identifiedUserKey"]).toBe("hmac-key");
|
|
3323
|
+
expect(header["visitorId"]).toBe(VISITOR_ID);
|
|
3324
|
+
expect(header["identifiedUserLabel"]).toBeUndefined();
|
|
3325
|
+
expect(header["identifiedUserTraits"]).toBeUndefined();
|
|
3326
|
+
});
|
|
3327
|
+
|
|
3328
|
+
test("the header keeps identifiedUserKey and visitorId beside the label for an identity-permitted caller", async () => {
|
|
3329
|
+
const principal: {
|
|
3330
|
+
request: JSONObject;
|
|
3331
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
3332
|
+
} = buildPrincipal({
|
|
3333
|
+
projectId: projectId,
|
|
3334
|
+
userId: userId,
|
|
3335
|
+
permissions: [Permission.ProjectOwner],
|
|
3336
|
+
});
|
|
3337
|
+
|
|
3338
|
+
mockProps(principal.databaseProps);
|
|
3339
|
+
headerQuerySpy.mockImplementation(async (statement: Statement) => {
|
|
3340
|
+
if (statement.query.includes("identifiedUserTraits")) {
|
|
3341
|
+
return fakeResultSet([
|
|
3342
|
+
{
|
|
3343
|
+
aggIdentifiedUserLabel: "jane@example.com",
|
|
3344
|
+
aggIdentifiedUserTraits: { plan: "pro" },
|
|
3345
|
+
},
|
|
3346
|
+
]);
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
return fakeResultSet([
|
|
3350
|
+
{
|
|
3351
|
+
...buildHeaderRow({
|
|
3352
|
+
sessionId: "session-1",
|
|
3353
|
+
projectId: projectId,
|
|
3354
|
+
rumApplicationId: applicationAId,
|
|
3355
|
+
}),
|
|
3356
|
+
aggVisitorId: VISITOR_ID,
|
|
3357
|
+
},
|
|
3358
|
+
]);
|
|
3359
|
+
});
|
|
3360
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
3361
|
+
mockRecordedView();
|
|
2504
3362
|
|
|
2505
3363
|
const result: CallResult = await callRoute({
|
|
2506
3364
|
uri: MANIFEST_ROUTE,
|
|
@@ -2508,29 +3366,13 @@ describe("Session replay playback API", () => {
|
|
|
2508
3366
|
body: { sessionId: "session-1" },
|
|
2509
3367
|
});
|
|
2510
3368
|
|
|
2511
|
-
const
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
expect(header["
|
|
2515
|
-
expect(header["
|
|
2516
|
-
expect(header["
|
|
2517
|
-
expect(header["
|
|
2518
|
-
expect(header["expiresAtUnixMs"]).toBe(1700604800000);
|
|
2519
|
-
expect(header["clickCount"]).toBe(41);
|
|
2520
|
-
expect(header["customEventCount"]).toBe(3);
|
|
2521
|
-
expect(header["activeMs"]).toBe(36000);
|
|
2522
|
-
expect(header["firstErrorOffsetMs"]).toBe(12000);
|
|
2523
|
-
expect(header["recorderCapabilities"]).toEqual(["click-events", "tags"]);
|
|
2524
|
-
|
|
2525
|
-
const tabs: Array<JSONObject> = body[
|
|
2526
|
-
"tabs"
|
|
2527
|
-
] as unknown as Array<JSONObject>;
|
|
2528
|
-
expect(tabs[0]!["firstChunkStartOffsetMs"]).toBe(134000);
|
|
2529
|
-
const chunks: Array<JSONObject> = tabs[0]![
|
|
2530
|
-
"chunks"
|
|
2531
|
-
] as unknown as Array<JSONObject>;
|
|
2532
|
-
expect(chunks[0]!["clickCount"]).toBe(2);
|
|
2533
|
-
expect(chunks[0]!["url"]).toBe("https://example.com/help");
|
|
3369
|
+
const header: JSONObject = (result.jsonBody as JSONObject)[
|
|
3370
|
+
"header"
|
|
3371
|
+
] as JSONObject;
|
|
3372
|
+
expect(header["identifiedUserKey"]).toBe("hmac-key");
|
|
3373
|
+
expect(header["visitorId"]).toBe(VISITOR_ID);
|
|
3374
|
+
expect(header["identifiedUserLabel"]).toBe("jane@example.com");
|
|
3375
|
+
expect(header["identifiedUserTraits"]).toEqual({ plan: "pro" });
|
|
2534
3376
|
});
|
|
2535
3377
|
|
|
2536
3378
|
/*
|
|
@@ -3147,6 +3989,322 @@ describe("Session replay playback API", () => {
|
|
|
3147
3989
|
);
|
|
3148
3990
|
});
|
|
3149
3991
|
|
|
3992
|
+
/*
|
|
3993
|
+
* The payload column is stored decompressed and the body is
|
|
3994
|
+
* application/octet-stream, which nginx's gzip_types does not cover,
|
|
3995
|
+
* so the route must compress on the wire itself or a page ships as
|
|
3996
|
+
* 1-8 MB of raw JSON. The browser's fetch() inflates transparently,
|
|
3997
|
+
* so the decoded bytes must be the very same frames.
|
|
3998
|
+
*/
|
|
3999
|
+
test("gzips the frames when the caller accepts gzip", async () => {
|
|
4000
|
+
const principal: {
|
|
4001
|
+
request: JSONObject;
|
|
4002
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
4003
|
+
} = payloadPrincipal();
|
|
4004
|
+
|
|
4005
|
+
mockProps(principal.databaseProps);
|
|
4006
|
+
mockSessionHeader(applicationAId);
|
|
4007
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
4008
|
+
|
|
4009
|
+
const payload: string = "[" + "1,".repeat(600) + "1]";
|
|
4010
|
+
|
|
4011
|
+
chunkQuerySpy.mockResolvedValue(
|
|
4012
|
+
fakeResultSet([
|
|
4013
|
+
{ chunkIndex: 0, servedPayload: payload, isServed: 1 },
|
|
4014
|
+
{ chunkIndex: 1, servedPayload: "[22]", isServed: 1 },
|
|
4015
|
+
]) as never,
|
|
4016
|
+
);
|
|
4017
|
+
|
|
4018
|
+
const result: CallResult = await callRoute({
|
|
4019
|
+
uri: CHUNKS_ROUTE,
|
|
4020
|
+
request: principal.request,
|
|
4021
|
+
body: {
|
|
4022
|
+
sessionId: "session-1",
|
|
4023
|
+
tabId: "tab-1",
|
|
4024
|
+
chunkIndexes: [0, 1],
|
|
4025
|
+
},
|
|
4026
|
+
headers: { "accept-encoding": "gzip, deflate, br" },
|
|
4027
|
+
});
|
|
4028
|
+
|
|
4029
|
+
expect(result.thrownToNext).toBeUndefined();
|
|
4030
|
+
expect(result.deniedWith).toBeUndefined();
|
|
4031
|
+
|
|
4032
|
+
const sent: Buffer = result.sentBuffer as unknown as Buffer;
|
|
4033
|
+
expect(sent).toBeDefined();
|
|
4034
|
+
|
|
4035
|
+
expect(result.headers["Content-Encoding"]).toBe("gzip");
|
|
4036
|
+
expect(result.headers["Vary"]).toBe("Accept-Encoding");
|
|
4037
|
+
expect(result.headers["Content-Type"]).toBe("application/octet-stream");
|
|
4038
|
+
expect(result.headers["Cache-Control"]).toBe("no-store");
|
|
4039
|
+
// Content-Length describes the bytes actually sent, not the frames.
|
|
4040
|
+
expect(result.headers["Content-Length"]).toBe(String(sent.length));
|
|
4041
|
+
expect(sent.length).toBeLessThan(8 + payload.length);
|
|
4042
|
+
|
|
4043
|
+
const decoded: Buffer = zlib.gunzipSync(sent);
|
|
4044
|
+
expect(decoded.length).toBe(8 + payload.length + 8 + 4);
|
|
4045
|
+
expect(decoded.readUInt32LE(0)).toBe(0);
|
|
4046
|
+
expect(decoded.readUInt32LE(4)).toBe(payload.length);
|
|
4047
|
+
expect(decoded.subarray(8, 8 + payload.length).toString("utf8")).toBe(
|
|
4048
|
+
payload,
|
|
4049
|
+
);
|
|
4050
|
+
expect(decoded.readUInt32LE(8 + payload.length)).toBe(1);
|
|
4051
|
+
expect(decoded.readUInt32LE(12 + payload.length)).toBe(4);
|
|
4052
|
+
expect(decoded.subarray(16 + payload.length).toString("utf8")).toBe(
|
|
4053
|
+
"[22]",
|
|
4054
|
+
);
|
|
4055
|
+
});
|
|
4056
|
+
|
|
4057
|
+
test("honours a positive q-value and the x-gzip alias", async () => {
|
|
4058
|
+
const principal: {
|
|
4059
|
+
request: JSONObject;
|
|
4060
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
4061
|
+
} = payloadPrincipal();
|
|
4062
|
+
|
|
4063
|
+
mockProps(principal.databaseProps);
|
|
4064
|
+
mockSessionHeader(applicationAId);
|
|
4065
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
4066
|
+
|
|
4067
|
+
const payload: string = "[" + "1,".repeat(600) + "1]";
|
|
4068
|
+
|
|
4069
|
+
for (const acceptEncoding of [
|
|
4070
|
+
"deflate;q=1.0, gzip;q=0.5",
|
|
4071
|
+
"X-GZIP",
|
|
4072
|
+
" br , gzip ; q=0.1 ",
|
|
4073
|
+
]) {
|
|
4074
|
+
chunkQuerySpy.mockResolvedValue(
|
|
4075
|
+
fakeResultSet([
|
|
4076
|
+
{ chunkIndex: 0, servedPayload: payload, isServed: 1 },
|
|
4077
|
+
]) as never,
|
|
4078
|
+
);
|
|
4079
|
+
|
|
4080
|
+
const result: CallResult = await callRoute({
|
|
4081
|
+
uri: CHUNKS_ROUTE,
|
|
4082
|
+
request: principal.request,
|
|
4083
|
+
body: {
|
|
4084
|
+
sessionId: "session-1",
|
|
4085
|
+
tabId: "tab-1",
|
|
4086
|
+
chunkIndexes: [0],
|
|
4087
|
+
},
|
|
4088
|
+
headers: { "accept-encoding": acceptEncoding },
|
|
4089
|
+
});
|
|
4090
|
+
|
|
4091
|
+
expect(result.thrownToNext).toBeUndefined();
|
|
4092
|
+
expect(result.headers["Content-Encoding"]).toBe("gzip");
|
|
4093
|
+
|
|
4094
|
+
const decoded: Buffer = zlib.gunzipSync(
|
|
4095
|
+
result.sentBuffer as unknown as Buffer,
|
|
4096
|
+
);
|
|
4097
|
+
expect(decoded.readUInt32LE(4)).toBe(payload.length);
|
|
4098
|
+
}
|
|
4099
|
+
});
|
|
4100
|
+
|
|
4101
|
+
test("sends identity frames when Accept-Encoding is absent", async () => {
|
|
4102
|
+
const principal: {
|
|
4103
|
+
request: JSONObject;
|
|
4104
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
4105
|
+
} = payloadPrincipal();
|
|
4106
|
+
|
|
4107
|
+
mockProps(principal.databaseProps);
|
|
4108
|
+
mockSessionHeader(applicationAId);
|
|
4109
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
4110
|
+
|
|
4111
|
+
const payload: string = "[" + "1,".repeat(600) + "1]";
|
|
4112
|
+
|
|
4113
|
+
chunkQuerySpy.mockResolvedValue(
|
|
4114
|
+
fakeResultSet([
|
|
4115
|
+
{ chunkIndex: 0, servedPayload: payload, isServed: 1 },
|
|
4116
|
+
]) as never,
|
|
4117
|
+
);
|
|
4118
|
+
|
|
4119
|
+
const result: CallResult = await callRoute({
|
|
4120
|
+
uri: CHUNKS_ROUTE,
|
|
4121
|
+
request: principal.request,
|
|
4122
|
+
body: {
|
|
4123
|
+
sessionId: "session-1",
|
|
4124
|
+
tabId: "tab-1",
|
|
4125
|
+
chunkIndexes: [0],
|
|
4126
|
+
},
|
|
4127
|
+
});
|
|
4128
|
+
|
|
4129
|
+
const sent: Buffer = result.sentBuffer as unknown as Buffer;
|
|
4130
|
+
|
|
4131
|
+
expect(result.headers["Content-Encoding"]).toBeUndefined();
|
|
4132
|
+
// The answer still depends on the request header, so Vary is set.
|
|
4133
|
+
expect(result.headers["Vary"]).toBe("Accept-Encoding");
|
|
4134
|
+
expect(result.headers["Content-Length"]).toBe(String(8 + payload.length));
|
|
4135
|
+
expect(sent.length).toBe(8 + payload.length);
|
|
4136
|
+
expect(sent.readUInt32LE(0)).toBe(0);
|
|
4137
|
+
expect(sent.readUInt32LE(4)).toBe(payload.length);
|
|
4138
|
+
});
|
|
4139
|
+
|
|
4140
|
+
test("sends identity frames when only br and deflate are accepted", async () => {
|
|
4141
|
+
const principal: {
|
|
4142
|
+
request: JSONObject;
|
|
4143
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
4144
|
+
} = payloadPrincipal();
|
|
4145
|
+
|
|
4146
|
+
mockProps(principal.databaseProps);
|
|
4147
|
+
mockSessionHeader(applicationAId);
|
|
4148
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
4149
|
+
|
|
4150
|
+
const payload: string = "[" + "1,".repeat(600) + "1]";
|
|
4151
|
+
|
|
4152
|
+
chunkQuerySpy.mockResolvedValue(
|
|
4153
|
+
fakeResultSet([
|
|
4154
|
+
{ chunkIndex: 0, servedPayload: payload, isServed: 1 },
|
|
4155
|
+
]) as never,
|
|
4156
|
+
);
|
|
4157
|
+
|
|
4158
|
+
const result: CallResult = await callRoute({
|
|
4159
|
+
uri: CHUNKS_ROUTE,
|
|
4160
|
+
request: principal.request,
|
|
4161
|
+
body: {
|
|
4162
|
+
sessionId: "session-1",
|
|
4163
|
+
tabId: "tab-1",
|
|
4164
|
+
chunkIndexes: [0],
|
|
4165
|
+
},
|
|
4166
|
+
headers: { "accept-encoding": "br, deflate" },
|
|
4167
|
+
});
|
|
4168
|
+
|
|
4169
|
+
const sent: Buffer = result.sentBuffer as unknown as Buffer;
|
|
4170
|
+
|
|
4171
|
+
expect(result.headers["Content-Encoding"]).toBeUndefined();
|
|
4172
|
+
expect(result.headers["Vary"]).toBe("Accept-Encoding");
|
|
4173
|
+
expect(sent.length).toBe(8 + payload.length);
|
|
4174
|
+
expect(sent.readUInt32LE(4)).toBe(payload.length);
|
|
4175
|
+
});
|
|
4176
|
+
|
|
4177
|
+
test("gzip;q=0 is an explicit refusal of gzip", async () => {
|
|
4178
|
+
const principal: {
|
|
4179
|
+
request: JSONObject;
|
|
4180
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
4181
|
+
} = payloadPrincipal();
|
|
4182
|
+
|
|
4183
|
+
mockProps(principal.databaseProps);
|
|
4184
|
+
mockSessionHeader(applicationAId);
|
|
4185
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
4186
|
+
|
|
4187
|
+
const payload: string = "[" + "1,".repeat(600) + "1]";
|
|
4188
|
+
|
|
4189
|
+
for (const acceptEncoding of ["gzip;q=0", "gzip;q=0.0, identity"]) {
|
|
4190
|
+
chunkQuerySpy.mockResolvedValue(
|
|
4191
|
+
fakeResultSet([
|
|
4192
|
+
{ chunkIndex: 0, servedPayload: payload, isServed: 1 },
|
|
4193
|
+
]) as never,
|
|
4194
|
+
);
|
|
4195
|
+
|
|
4196
|
+
const result: CallResult = await callRoute({
|
|
4197
|
+
uri: CHUNKS_ROUTE,
|
|
4198
|
+
request: principal.request,
|
|
4199
|
+
body: {
|
|
4200
|
+
sessionId: "session-1",
|
|
4201
|
+
tabId: "tab-1",
|
|
4202
|
+
chunkIndexes: [0],
|
|
4203
|
+
},
|
|
4204
|
+
headers: { "accept-encoding": acceptEncoding },
|
|
4205
|
+
});
|
|
4206
|
+
|
|
4207
|
+
const sent: Buffer = result.sentBuffer as unknown as Buffer;
|
|
4208
|
+
|
|
4209
|
+
expect(result.headers["Content-Encoding"]).toBeUndefined();
|
|
4210
|
+
expect(sent.length).toBe(8 + payload.length);
|
|
4211
|
+
expect(sent.readUInt32LE(4)).toBe(payload.length);
|
|
4212
|
+
}
|
|
4213
|
+
});
|
|
4214
|
+
|
|
4215
|
+
/* Mirrors nginx's gzip_min_length: a tiny page gains nothing. */
|
|
4216
|
+
test("does not gzip a page below the minimum size even when gzip is accepted", async () => {
|
|
4217
|
+
const principal: {
|
|
4218
|
+
request: JSONObject;
|
|
4219
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
4220
|
+
} = payloadPrincipal();
|
|
4221
|
+
|
|
4222
|
+
mockProps(principal.databaseProps);
|
|
4223
|
+
mockSessionHeader(applicationAId);
|
|
4224
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
4225
|
+
|
|
4226
|
+
chunkQuerySpy.mockResolvedValue(
|
|
4227
|
+
fakeResultSet([
|
|
4228
|
+
{ chunkIndex: 0, servedPayload: "[1]", isServed: 1 },
|
|
4229
|
+
]) as never,
|
|
4230
|
+
);
|
|
4231
|
+
|
|
4232
|
+
const result: CallResult = await callRoute({
|
|
4233
|
+
uri: CHUNKS_ROUTE,
|
|
4234
|
+
request: principal.request,
|
|
4235
|
+
body: {
|
|
4236
|
+
sessionId: "session-1",
|
|
4237
|
+
tabId: "tab-1",
|
|
4238
|
+
chunkIndexes: [0],
|
|
4239
|
+
},
|
|
4240
|
+
headers: { "accept-encoding": "gzip, deflate, br" },
|
|
4241
|
+
});
|
|
4242
|
+
|
|
4243
|
+
const sent: Buffer = result.sentBuffer as unknown as Buffer;
|
|
4244
|
+
|
|
4245
|
+
expect(result.headers["Content-Encoding"]).toBeUndefined();
|
|
4246
|
+
expect(result.headers["Vary"]).toBe("Accept-Encoding");
|
|
4247
|
+
expect(result.headers["Content-Length"]).toBe("11");
|
|
4248
|
+
expect(sent.length).toBe(11);
|
|
4249
|
+
expect(sent.readUInt32LE(0)).toBe(0);
|
|
4250
|
+
expect(sent.readUInt32LE(4)).toBe(3);
|
|
4251
|
+
expect(sent.subarray(8, 11).toString("utf8")).toBe("[1]");
|
|
4252
|
+
});
|
|
4253
|
+
|
|
4254
|
+
/*
|
|
4255
|
+
* The read cap bounds what the player must hold decoded in memory,
|
|
4256
|
+
* so it and the omitted list are judged on the uncompressed frames:
|
|
4257
|
+
* two 5 MiB chunks of one repeated byte gzip to a few KB, yet only
|
|
4258
|
+
* the first may be served.
|
|
4259
|
+
*/
|
|
4260
|
+
test("judges the read cap and the omitted-chunks header on the uncompressed frames when compressing", async () => {
|
|
4261
|
+
const principal: {
|
|
4262
|
+
request: JSONObject;
|
|
4263
|
+
databaseProps: DatabaseCommonInteractionProps;
|
|
4264
|
+
} = payloadPrincipal();
|
|
4265
|
+
|
|
4266
|
+
mockProps(principal.databaseProps);
|
|
4267
|
+
mockSessionHeader(applicationAId);
|
|
4268
|
+
mockApplication({ id: applicationAId, labelIds: [] });
|
|
4269
|
+
|
|
4270
|
+
const fatPayload: string = "a".repeat(5 * 1024 * 1024);
|
|
4271
|
+
|
|
4272
|
+
chunkQuerySpy.mockResolvedValue(
|
|
4273
|
+
fakeResultSet([
|
|
4274
|
+
{ chunkIndex: 0, servedPayload: fatPayload, isServed: 1 },
|
|
4275
|
+
{ chunkIndex: 1, servedPayload: fatPayload, isServed: 1 },
|
|
4276
|
+
{ chunkIndex: 2, servedPayload: "", isServed: 0 },
|
|
4277
|
+
]) as never,
|
|
4278
|
+
);
|
|
4279
|
+
|
|
4280
|
+
const result: CallResult = await callRoute({
|
|
4281
|
+
uri: CHUNKS_ROUTE,
|
|
4282
|
+
request: principal.request,
|
|
4283
|
+
body: {
|
|
4284
|
+
sessionId: "session-1",
|
|
4285
|
+
tabId: "tab-1",
|
|
4286
|
+
chunkIndexes: [0, 1, 2],
|
|
4287
|
+
},
|
|
4288
|
+
headers: { "accept-encoding": "gzip, deflate, br" },
|
|
4289
|
+
});
|
|
4290
|
+
|
|
4291
|
+
expect(result.thrownToNext).toBeUndefined();
|
|
4292
|
+
expect(result.deniedWith).toBeUndefined();
|
|
4293
|
+
|
|
4294
|
+
const sent: Buffer = result.sentBuffer as unknown as Buffer;
|
|
4295
|
+
|
|
4296
|
+
expect(result.headers["Content-Encoding"]).toBe("gzip");
|
|
4297
|
+
expect(result.headers["Content-Length"]).toBe(String(sent.length));
|
|
4298
|
+
expect(sent.length).toBeLessThan(fatPayload.length);
|
|
4299
|
+
expect(result.headers["X-OneUptime-Replay-Omitted-Chunks"]).toBe("1,2");
|
|
4300
|
+
expect(result.headers["Cache-Control"]).toBe("no-store");
|
|
4301
|
+
|
|
4302
|
+
const decoded: Buffer = zlib.gunzipSync(sent);
|
|
4303
|
+
expect(decoded.readUInt32LE(0)).toBe(0);
|
|
4304
|
+
expect(decoded.readUInt32LE(4)).toBe(fatPayload.length);
|
|
4305
|
+
expect(decoded.length).toBe(8 + fatPayload.length);
|
|
4306
|
+
});
|
|
4307
|
+
|
|
3150
4308
|
test("rejects a non-integer chunk index", async () => {
|
|
3151
4309
|
const principal: {
|
|
3152
4310
|
request: JSONObject;
|