@oneuptime/common 14.0.9 → 14.0.10
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/DatabaseModels/AutoRemediationSuggestion.ts +60 -0
- package/Models/DatabaseModels/CephCluster.ts +213 -0
- package/Models/DatabaseModels/DatabaseServer.ts +213 -0
- package/Models/DatabaseModels/DockerHost.ts +213 -0
- package/Models/DatabaseModels/DockerSwarmCluster.ts +213 -0
- package/Models/DatabaseModels/GlobalConfig.ts +1 -1
- package/Models/DatabaseModels/Host.ts +213 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/PodmanHost.ts +213 -0
- package/Models/DatabaseModels/ProxmoxCluster.ts +213 -0
- package/Models/DatabaseModels/ResourceAiAgent.ts +419 -0
- package/Models/DatabaseModels/RunnerJob.ts +144 -0
- package/Models/DatabaseModels/VMwareVCenter.ts +213 -0
- package/Server/API/AutoRemediationAPI.ts +392 -1
- package/Server/API/ResourceAiAccessAPI.ts +1669 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.ts +423 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Infrastructure/Semaphore.ts +22 -0
- package/Server/Middleware/TelemetryIngest.ts +15 -5
- package/Server/Services/AnalyticsDatabaseService.ts +45 -1
- package/Server/Services/AutoRemediationRuleEngineService.ts +940 -112
- package/Server/Services/CephClusterService.ts +109 -1
- package/Server/Services/DatabaseServerService.ts +116 -1
- package/Server/Services/DockerHostService.ts +109 -1
- package/Server/Services/DockerSwarmClusterService.ts +113 -1
- package/Server/Services/HostService.ts +126 -4
- package/Server/Services/MetricRecordingRuleService.ts +47 -0
- package/Server/Services/PodmanHostService.ts +109 -1
- package/Server/Services/ProxmoxClusterService.ts +110 -1
- package/Server/Services/ResourceAiAccessService.ts +1439 -0
- package/Server/Services/ResourceAiAgentJobService.ts +202 -0
- package/Server/Services/ResourceAiAgentService.ts +2432 -0
- package/Server/Services/RunnerJobService.ts +611 -4
- package/Server/Services/TelemetryUsageBillingService.ts +28 -0
- package/Server/Services/TraceRecordingRuleService.ts +33 -0
- package/Server/Services/VMwareVCenterService.ts +110 -1
- package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1434 -32
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +935 -21
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +25 -1
- package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +577 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessContext.ts +271 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.ts +45 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.ts +964 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.ts +333 -0
- package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +873 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +72 -2
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +72 -5
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +72 -5
- package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +396 -13
- package/Server/Utils/AutoRemediation/RemediationVerifier.ts +35 -2
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +9 -1
- package/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.ts +920 -0
- package/Server/Utils/SessionReplay/SessionReplayUsage.ts +84 -6
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +35 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +33 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +21 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +298 -224
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +35 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +389 -175
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +366 -143
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.ts +163 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.ts +396 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.ts +418 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.ts +152 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.ts +251 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.ts +214 -0
- package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +93 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +18 -6
- package/Tests/App/Dashboard/InvestigationInfrastructureTools.test.tsx +506 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardDescription.test.tsx +209 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardResource.test.tsx +317 -0
- package/Tests/App/Dashboard/ResourceAiAccessSettingsUtil.test.ts +921 -0
- package/Tests/App/Dashboard/ResourceAiAgentInstall.test.ts +860 -0
- package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +1721 -0
- package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +1002 -0
- package/Tests/App/Dashboard/ResourceAiInsightsPage.test.tsx +931 -0
- package/Tests/App/Dashboard/ResourceAiNavigation.test.tsx +575 -0
- package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +38 -7
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +33 -1
- package/Tests/Models/DatabaseModels/ResourceAiAccessColumns.test.ts +738 -0
- package/Tests/Models/DatabaseModels/ResourceAiAgentModel.test.ts +842 -0
- package/Tests/Server/API/AutoRemediationApproveResourceRound.test.ts +835 -0
- package/Tests/Server/API/ResourceAiAccessAPI.test.ts +2730 -0
- package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +60 -0
- package/Tests/Server/Infrastructure/Postgres/AddResourceAiAgentsMigration.test.ts +659 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +31 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +63 -5
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +103 -5
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +19 -1
- package/Tests/Server/Services/AutoRemediationResourceRuleEngine.test.ts +1279 -0
- package/Tests/Server/Services/DatabaseServerService.test.ts +55 -0
- package/Tests/Server/Services/GroupTelemetryUsageExcludeNames.test.ts +299 -0
- package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +44 -0
- package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +45 -6
- package/Tests/Server/Services/RecordingRuleReservedMetricName.test.ts +171 -0
- package/Tests/Server/Services/ResourceAiAccessChangeAuthorization.test.ts +256 -0
- package/Tests/Server/Services/ResourceAiAccessService.test.ts +1373 -0
- package/Tests/Server/Services/ResourceAiAgentJobService.test.ts +375 -0
- package/Tests/Server/Services/ResourceAiAgentServiceHelpers.test.ts +1114 -0
- package/Tests/Server/Services/ResourceAiAgentServiceLifecycle.test.ts +1050 -0
- package/Tests/Server/Services/ResourceAiAgentServiceRegister.test.ts +2251 -0
- package/Tests/Server/Services/ResourceAiSettingsCreate.test.ts +373 -0
- package/Tests/Server/Services/ResourceAiSettingsPermission.test.ts +1042 -0
- package/Tests/Server/Services/ResourceServiceDeleteCleansUpAi.test.ts +319 -0
- package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +105 -0
- package/Tests/Server/Services/RunnerJobEnqueueResourceCommand.test.ts +986 -0
- package/Tests/Server/Services/RunnerJobResourceCommandLane.test.ts +211 -0
- package/Tests/Server/Services/RunnerJobResourceCommandTimeoutAndRedaction.test.ts +352 -0
- package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +218 -0
- package/Tests/Server/TestingUtils/Services/FakeRunnerJobCount.ts +145 -0
- package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +453 -0
- package/Tests/Server/Utils/AI/InvestigationInfrastructureReport.test.ts +721 -0
- package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +94 -1
- package/Tests/Server/Utils/AI/RemediationCommandToolsResource.test.ts +1530 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +1249 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +117 -0
- package/Tests/Server/Utils/AI/RemediationResourceCopyParity.test.ts +463 -0
- package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +722 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAccessContext.test.ts +266 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.test.ts +1220 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.test.ts +569 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +830 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorResource.test.ts +717 -0
- package/Tests/Server/Utils/AutoRemediation/RemediationVerifierResourceFollowUp.test.ts +338 -0
- package/Tests/Server/Utils/Monitor/Criteria/SessionReplayBudgetTemplateCriteria.test.ts +422 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.test.ts +1647 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +143 -1
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +33 -3
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsAccountNotLinked.test.ts +1093 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.test.ts +1049 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.test.ts +1676 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCards.test.ts +2884 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.test.ts +2490 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmit.test.ts +2293 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmitServerTimezone.test.ts +386 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.test.ts +1477 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.test.ts +1967 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsStripHtmlTags.test.ts +92 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsSubmittedFormRemoval.test.ts +1819 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.test.ts +1033 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezoneServerZone.test.ts +610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsBotMessageHandling.test.ts +2610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsCreateCommandsEndToEnd.test.ts +4672 -0
- package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +190 -65
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +10 -4
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlanResourceCommand.test.ts +305 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +277 -13
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +113 -0
- package/Tests/Types/Monitor/RumAlertTemplates.test.ts +773 -2
- package/Tests/Types/ResourceAiAgent/AiResourceType.test.ts +419 -0
- package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +517 -0
- package/Tests/Types/Runbook/RunbookStepType.test.ts +147 -8
- package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +769 -1
- package/Tests/Utils/AiRemediation/Resource/CephCommandPolicy.test.ts +1653 -0
- package/Tests/Utils/AiRemediation/Resource/CephOutputRedaction.test.ts +204 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseCommandPolicy.test.ts +1077 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.test.ts +558 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseQueryRedactor.test.ts +834 -0
- package/Tests/Utils/AiRemediation/Resource/DockerCliGrammar.test.ts +747 -0
- package/Tests/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.test.ts +1259 -0
- package/Tests/Utils/AiRemediation/Resource/DockerOutputRedaction.test.ts +386 -0
- package/Tests/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.test.ts +782 -0
- package/Tests/Utils/AiRemediation/Resource/GovcCommandPolicy.test.ts +2259 -0
- package/Tests/Utils/AiRemediation/Resource/HostCommandPolicy.test.ts +2019 -0
- package/Tests/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.test.ts +2497 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicy.test.ts +1305 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.test.ts +585 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactor.test.ts +334 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactorCopyParity.test.ts +98 -0
- package/Tests/Utils/AiRemediation/Resource/ResourcePolicyImportClosure.test.ts +391 -0
- package/Tests/Utils/AiRemediation/ResourceAiAgentPolicyCopyParity.test.ts +497 -0
- package/Tests/Utils/SessionReplay/SessionReplayBudgetMetricType.test.ts +383 -0
- package/Types/AI/ResourceAiAccessApi.ts +140 -0
- package/Types/AI/ResourceAiAccessPermissions.ts +126 -0
- package/Types/AutoRemediation/AiRemediationCommandPlan.ts +183 -2
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +55 -22
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +35 -3
- package/Types/Monitor/RumAlertTemplates.ts +351 -4
- package/Types/ResourceAiAgent/AiResourceType.ts +310 -0
- package/Types/ResourceAiAgent/ResourceAiAccess.ts +574 -0
- package/Types/Rum/SessionReplayBudgetMetricType.ts +47 -0
- package/Types/Runbook/RunbookStepType.ts +29 -0
- package/Types/Telemetry/TelemetryIngestSurface.ts +14 -2
- package/Utils/AI/InvestigationReport.ts +121 -15
- package/Utils/AiRemediation/Resource/CephCommandPolicy.ts +1936 -0
- package/Utils/AiRemediation/Resource/DatabaseCommandPolicy.ts +166 -0
- package/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.ts +1532 -0
- package/Utils/AiRemediation/Resource/DatabaseQueryRedactor.ts +1394 -0
- package/Utils/AiRemediation/Resource/DockerCliGrammar.ts +1839 -0
- package/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.ts +490 -0
- package/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.ts +687 -0
- package/Utils/AiRemediation/Resource/GovcCommandPolicy.ts +2096 -0
- package/Utils/AiRemediation/Resource/HostCommandPolicy.ts +2982 -0
- package/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.ts +1679 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicy.ts +851 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.ts +593 -0
- package/Utils/AiRemediation/Resource/ResourceOutputRedactor.ts +2812 -0
- package/Utils/SessionReplay/SessionReplayBudgetMetricType.ts +184 -0
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +219 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +219 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +219 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +219 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +219 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHost.js +219 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +219 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js +439 -0
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js +145 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +219 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
- package/build/dist/Server/API/AutoRemediationAPI.js +231 -1
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- package/build/dist/Server/API/ResourceAiAccessAPI.js +1119 -0
- package/build/dist/Server/API/ResourceAiAccessAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js +168 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +6 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +12 -5
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +26 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +601 -3
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +104 -0
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerService.js +99 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +104 -0
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +104 -0
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +114 -2
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/MetricRecordingRuleService.js +46 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +104 -0
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +104 -0
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ResourceAiAccessService.js +1028 -0
- package/build/dist/Server/Services/ResourceAiAccessService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js +173 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js +1687 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/RunnerJobService.js +344 -5
- package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +26 -0
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceRecordingRuleService.js +37 -0
- package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterService.js +104 -0
- package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1029 -30
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +633 -28
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +21 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +330 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js +160 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js +33 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js +640 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js +226 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +600 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +50 -4
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +55 -4
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +55 -4
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +290 -13
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +29 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +9 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js +627 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +60 -5
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +17 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +183 -209
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +233 -167
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +263 -110
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js +129 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js +266 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js +258 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js +104 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js +183 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js +123 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js +30 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js +98 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js.map +1 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +116 -29
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +47 -21
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +5 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/RumAlertTemplates.js +199 -3
- package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js +242 -0
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js.map +1 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +275 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js +45 -0
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookStepType.js +27 -0
- package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +13 -2
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
- package/build/dist/Utils/AI/InvestigationReport.js +71 -11
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js +1462 -0
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js +122 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js +1139 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js +1060 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js +1301 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js +370 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js +498 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js +1565 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js +2206 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js +1129 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js +565 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js +408 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js +1910 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js.map +1 -0
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js +160 -0
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js.map +1 -0
- package/package.json +1 -1
|
@@ -52,6 +52,28 @@ import KubectlJobRunner, {
|
|
|
52
52
|
KubectlTerminalJobFacts,
|
|
53
53
|
} from "../AI/ClusterAccess/KubectlJobRunner";
|
|
54
54
|
import RemediationCommandToolkit from "../AI/Remediation/RemediationCommandTools";
|
|
55
|
+
import ResourceCommandJobRunner, {
|
|
56
|
+
ResourceCommandRunState,
|
|
57
|
+
ResourceCommandTerminalJobFacts,
|
|
58
|
+
} from "../AI/ResourceAccess/ResourceCommandJobRunner";
|
|
59
|
+
import AiResourceType, {
|
|
60
|
+
AI_RESOURCE_TYPE_INFO,
|
|
61
|
+
isAiResourceType,
|
|
62
|
+
} from "../../../Types/ResourceAiAgent/AiResourceType";
|
|
63
|
+
import {
|
|
64
|
+
ResourceAiAccessGap,
|
|
65
|
+
ResourceAiAccessStatus,
|
|
66
|
+
ResourceAiRemediationMode,
|
|
67
|
+
ResourceCommandTier,
|
|
68
|
+
} from "../../../Types/ResourceAiAgent/ResourceAiAccess";
|
|
69
|
+
import ResourceCommandPolicy from "../../../Utils/AiRemediation/Resource/ResourceCommandPolicy";
|
|
70
|
+
import {
|
|
71
|
+
ResourceAutoExecutionVerdict,
|
|
72
|
+
ResourceCommandPolicyResult,
|
|
73
|
+
} from "../../../Utils/AiRemediation/Resource/ResourceCommandPolicyCore";
|
|
74
|
+
import ResourceAiAccessService, {
|
|
75
|
+
describeResourceNoun,
|
|
76
|
+
} from "../../Services/ResourceAiAccessService";
|
|
55
77
|
import logger from "../Logger";
|
|
56
78
|
import CaptureSpan from "../Telemetry/CaptureSpan";
|
|
57
79
|
|
|
@@ -510,6 +532,26 @@ export default class CommandPlanExecutor {
|
|
|
510
532
|
anyFailed = true;
|
|
511
533
|
}
|
|
512
534
|
|
|
535
|
+
/*
|
|
536
|
+
* The same for a resource command recorded as failed: its job is read
|
|
537
|
+
* the way every resource job is read
|
|
538
|
+
* (ResourceCommandJobRunner.getRunStateOfJobRow), and one that may
|
|
539
|
+
* have changed the resource is left for a human, never undone blind.
|
|
540
|
+
*/
|
|
541
|
+
for (const command of await this.reconcileFailedResourceExecutions(
|
|
542
|
+
suggestion,
|
|
543
|
+
plan,
|
|
544
|
+
)) {
|
|
545
|
+
command.rollbackExecution = {
|
|
546
|
+
status: AiRemediationCommandExecutionStatus.Skipped,
|
|
547
|
+
errorMessage: `Rollback not run: the command reached the resource's AI agent but it did not report a finished result, so whether it changed the ${this.describeCommandResourceNoun(
|
|
548
|
+
command,
|
|
549
|
+
)} is unknown. If it did, undo it manually: ${command.rollbackCommand}`,
|
|
550
|
+
};
|
|
551
|
+
leftForHuman.push(command);
|
|
552
|
+
anyFailed = true;
|
|
553
|
+
}
|
|
554
|
+
|
|
513
555
|
if (
|
|
514
556
|
plan.commands.some((command: AiRemediationCommand) => {
|
|
515
557
|
return (
|
|
@@ -561,6 +603,7 @@ export default class CommandPlanExecutor {
|
|
|
561
603
|
const denyReason: string | null = this.getDenyReason({
|
|
562
604
|
stepType: command.stepType,
|
|
563
605
|
command: rollbackCommand,
|
|
606
|
+
resourceType: command.resourceType,
|
|
564
607
|
});
|
|
565
608
|
|
|
566
609
|
if (denyReason) {
|
|
@@ -581,13 +624,25 @@ export default class CommandPlanExecutor {
|
|
|
581
624
|
* stopped bypassing them; a cluster whose remediation was turned
|
|
582
625
|
* off must not be changed at all. Left for a human, and said so.
|
|
583
626
|
*/
|
|
627
|
+
/*
|
|
628
|
+
* The same for a resource: its AI page as it is NOW, its agent, the
|
|
629
|
+
* agent's write scope, and the resource's CURRENT mode and
|
|
630
|
+
* allowlist (getResourceExecutionRefusal). Null for kubectl and
|
|
631
|
+
* Bash/SSH, which the cluster re-check above covers.
|
|
632
|
+
*/
|
|
584
633
|
const clusterRefusal: string | null =
|
|
585
|
-
await this.getClusterExecutionRefusal({
|
|
634
|
+
(await this.getClusterExecutionRefusal({
|
|
586
635
|
suggestion,
|
|
587
636
|
command,
|
|
588
637
|
commandText: rollbackCommand,
|
|
589
638
|
purpose: "rollback",
|
|
590
|
-
})
|
|
639
|
+
})) ||
|
|
640
|
+
(await this.getResourceExecutionRefusal({
|
|
641
|
+
suggestion,
|
|
642
|
+
command,
|
|
643
|
+
commandText: rollbackCommand,
|
|
644
|
+
purpose: "rollback",
|
|
645
|
+
}));
|
|
591
646
|
|
|
592
647
|
if (clusterRefusal) {
|
|
593
648
|
command.rollbackExecution = {
|
|
@@ -630,6 +685,7 @@ export default class CommandPlanExecutor {
|
|
|
630
685
|
command.rollbackExecution,
|
|
631
686
|
terminalJob,
|
|
632
687
|
"Rollback",
|
|
688
|
+
command,
|
|
633
689
|
);
|
|
634
690
|
if (
|
|
635
691
|
command.rollbackExecution.status !==
|
|
@@ -666,7 +722,13 @@ export default class CommandPlanExecutor {
|
|
|
666
722
|
suggestion,
|
|
667
723
|
markdown:
|
|
668
724
|
leftForHuman.length > 0
|
|
669
|
-
? `⚠️ **Auto-remediation rollback was not run for ${leftForHuman.length} command(s)** — the
|
|
725
|
+
? `⚠️ **Auto-remediation rollback was not run for ${leftForHuman.length} command(s)** — the ${
|
|
726
|
+
leftForHuman.every((command: AiRemediationCommand): boolean => {
|
|
727
|
+
return command.stepType === RunbookStepType.ResourceCommand;
|
|
728
|
+
})
|
|
729
|
+
? this.describeCommandResourceNoun(leftForHuman[0]!)
|
|
730
|
+
: "cluster"
|
|
731
|
+
} no longer allows them unattended, or whether they ran could not be confirmed, so a human has to undo them. ${leftForHuman
|
|
670
732
|
.map((command: AiRemediationCommand) => {
|
|
671
733
|
return this.capForFeed(
|
|
672
734
|
command.rollbackExecution?.errorMessage || "",
|
|
@@ -730,6 +792,7 @@ export default class CommandPlanExecutor {
|
|
|
730
792
|
const denyReason: string | null = this.getDenyReason({
|
|
731
793
|
stepType: command.stepType,
|
|
732
794
|
command: command.command,
|
|
795
|
+
resourceType: command.resourceType,
|
|
733
796
|
});
|
|
734
797
|
|
|
735
798
|
if (denyReason) {
|
|
@@ -747,16 +810,23 @@ export default class CommandPlanExecutor {
|
|
|
747
810
|
* Execution-time cluster re-check: the approve API re-checks the
|
|
748
811
|
* project switches, this re-checks the cluster's own AI page. An
|
|
749
812
|
* operator who turned remediation off, or bound a different Runner,
|
|
750
|
-
* after the plan was composed expects that to stop the plan too.
|
|
813
|
+
* after the plan was composed expects that to stop the plan too. A
|
|
814
|
+
* resource command gets the same re-check against its resource's AI
|
|
815
|
+
* page and agent (getResourceExecutionRefusal).
|
|
751
816
|
*/
|
|
752
|
-
const clusterRefusal: string | null =
|
|
753
|
-
{
|
|
817
|
+
const clusterRefusal: string | null =
|
|
818
|
+
(await this.getClusterExecutionRefusal({
|
|
754
819
|
suggestion,
|
|
755
820
|
command,
|
|
756
821
|
commandText: command.command,
|
|
757
822
|
purpose: "command",
|
|
758
|
-
}
|
|
759
|
-
|
|
823
|
+
})) ||
|
|
824
|
+
(await this.getResourceExecutionRefusal({
|
|
825
|
+
suggestion,
|
|
826
|
+
command,
|
|
827
|
+
commandText: command.command,
|
|
828
|
+
purpose: "command",
|
|
829
|
+
}));
|
|
760
830
|
|
|
761
831
|
if (clusterRefusal) {
|
|
762
832
|
return {
|
|
@@ -839,7 +909,7 @@ export default class CommandPlanExecutor {
|
|
|
839
909
|
throw new Error("Command job did not reach a terminal state.");
|
|
840
910
|
}
|
|
841
911
|
|
|
842
|
-
this.settleFromJob(state, terminalJob, "Command");
|
|
912
|
+
this.settleFromJob(state, terminalJob, "Command", command);
|
|
843
913
|
facts = {
|
|
844
914
|
status: terminalJob.status,
|
|
845
915
|
exitCode: terminalJob.exitCode,
|
|
@@ -881,14 +951,61 @@ export default class CommandPlanExecutor {
|
|
|
881
951
|
});
|
|
882
952
|
}
|
|
883
953
|
|
|
954
|
+
/*
|
|
955
|
+
* The same rule for a resource's "Last error": a success, or a failure
|
|
956
|
+
* about the resource's ACCESS as its program reports it
|
|
957
|
+
* (ResourceCommandJobRunner.isAccessFailure, with the program's own
|
|
958
|
+
* patterns).
|
|
959
|
+
*/
|
|
960
|
+
if (
|
|
961
|
+
started.recordsClusterOutcome &&
|
|
962
|
+
command.stepType === RunbookStepType.ResourceCommand &&
|
|
963
|
+
isAiResourceType(command.resourceType) &&
|
|
964
|
+
command.resourceId &&
|
|
965
|
+
ObjectID.isValidUUID(command.resourceId)
|
|
966
|
+
) {
|
|
967
|
+
const resourceFacts: ResourceCommandTerminalJobFacts | null = facts
|
|
968
|
+
? { ...facts, program: this.getCommandProgram(command.command) }
|
|
969
|
+
: null;
|
|
970
|
+
const recordsResourceOutcome: boolean =
|
|
971
|
+
succeeded ||
|
|
972
|
+
(resourceFacts !== null &&
|
|
973
|
+
ResourceCommandJobRunner.isAccessFailure(resourceFacts));
|
|
974
|
+
|
|
975
|
+
if (recordsResourceOutcome) {
|
|
976
|
+
await ResourceAiAccessService.recordCommandOutcome({
|
|
977
|
+
resourceType: command.resourceType,
|
|
978
|
+
resourceId: new ObjectID(command.resourceId),
|
|
979
|
+
succeeded,
|
|
980
|
+
errorMessage: state.errorMessage,
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
884
985
|
return state;
|
|
885
986
|
}
|
|
886
987
|
|
|
988
|
+
// argv[0] of a resource command, for its program's rules.
|
|
989
|
+
private static getCommandProgram(command: string): string {
|
|
990
|
+
return (command || "").trim().split(/\s+/)[0] || "";
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// "Docker host", "host" — the noun of a resource command's resource.
|
|
994
|
+
private static describeCommandResourceNoun(
|
|
995
|
+
command: AiRemediationCommand,
|
|
996
|
+
): string {
|
|
997
|
+
return isAiResourceType(command.resourceType)
|
|
998
|
+
? describeResourceNoun(command.resourceType)
|
|
999
|
+
: "resource";
|
|
1000
|
+
}
|
|
1001
|
+
|
|
887
1002
|
// Copy a terminal job's outcome onto an execution record.
|
|
888
1003
|
private static settleFromJob(
|
|
889
1004
|
state: AiRemediationCommandExecutionState,
|
|
890
1005
|
job: RunnerJob,
|
|
891
1006
|
label: "Command" | "Rollback",
|
|
1007
|
+
// The command the job ran: a resource command's output gets its program's redaction.
|
|
1008
|
+
command?: AiRemediationCommand | undefined,
|
|
892
1009
|
): void {
|
|
893
1010
|
const succeeded: boolean = job.status === RunnerJobStatus.Succeeded;
|
|
894
1011
|
|
|
@@ -897,12 +1014,36 @@ export default class CommandPlanExecutor {
|
|
|
897
1014
|
: AiRemediationCommandExecutionStatus.Failed;
|
|
898
1015
|
state.completedAt = OneUptimeDate.getCurrentDate().toISOString();
|
|
899
1016
|
state.exitCode = job.exitCode;
|
|
900
|
-
state.output = this.
|
|
1017
|
+
state.output = this.capCommandOutput(job.output || "", command);
|
|
901
1018
|
state.errorMessage = succeeded
|
|
902
1019
|
? undefined
|
|
903
1020
|
: job.errorMessage || `${label} ended with status ${job.status}.`;
|
|
904
1021
|
}
|
|
905
1022
|
|
|
1023
|
+
/*
|
|
1024
|
+
* The stored output of a command's job: a resource command's goes through
|
|
1025
|
+
* the resource redaction (its program's rules, then the generic ones) at
|
|
1026
|
+
* the stored cap; everything else through capOutput, as before.
|
|
1027
|
+
*/
|
|
1028
|
+
private static capCommandOutput(
|
|
1029
|
+
output: string,
|
|
1030
|
+
command?: AiRemediationCommand | undefined,
|
|
1031
|
+
): string {
|
|
1032
|
+
if (
|
|
1033
|
+
command?.stepType === RunbookStepType.ResourceCommand &&
|
|
1034
|
+
isAiResourceType(command.resourceType)
|
|
1035
|
+
) {
|
|
1036
|
+
return ResourceCommandJobRunner.redactAndCap({
|
|
1037
|
+
output,
|
|
1038
|
+
resourceType: command.resourceType,
|
|
1039
|
+
program: this.getCommandProgram(command.command),
|
|
1040
|
+
maxChars: MAX_STORED_OUTPUT_CHARS,
|
|
1041
|
+
}).text;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
return this.capOutput(output);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
906
1047
|
/*
|
|
907
1048
|
* One enqueue for both lanes. Bash/SSH go through enqueueAiCommand
|
|
908
1049
|
* (script or SSH payload); Kubectl goes through enqueueAiKubectlCommand
|
|
@@ -916,6 +1057,38 @@ export default class CommandPlanExecutor {
|
|
|
916
1057
|
}): Promise<RunnerJob> {
|
|
917
1058
|
const { suggestion, command } = data;
|
|
918
1059
|
|
|
1060
|
+
/*
|
|
1061
|
+
* A resource command goes through the resource chokepoint
|
|
1062
|
+
* (enqueueAiResourceCommand), which re-runs the policy, the binding, the
|
|
1063
|
+
* resource's fixes switch and the agent's write scope — and targets the
|
|
1064
|
+
* agent the plan names, so a reset or replaced agent never receives a
|
|
1065
|
+
* job composed for its predecessor.
|
|
1066
|
+
*/
|
|
1067
|
+
if (command.stepType === RunbookStepType.ResourceCommand) {
|
|
1068
|
+
if (
|
|
1069
|
+
!isAiResourceType(command.resourceType) ||
|
|
1070
|
+
!command.resourceId ||
|
|
1071
|
+
!ObjectID.isValidUUID(command.resourceId) ||
|
|
1072
|
+
!ObjectID.isValidUUID(command.runnerId)
|
|
1073
|
+
) {
|
|
1074
|
+
throw new Error("The resource command names no resource.");
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
return RunnerJobService.enqueueAiResourceCommand({
|
|
1078
|
+
projectId: suggestion.projectId!,
|
|
1079
|
+
aiRunId: suggestion.aiRunId!,
|
|
1080
|
+
origin: RunnerJobOrigin.AiRemediation,
|
|
1081
|
+
autoRemediationSuggestionId: suggestion.id!,
|
|
1082
|
+
resourceType: command.resourceType,
|
|
1083
|
+
resourceId: new ObjectID(command.resourceId),
|
|
1084
|
+
stepId: data.stepId,
|
|
1085
|
+
targetResourceAiAgentId: new ObjectID(command.runnerId),
|
|
1086
|
+
command: data.commandText,
|
|
1087
|
+
timeoutInMs: command.timeoutInMs,
|
|
1088
|
+
claimTimeoutInMs: AI_COMMAND_CLAIM_TIMEOUT_MS,
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
|
|
919
1092
|
if (command.stepType === RunbookStepType.Kubectl) {
|
|
920
1093
|
if (
|
|
921
1094
|
!command.kubernetesClusterId ||
|
|
@@ -1073,6 +1246,118 @@ export default class CommandPlanExecutor {
|
|
|
1073
1246
|
return null;
|
|
1074
1247
|
}
|
|
1075
1248
|
|
|
1249
|
+
/*
|
|
1250
|
+
* Why a resource command may NOT run on its resource right now, or null
|
|
1251
|
+
* — getClusterExecutionRefusal for a resource. The plan froze the
|
|
1252
|
+
* resource and the AI agent it was composed for; before anything is
|
|
1253
|
+
* enqueued the resource's AI page is read again: fixes must still be on
|
|
1254
|
+
* and ready, the agent must still be the one on the plan (a reset or
|
|
1255
|
+
* replaced agent never receives a job meant for its predecessor), and
|
|
1256
|
+
* the agent's reported write scope must let the command run. A rollback
|
|
1257
|
+
* must ALSO be allowed unattended under the resource's CURRENT mode and
|
|
1258
|
+
* allowlist: nothing shows a rollback to a human when it fires.
|
|
1259
|
+
*
|
|
1260
|
+
* Fails closed: a status that cannot be read is a refusal. Other step
|
|
1261
|
+
* types pass through.
|
|
1262
|
+
*/
|
|
1263
|
+
private static async getResourceExecutionRefusal(data: {
|
|
1264
|
+
suggestion: AutoRemediationSuggestion;
|
|
1265
|
+
command: AiRemediationCommand;
|
|
1266
|
+
commandText: string;
|
|
1267
|
+
purpose: "command" | "rollback";
|
|
1268
|
+
}): Promise<string | null> {
|
|
1269
|
+
const { suggestion, command } = data;
|
|
1270
|
+
|
|
1271
|
+
if (command.stepType !== RunbookStepType.ResourceCommand) {
|
|
1272
|
+
return null;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
if (
|
|
1276
|
+
!isAiResourceType(command.resourceType) ||
|
|
1277
|
+
!command.resourceId ||
|
|
1278
|
+
!ObjectID.isValidUUID(command.resourceId) ||
|
|
1279
|
+
!suggestion.projectId
|
|
1280
|
+
) {
|
|
1281
|
+
return "the resource command names no valid resource";
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
const resourceType: AiResourceType = command.resourceType;
|
|
1285
|
+
const noun: string = describeResourceNoun(resourceType);
|
|
1286
|
+
const label: string = `${noun} "${
|
|
1287
|
+
command.resourceNameSnapshot || command.resourceId
|
|
1288
|
+
}"`;
|
|
1289
|
+
|
|
1290
|
+
let status: ResourceAiAccessStatus | null;
|
|
1291
|
+
|
|
1292
|
+
try {
|
|
1293
|
+
status = await ResourceAiAccessService.getStatusForResource({
|
|
1294
|
+
projectId: suggestion.projectId,
|
|
1295
|
+
resourceType,
|
|
1296
|
+
resourceId: new ObjectID(command.resourceId),
|
|
1297
|
+
});
|
|
1298
|
+
} catch (error) {
|
|
1299
|
+
logger.error(
|
|
1300
|
+
`CommandPlanExecutor: could not read the AI access status of ${resourceType} ${command.resourceId} before a ${data.purpose}: ${error}`,
|
|
1301
|
+
);
|
|
1302
|
+
return `could not confirm that ${label} still allows AI remediation`;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
if (!status) {
|
|
1306
|
+
return `${label} no longer exists in this project`;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
const liveLabel: string = `${noun} "${status.resourceName}"`;
|
|
1310
|
+
|
|
1311
|
+
if (!status.isRemediationReady) {
|
|
1312
|
+
const gap: ResourceAiAccessGap | undefined = status.gaps.find(
|
|
1313
|
+
(candidate: ResourceAiAccessGap): boolean => {
|
|
1314
|
+
return candidate.blocksRemediation;
|
|
1315
|
+
},
|
|
1316
|
+
);
|
|
1317
|
+
return `${liveLabel} no longer allows AI remediation${
|
|
1318
|
+
gap ? ` (${gap.title})` : ""
|
|
1319
|
+
}`;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
const agentName: string =
|
|
1323
|
+
AI_RESOURCE_TYPE_INFO[resourceType].agentDisplayName;
|
|
1324
|
+
|
|
1325
|
+
if (!status.agent || status.agent.agentId !== command.runnerId) {
|
|
1326
|
+
return `${liveLabel} is no longer reached through the ${agentName} this plan was composed for (the agent was reset or replaced)`;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
const scopeRefusal: string | null =
|
|
1330
|
+
RemediationCommandToolkit.getResourceWriteScopeRefusal({
|
|
1331
|
+
resource: status,
|
|
1332
|
+
command: data.commandText,
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
if (scopeRefusal) {
|
|
1336
|
+
// The callers end the sentence themselves.
|
|
1337
|
+
return `the ${agentName} would refuse it: ${
|
|
1338
|
+
scopeRefusal.endsWith(".") ? scopeRefusal.slice(0, -1) : scopeRefusal
|
|
1339
|
+
}`;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
if (data.purpose === "rollback") {
|
|
1343
|
+
const verdict: ResourceAutoExecutionVerdict =
|
|
1344
|
+
ResourceCommandPolicy.evaluateForAutoExecution({
|
|
1345
|
+
resourceType,
|
|
1346
|
+
command: data.commandText,
|
|
1347
|
+
allowlistPatterns: status.aiCommandAllowlist,
|
|
1348
|
+
bypassApproval:
|
|
1349
|
+
status.aiRemediationMode ===
|
|
1350
|
+
ResourceAiRemediationMode.BypassApproval,
|
|
1351
|
+
});
|
|
1352
|
+
|
|
1353
|
+
if (verdict.verdict !== AiRemediationCommandPolicyVerdict.AutoApproved) {
|
|
1354
|
+
return `${liveLabel} no longer allows this change unattended (its AI remediation mode is now ${status.aiRemediationMode}): ${verdict.reason}`;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
return null;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1076
1361
|
/*
|
|
1077
1362
|
* The job a command's step ran under, when its record never got the job
|
|
1078
1363
|
* id. The enqueue and the write that names the job are two steps; a pod
|
|
@@ -1123,7 +1408,30 @@ export default class CommandPlanExecutor {
|
|
|
1123
1408
|
private static getDenyReason(data: {
|
|
1124
1409
|
stepType: RunbookStepType;
|
|
1125
1410
|
command: string;
|
|
1411
|
+
// ResourceCommand only: which resource command policy decides.
|
|
1412
|
+
resourceType?: AiResourceType | undefined;
|
|
1126
1413
|
}): string | null {
|
|
1414
|
+
/*
|
|
1415
|
+
* A resource command's floor is the Denied tier of its resource's
|
|
1416
|
+
* command policy — never the bash denylist, and never a step whose
|
|
1417
|
+
* resource type is unknown.
|
|
1418
|
+
*/
|
|
1419
|
+
if (data.stepType === RunbookStepType.ResourceCommand) {
|
|
1420
|
+
if (!isAiResourceType(data.resourceType)) {
|
|
1421
|
+
return "the resource command names no valid resource type";
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
const resourcePolicy: ResourceCommandPolicyResult =
|
|
1425
|
+
ResourceCommandPolicy.evaluateCommand({
|
|
1426
|
+
resourceType: data.resourceType,
|
|
1427
|
+
command: data.command,
|
|
1428
|
+
});
|
|
1429
|
+
|
|
1430
|
+
return resourcePolicy.tier === ResourceCommandTier.Denied
|
|
1431
|
+
? resourcePolicy.reason
|
|
1432
|
+
: null;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1127
1435
|
if (data.stepType === RunbookStepType.Kubectl) {
|
|
1128
1436
|
const policy: KubectlPolicyResult = KubectlPolicy.evaluateCommand(
|
|
1129
1437
|
data.command,
|
|
@@ -1224,7 +1532,7 @@ export default class CommandPlanExecutor {
|
|
|
1224
1532
|
? AiRemediationCommandExecutionStatus.Succeeded
|
|
1225
1533
|
: AiRemediationCommandExecutionStatus.Failed;
|
|
1226
1534
|
execution.exitCode = job.exitCode;
|
|
1227
|
-
execution.output = this.
|
|
1535
|
+
execution.output = this.capCommandOutput(job.output || "", command);
|
|
1228
1536
|
execution.errorMessage = succeeded
|
|
1229
1537
|
? undefined
|
|
1230
1538
|
: job.errorMessage ||
|
|
@@ -1303,7 +1611,7 @@ export default class CommandPlanExecutor {
|
|
|
1303
1611
|
}
|
|
1304
1612
|
|
|
1305
1613
|
if (isTerminalAgentJobStatus(job.status)) {
|
|
1306
|
-
this.settleFromJob(rollback, job, "Rollback");
|
|
1614
|
+
this.settleFromJob(rollback, job, "Rollback", command);
|
|
1307
1615
|
changed = true;
|
|
1308
1616
|
}
|
|
1309
1617
|
} catch (error) {
|
|
@@ -1381,7 +1689,7 @@ export default class CommandPlanExecutor {
|
|
|
1381
1689
|
}
|
|
1382
1690
|
|
|
1383
1691
|
if (job && job.status === RunnerJobStatus.Succeeded) {
|
|
1384
|
-
this.settleFromJob(execution, job, "Command");
|
|
1692
|
+
this.settleFromJob(execution, job, "Command", command);
|
|
1385
1693
|
changed = true;
|
|
1386
1694
|
continue;
|
|
1387
1695
|
}
|
|
@@ -1401,6 +1709,81 @@ export default class CommandPlanExecutor {
|
|
|
1401
1709
|
return mayHaveRun;
|
|
1402
1710
|
}
|
|
1403
1711
|
|
|
1712
|
+
/*
|
|
1713
|
+
* reconcileFailedKubectlExecutions for resource commands: the ones
|
|
1714
|
+
* recorded as Failed that may nonetheless have changed the resource,
|
|
1715
|
+
* read from their jobs the way ResourceCommandJobRunner reads every
|
|
1716
|
+
* resource job. A job that Succeeded after all is settled from the job
|
|
1717
|
+
* (and so rolled back like any other); one whose run is Unknown, or whose
|
|
1718
|
+
* program ran without finishing (the agent killed it at its timeout), is
|
|
1719
|
+
* returned — its undo is not run blind; one that certainly never ran, or
|
|
1720
|
+
* whose program finished and reported a failure, owes no undo.
|
|
1721
|
+
*/
|
|
1722
|
+
private static async reconcileFailedResourceExecutions(
|
|
1723
|
+
suggestion: AutoRemediationSuggestion,
|
|
1724
|
+
plan: AiRemediationCommandPlan,
|
|
1725
|
+
): Promise<Array<AiRemediationCommand>> {
|
|
1726
|
+
const mayHaveRun: Array<AiRemediationCommand> = [];
|
|
1727
|
+
let changed: boolean = false;
|
|
1728
|
+
|
|
1729
|
+
for (const command of plan.commands) {
|
|
1730
|
+
const execution: AiRemediationCommandExecutionState | undefined =
|
|
1731
|
+
command.execution;
|
|
1732
|
+
|
|
1733
|
+
if (
|
|
1734
|
+
command.stepType !== RunbookStepType.ResourceCommand ||
|
|
1735
|
+
!execution ||
|
|
1736
|
+
execution.status !== AiRemediationCommandExecutionStatus.Failed ||
|
|
1737
|
+
!execution.runnerJobId ||
|
|
1738
|
+
!command.rollbackCommand ||
|
|
1739
|
+
command.rollbackExecution
|
|
1740
|
+
) {
|
|
1741
|
+
continue;
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
let runState: ResourceCommandRunState = ResourceCommandRunState.Unknown;
|
|
1745
|
+
let job: RunnerJob | null = null;
|
|
1746
|
+
|
|
1747
|
+
try {
|
|
1748
|
+
job = ObjectID.isValidUUID(execution.runnerJobId)
|
|
1749
|
+
? await RunnerJobService.findOneById({
|
|
1750
|
+
id: new ObjectID(execution.runnerJobId),
|
|
1751
|
+
select: RUN_STATE_JOB_SELECT,
|
|
1752
|
+
props: { isRoot: true },
|
|
1753
|
+
})
|
|
1754
|
+
: null;
|
|
1755
|
+
|
|
1756
|
+
if (job) {
|
|
1757
|
+
runState = ResourceCommandJobRunner.getRunStateOfJobRow(job);
|
|
1758
|
+
}
|
|
1759
|
+
} catch (error) {
|
|
1760
|
+
logger.error(
|
|
1761
|
+
`CommandPlanExecutor: could not read whether resource command ${command.sequence} of suggestion ${suggestion.id?.toString()} ran: ${error}`,
|
|
1762
|
+
);
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
if (job && job.status === RunnerJobStatus.Succeeded) {
|
|
1766
|
+
this.settleFromJob(execution, job, "Command", command);
|
|
1767
|
+
changed = true;
|
|
1768
|
+
continue;
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
const programFinished: boolean =
|
|
1772
|
+
runState === ResourceCommandRunState.Ran &&
|
|
1773
|
+
typeof job?.exitCode === "number";
|
|
1774
|
+
|
|
1775
|
+
if (runState !== ResourceCommandRunState.NotRun && !programFinished) {
|
|
1776
|
+
mayHaveRun.push(command);
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
if (changed) {
|
|
1781
|
+
await this.persistPlan(suggestion, plan, "rollback");
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
return mayHaveRun;
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1404
1787
|
private static describeRollbackOutcome(
|
|
1405
1788
|
plan: AiRemediationCommandPlan | null,
|
|
1406
1789
|
): CommandPlanRollbackOutcome {
|
|
@@ -157,6 +157,8 @@ export default class RemediationVerifier {
|
|
|
157
157
|
ruleNameSnapshot: true,
|
|
158
158
|
runbookNameSnapshot: true,
|
|
159
159
|
kubernetesClusterId: true,
|
|
160
|
+
resourceType: true,
|
|
161
|
+
resourceId: true,
|
|
160
162
|
},
|
|
161
163
|
limit: 100,
|
|
162
164
|
skip: 0,
|
|
@@ -292,7 +294,19 @@ export default class RemediationVerifier {
|
|
|
292
294
|
}
|
|
293
295
|
}
|
|
294
296
|
|
|
295
|
-
|
|
297
|
+
/*
|
|
298
|
+
* A resource round (its suggestion names a resource, never a cluster)
|
|
299
|
+
* gets the same follow-up on its resource, on the same terms.
|
|
300
|
+
*/
|
|
301
|
+
const isResourceRound: boolean =
|
|
302
|
+
!suggestion.kubernetesClusterId &&
|
|
303
|
+
Boolean(suggestion.resourceType) &&
|
|
304
|
+
Boolean(suggestion.resourceId);
|
|
305
|
+
|
|
306
|
+
if (
|
|
307
|
+
(!suggestion.kubernetesClusterId && !isResourceRound) ||
|
|
308
|
+
!suggestion.projectId
|
|
309
|
+
) {
|
|
296
310
|
return;
|
|
297
311
|
}
|
|
298
312
|
|
|
@@ -306,9 +320,24 @@ export default class RemediationVerifier {
|
|
|
306
320
|
const rollbackIncomplete: boolean =
|
|
307
321
|
rollback.rollbackStatus === AiRemediationRollbackStatus.Failed;
|
|
308
322
|
|
|
323
|
+
if (isResourceRound) {
|
|
324
|
+
await AutoRemediationRuleEngineService.startFollowUpResourceRemediation({
|
|
325
|
+
projectId: suggestion.projectId,
|
|
326
|
+
resourceType: suggestion.resourceType!,
|
|
327
|
+
resourceId: suggestion.resourceId!,
|
|
328
|
+
incidentId: suggestion.incidentId,
|
|
329
|
+
alertId: suggestion.alertId,
|
|
330
|
+
forceSuggest: rollbackIncomplete ? true : undefined,
|
|
331
|
+
forceSuggestReason: rollbackIncomplete
|
|
332
|
+
? "the previous fix's rollback did not complete, so its change may still be applied"
|
|
333
|
+
: undefined,
|
|
334
|
+
});
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
309
338
|
await AutoRemediationRuleEngineService.startFollowUpClusterRemediation({
|
|
310
339
|
projectId: suggestion.projectId,
|
|
311
|
-
kubernetesClusterId: suggestion.kubernetesClusterId
|
|
340
|
+
kubernetesClusterId: suggestion.kubernetesClusterId!,
|
|
312
341
|
incidentId: suggestion.incidentId,
|
|
313
342
|
alertId: suggestion.alertId,
|
|
314
343
|
forceSuggest: rollbackIncomplete ? true : undefined,
|
|
@@ -371,6 +400,8 @@ export default class RemediationVerifier {
|
|
|
371
400
|
verificationNote: true,
|
|
372
401
|
ruleNameSnapshot: true,
|
|
373
402
|
kubernetesClusterId: true,
|
|
403
|
+
resourceType: true,
|
|
404
|
+
resourceId: true,
|
|
374
405
|
},
|
|
375
406
|
sort: { verificationCompletedAt: SortOrder.Ascending },
|
|
376
407
|
limit: ROLLBACK_RESUME_BATCH_SIZE,
|
|
@@ -485,6 +516,8 @@ export default class RemediationVerifier {
|
|
|
485
516
|
verificationNote: true,
|
|
486
517
|
ruleNameSnapshot: true,
|
|
487
518
|
kubernetesClusterId: true,
|
|
519
|
+
resourceType: true,
|
|
520
|
+
resourceId: true,
|
|
488
521
|
},
|
|
489
522
|
props: { isRoot: true },
|
|
490
523
|
});
|
|
@@ -162,6 +162,14 @@ export function resolveReferenceIds(value: unknown): Array<ObjectID | string> {
|
|
|
162
162
|
return ids;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
/*
|
|
166
|
+
* Thrown when a payload references another project's records, or records that
|
|
167
|
+
* do not exist. Still a BadDataException with the same message, so API callers
|
|
168
|
+
* see no change; its own type lets a chat reply say something fixed instead of
|
|
169
|
+
* naming another project's record.
|
|
170
|
+
*/
|
|
171
|
+
export class ProjectScopedReferenceException extends BadDataException {}
|
|
172
|
+
|
|
165
173
|
export default class ProjectScopedReferenceValidator {
|
|
166
174
|
public static async validateReferencesBelongToProject(data: {
|
|
167
175
|
projectId: ObjectID | undefined;
|
|
@@ -354,7 +362,7 @@ export default class ProjectScopedReferenceValidator {
|
|
|
354
362
|
return;
|
|
355
363
|
}
|
|
356
364
|
|
|
357
|
-
throw new
|
|
365
|
+
throw new ProjectScopedReferenceException(
|
|
358
366
|
`This ${data.subject || "request"} ${clauses.join(" It also ")}`,
|
|
359
367
|
);
|
|
360
368
|
}
|