@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
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
import AutoRemediationRule from "../../../Models/DatabaseModels/AutoRemediationRule";
|
|
2
|
+
import CephCluster from "../../../Models/DatabaseModels/CephCluster";
|
|
3
|
+
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
4
|
+
import DatabaseServer from "../../../Models/DatabaseModels/DatabaseServer";
|
|
5
|
+
import DockerHost from "../../../Models/DatabaseModels/DockerHost";
|
|
6
|
+
import DockerSwarmCluster from "../../../Models/DatabaseModels/DockerSwarmCluster";
|
|
7
|
+
import Host from "../../../Models/DatabaseModels/Host";
|
|
8
|
+
import KubernetesCluster from "../../../Models/DatabaseModels/KubernetesCluster";
|
|
9
|
+
import PodmanHost from "../../../Models/DatabaseModels/PodmanHost";
|
|
10
|
+
import ProxmoxCluster from "../../../Models/DatabaseModels/ProxmoxCluster";
|
|
11
|
+
import VMwareVCenter from "../../../Models/DatabaseModels/VMwareVCenter";
|
|
12
|
+
import DatabaseRequestType from "../../../Server/Types/BaseDatabase/DatabaseRequestType";
|
|
13
|
+
import ColumnPermissions from "../../../Server/Types/Database/Permissions/ColumnPermission";
|
|
14
|
+
import TablePermission from "../../../Server/Types/Database/Permissions/TablePermission";
|
|
15
|
+
import { ColumnAccessControl } from "../../../Types/BaseDatabase/AccessControl";
|
|
16
|
+
import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
17
|
+
import ColumnLength from "../../../Types/Database/ColumnLength";
|
|
18
|
+
import ColumnType from "../../../Types/Database/ColumnType";
|
|
19
|
+
import TableColumnType from "../../../Types/Database/TableColumnType";
|
|
20
|
+
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
21
|
+
import { KubernetesAiRemediationMode } from "../../../Types/Kubernetes/KubernetesClusterAiAccess";
|
|
22
|
+
import { KUBERNETES_AI_ACCESS_ADMIN_PERMISSIONS } from "../../../Types/Kubernetes/KubernetesClusterAiAccessPermissions";
|
|
23
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
24
|
+
import Permission, {
|
|
25
|
+
PermissionHelper,
|
|
26
|
+
UserTenantAccessPermission,
|
|
27
|
+
} from "../../../Types/Permission";
|
|
28
|
+
import AiResourceType, {
|
|
29
|
+
ALL_AI_RESOURCE_TYPES,
|
|
30
|
+
AI_RESOURCE_TYPE_INFO,
|
|
31
|
+
AiResourceTypeInfo,
|
|
32
|
+
} from "../../../Types/ResourceAiAgent/AiResourceType";
|
|
33
|
+
import {
|
|
34
|
+
RESOURCE_AI_ALLOW_WRITES_ENV,
|
|
35
|
+
RESOURCE_AI_WRITE_TARGETS_ENV,
|
|
36
|
+
ResourceAiRemediationMode,
|
|
37
|
+
} from "../../../Types/ResourceAiAgent/ResourceAiAccess";
|
|
38
|
+
import {
|
|
39
|
+
RESOURCE_ALLOWLIST_MAX_PATTERNS,
|
|
40
|
+
RESOURCE_ALLOWLIST_MAX_PATTERN_LENGTH,
|
|
41
|
+
} from "../../../Utils/AiRemediation/Resource/ResourceCommandPolicy";
|
|
42
|
+
import { describe, expect, it } from "@jest/globals";
|
|
43
|
+
import fs from "fs";
|
|
44
|
+
import path from "path";
|
|
45
|
+
import { getMetadataArgsStorage } from "typeorm";
|
|
46
|
+
import type { ColumnMetadataArgs } from "typeorm/metadata-args/ColumnMetadataArgs";
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* The OneUptime AI access columns of every resource a resource AI agent can
|
|
50
|
+
* serve (DockerHost, PodmanHost, DockerSwarmCluster, ProxmoxCluster,
|
|
51
|
+
* VMwareVCenter, CephCluster, DatabaseServer, Host) — the resource twin of
|
|
52
|
+
* KubernetesClusterAiAccessColumns.test.ts.
|
|
53
|
+
*
|
|
54
|
+
* - The three settings (isAiInvestigationEnabled, aiRemediationMode,
|
|
55
|
+
* aiCommandAllowlist) keep the resource's OWN update ACL, exactly like a
|
|
56
|
+
* cluster's: every editor may make AI do less, and making it do more is
|
|
57
|
+
* the service's check, not the ACL's. None of them can be set on create.
|
|
58
|
+
* - The three aiAccess* columns are written only by the server.
|
|
59
|
+
* - Defaults: investigation off, remediation Disabled, so a resource nobody
|
|
60
|
+
* configured lets AI do nothing until its agent or an operator says so.
|
|
61
|
+
* - Column for column they are declared like the cluster's analogous
|
|
62
|
+
* columns (same database types), so stored values and the API behave the
|
|
63
|
+
* same.
|
|
64
|
+
* - The descriptions are the public API, OpenAPI and Terraform docs: the
|
|
65
|
+
* mode text is the canonical ResourceAiRemediationMode semantics, and the
|
|
66
|
+
* loosenable settings name who may loosen them.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
type ModelType = { new (): BaseModel; name: string };
|
|
70
|
+
|
|
71
|
+
interface ResourceCase {
|
|
72
|
+
type: AiResourceType;
|
|
73
|
+
model: ModelType;
|
|
74
|
+
// How the model's own descriptions name the resource ("this Docker host").
|
|
75
|
+
noun: string;
|
|
76
|
+
edit: Permission;
|
|
77
|
+
read: Permission;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const CASES: Array<ResourceCase> = [
|
|
81
|
+
{
|
|
82
|
+
type: AiResourceType.DockerHost,
|
|
83
|
+
model: DockerHost,
|
|
84
|
+
noun: "Docker host",
|
|
85
|
+
edit: Permission.EditDockerHost,
|
|
86
|
+
read: Permission.ReadDockerHost,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
type: AiResourceType.PodmanHost,
|
|
90
|
+
model: PodmanHost,
|
|
91
|
+
noun: "Podman host",
|
|
92
|
+
edit: Permission.EditPodmanHost,
|
|
93
|
+
read: Permission.ReadPodmanHost,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: AiResourceType.DockerSwarmCluster,
|
|
97
|
+
model: DockerSwarmCluster,
|
|
98
|
+
noun: "Docker Swarm cluster",
|
|
99
|
+
edit: Permission.EditDockerSwarmCluster,
|
|
100
|
+
read: Permission.ReadDockerSwarmCluster,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: AiResourceType.ProxmoxCluster,
|
|
104
|
+
model: ProxmoxCluster,
|
|
105
|
+
noun: "Proxmox cluster",
|
|
106
|
+
edit: Permission.EditProxmoxCluster,
|
|
107
|
+
read: Permission.ReadProxmoxCluster,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: AiResourceType.VMwareVCenter,
|
|
111
|
+
model: VMwareVCenter,
|
|
112
|
+
noun: "vCenter",
|
|
113
|
+
edit: Permission.EditVMwareVCenter,
|
|
114
|
+
read: Permission.ReadVMwareVCenter,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
type: AiResourceType.CephCluster,
|
|
118
|
+
model: CephCluster,
|
|
119
|
+
noun: "Ceph cluster",
|
|
120
|
+
edit: Permission.EditCephCluster,
|
|
121
|
+
read: Permission.ReadCephCluster,
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
type: AiResourceType.DatabaseServer,
|
|
125
|
+
model: DatabaseServer,
|
|
126
|
+
noun: "database server",
|
|
127
|
+
edit: Permission.EditDatabaseServer,
|
|
128
|
+
read: Permission.ReadDatabaseServer,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
type: AiResourceType.Host,
|
|
132
|
+
model: Host,
|
|
133
|
+
noun: "host",
|
|
134
|
+
edit: Permission.EditHost,
|
|
135
|
+
read: Permission.ReadHost,
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
// Columns an operator writes on the resource's AI page (and through the API).
|
|
140
|
+
const AI_SETTING_COLUMNS: Array<string> = [
|
|
141
|
+
"isAiInvestigationEnabled",
|
|
142
|
+
"aiRemediationMode",
|
|
143
|
+
"aiCommandAllowlist",
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
// Columns only the server writes.
|
|
147
|
+
const SERVER_WRITTEN_COLUMNS: Array<string> = [
|
|
148
|
+
"aiAccessLastVerifiedAt",
|
|
149
|
+
"aiAccessLastError",
|
|
150
|
+
"aiAccessConfiguredAt",
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
// The settings that loosen AI access, and so name who may loosen them.
|
|
154
|
+
const LOOSENABLE_COLUMNS: Array<string> = [
|
|
155
|
+
"aiRemediationMode",
|
|
156
|
+
"aiCommandAllowlist",
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
// Each resource column and the KubernetesCluster column it mirrors.
|
|
160
|
+
const KUBERNETES_TWIN: Record<string, string> = {
|
|
161
|
+
isAiInvestigationEnabled: "isAiInvestigationEnabled",
|
|
162
|
+
aiRemediationMode: "aiRemediationMode",
|
|
163
|
+
aiCommandAllowlist: "aiKubectlCommandAllowlist",
|
|
164
|
+
aiAccessLastVerifiedAt: "aiAccessLastVerifiedAt",
|
|
165
|
+
aiAccessLastError: "aiAccessLastError",
|
|
166
|
+
aiAccessConfiguredAt: "aiAccessConfiguredAt",
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
170
|
+
|
|
171
|
+
function makeProps(
|
|
172
|
+
permissions: Array<Permission>,
|
|
173
|
+
): DatabaseCommonInteractionProps {
|
|
174
|
+
const tenantPermission: UserTenantAccessPermission = {
|
|
175
|
+
projectId,
|
|
176
|
+
_type: "UserTenantAccessPermission",
|
|
177
|
+
permissions: permissions.map((permission: Permission) => {
|
|
178
|
+
return {
|
|
179
|
+
_type: "UserPermission",
|
|
180
|
+
permission,
|
|
181
|
+
labelIds: [],
|
|
182
|
+
isBlockPermission: false,
|
|
183
|
+
};
|
|
184
|
+
}),
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
userId: ObjectID.generate(),
|
|
189
|
+
tenantId: projectId,
|
|
190
|
+
userTenantAccessPermission: {
|
|
191
|
+
[projectId.toString()]: tenantPermission,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function sorted(permissions: ReadonlyArray<Permission>): Array<Permission> {
|
|
197
|
+
return [...permissions].sort();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function declaredColumn(
|
|
201
|
+
model: ModelType,
|
|
202
|
+
property: string,
|
|
203
|
+
): ColumnMetadataArgs {
|
|
204
|
+
const declared: ColumnMetadataArgs | undefined =
|
|
205
|
+
getMetadataArgsStorage().columns.find(
|
|
206
|
+
(column: ColumnMetadataArgs): boolean => {
|
|
207
|
+
return column.target === model && column.propertyName === property;
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
if (!declared) {
|
|
212
|
+
throw new Error(`${model.name} declares no column ${property}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return declared;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function description(model: ModelType, column: string): string {
|
|
219
|
+
return new model().getTableColumnMetadata(column).description!;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const COMMENT_LINE_PREFIX: RegExp = /^\s*\*\s?/;
|
|
223
|
+
const WHITESPACE_RUN: RegExp = /\s+/g;
|
|
224
|
+
|
|
225
|
+
function normalizeWhitespace(text: string): string {
|
|
226
|
+
return text.replace(WHITESPACE_RUN, " ").trim();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/*
|
|
230
|
+
* The canonical description of the resource remediation modes: the doc
|
|
231
|
+
* comment on ResourceAiRemediationMode in
|
|
232
|
+
* Types/ResourceAiAgent/ResourceAiAccess.ts, from "Disabled:" to its end,
|
|
233
|
+
* with the comment markup and the column alignment taken out.
|
|
234
|
+
*/
|
|
235
|
+
function canonicalRemediationModeText(): string {
|
|
236
|
+
const source: string = fs.readFileSync(
|
|
237
|
+
path.resolve(
|
|
238
|
+
__dirname,
|
|
239
|
+
"../../../Types/ResourceAiAgent/ResourceAiAccess.ts",
|
|
240
|
+
),
|
|
241
|
+
"utf8",
|
|
242
|
+
);
|
|
243
|
+
const enumAt: number = source.indexOf(
|
|
244
|
+
"export enum ResourceAiRemediationMode",
|
|
245
|
+
);
|
|
246
|
+
expect(enumAt).toBeGreaterThan(0);
|
|
247
|
+
|
|
248
|
+
const commentStart: number = source.lastIndexOf("/*", enumAt);
|
|
249
|
+
const commentEnd: number = source.indexOf("*/", commentStart);
|
|
250
|
+
expect(commentStart).toBeGreaterThanOrEqual(0);
|
|
251
|
+
expect(commentEnd).toBeLessThan(enumAt);
|
|
252
|
+
|
|
253
|
+
const body: string = source
|
|
254
|
+
.slice(commentStart + 2, commentEnd)
|
|
255
|
+
.split("\n")
|
|
256
|
+
.map((line: string) => {
|
|
257
|
+
return line.replace(COMMENT_LINE_PREFIX, "");
|
|
258
|
+
})
|
|
259
|
+
.join(" ");
|
|
260
|
+
|
|
261
|
+
const text: string = normalizeWhitespace(body);
|
|
262
|
+
const disabledAt: number = text.indexOf("Disabled:");
|
|
263
|
+
expect(disabledAt).toBeGreaterThanOrEqual(0);
|
|
264
|
+
|
|
265
|
+
return text.slice(disabledAt);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/*
|
|
269
|
+
* The canonical text as one resource's description says it: "this
|
|
270
|
+
* resource" names the resource, and the environment variable constants are
|
|
271
|
+
* spelled out as the operator types them.
|
|
272
|
+
*/
|
|
273
|
+
function canonicalTextFor(noun: string): string {
|
|
274
|
+
return canonicalRemediationModeText()
|
|
275
|
+
.split("this resource")
|
|
276
|
+
.join(`this ${noun}`)
|
|
277
|
+
.split("the resource's")
|
|
278
|
+
.join(`the ${noun}'s`)
|
|
279
|
+
.split("RESOURCE_AI_ALLOW_WRITES_ENV")
|
|
280
|
+
.join(RESOURCE_AI_ALLOW_WRITES_ENV)
|
|
281
|
+
.split("RESOURCE_AI_WRITE_TARGETS_ENV")
|
|
282
|
+
.join(RESOURCE_AI_WRITE_TARGETS_ENV);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function caseTable(): Array<[string, ResourceCase]> {
|
|
286
|
+
return CASES.map((resource: ResourceCase): [string, ResourceCase] => {
|
|
287
|
+
return [resource.model.name, resource];
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
describe("resource AI access columns - coverage", () => {
|
|
292
|
+
it("covers every AiResourceType exactly once, with the model of that name", () => {
|
|
293
|
+
expect(
|
|
294
|
+
CASES.map((resource: ResourceCase) => {
|
|
295
|
+
return resource.type;
|
|
296
|
+
}),
|
|
297
|
+
).toEqual([...ALL_AI_RESOURCE_TYPES]);
|
|
298
|
+
|
|
299
|
+
for (const resource of CASES) {
|
|
300
|
+
expect(new resource.model().tableName).toBe(resource.type);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("the canonical mode text still carries the phrases this file substitutes", () => {
|
|
305
|
+
const text: string = canonicalRemediationModeText();
|
|
306
|
+
|
|
307
|
+
expect(text).toContain("this resource");
|
|
308
|
+
expect(text).toContain("the resource's");
|
|
309
|
+
expect(text).toContain("RESOURCE_AI_ALLOW_WRITES_ENV");
|
|
310
|
+
expect(text).toContain("RESOURCE_AI_WRITE_TARGETS_ENV");
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
describe.each(caseTable())(
|
|
315
|
+
"%s AI access columns",
|
|
316
|
+
(_name: string, resource: ResourceCase) => {
|
|
317
|
+
const model: BaseModel = new resource.model();
|
|
318
|
+
const accessControl: Record<string, ColumnAccessControl> =
|
|
319
|
+
model.getColumnAccessControlForAllColumns();
|
|
320
|
+
const info: AiResourceTypeInfo = AI_RESOURCE_TYPE_INFO[resource.type];
|
|
321
|
+
|
|
322
|
+
describe("the settings an operator writes", () => {
|
|
323
|
+
it.each(AI_SETTING_COLUMNS)(
|
|
324
|
+
"%s exists and cannot be set on create",
|
|
325
|
+
(column: string) => {
|
|
326
|
+
expect(accessControl[column]).toBeDefined();
|
|
327
|
+
expect(accessControl[column]!.create).toEqual([]);
|
|
328
|
+
},
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
/*
|
|
332
|
+
* Pinned on purpose: the service, not the ACL, decides who may LOOSEN.
|
|
333
|
+
* Narrowing these to the admin set would stop a Settings Member from
|
|
334
|
+
* turning AI remediation off.
|
|
335
|
+
*/
|
|
336
|
+
it.each(AI_SETTING_COLUMNS)(
|
|
337
|
+
"%s is updatable by exactly the roles that may edit the resource",
|
|
338
|
+
(column: string) => {
|
|
339
|
+
expect(sorted(accessControl[column]!.update)).toEqual(
|
|
340
|
+
sorted(model.getUpdatePermissions()),
|
|
341
|
+
);
|
|
342
|
+
expect(accessControl[column]!.update).toContain(resource.edit);
|
|
343
|
+
},
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
it.each(AI_SETTING_COLUMNS)(
|
|
347
|
+
"%s is readable by exactly the roles that may read the resource",
|
|
348
|
+
(column: string) => {
|
|
349
|
+
expect(sorted(accessControl[column]!.read)).toEqual(
|
|
350
|
+
sorted(model.getReadPermissions()),
|
|
351
|
+
);
|
|
352
|
+
expect(accessControl[column]!.read).toContain(resource.read);
|
|
353
|
+
},
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
it.each([Permission.ProjectMember, Permission.SettingsMember])(
|
|
357
|
+
"a %s (an editor, not an AI admin) may write every setting as far as the ACL is concerned",
|
|
358
|
+
(role: Permission) => {
|
|
359
|
+
expect(() => {
|
|
360
|
+
ColumnPermissions.checkDataColumnPermissions(
|
|
361
|
+
resource.model,
|
|
362
|
+
{
|
|
363
|
+
isAiInvestigationEnabled: false,
|
|
364
|
+
aiRemediationMode: ResourceAiRemediationMode.Disabled,
|
|
365
|
+
aiCommandAllowlist: [],
|
|
366
|
+
} as unknown as BaseModel,
|
|
367
|
+
makeProps([role]),
|
|
368
|
+
DatabaseRequestType.Update,
|
|
369
|
+
);
|
|
370
|
+
}).not.toThrow();
|
|
371
|
+
},
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
it("a holder of only the resource's own Edit permission may write the settings", () => {
|
|
375
|
+
expect(() => {
|
|
376
|
+
ColumnPermissions.checkDataColumnPermissions(
|
|
377
|
+
resource.model,
|
|
378
|
+
{
|
|
379
|
+
aiRemediationMode: ResourceAiRemediationMode.Disabled,
|
|
380
|
+
} as unknown as BaseModel,
|
|
381
|
+
makeProps([resource.edit]),
|
|
382
|
+
DatabaseRequestType.Update,
|
|
383
|
+
);
|
|
384
|
+
}).not.toThrow();
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it("a viewer may read but not write the settings", () => {
|
|
388
|
+
expect(() => {
|
|
389
|
+
ColumnPermissions.checkDataColumnPermissions(
|
|
390
|
+
resource.model,
|
|
391
|
+
{ isAiInvestigationEnabled: true } as unknown as BaseModel,
|
|
392
|
+
makeProps([Permission.Viewer]),
|
|
393
|
+
DatabaseRequestType.Update,
|
|
394
|
+
);
|
|
395
|
+
}).toThrow();
|
|
396
|
+
|
|
397
|
+
const readable: Array<string> =
|
|
398
|
+
ColumnPermissions.getModelColumnsByPermissions(
|
|
399
|
+
resource.model,
|
|
400
|
+
makeProps([Permission.Viewer]).userTenantAccessPermission![
|
|
401
|
+
projectId.toString()
|
|
402
|
+
]!.permissions,
|
|
403
|
+
DatabaseRequestType.Read,
|
|
404
|
+
).columns;
|
|
405
|
+
|
|
406
|
+
for (const column of [
|
|
407
|
+
...AI_SETTING_COLUMNS,
|
|
408
|
+
...SERVER_WRITTEN_COLUMNS,
|
|
409
|
+
]) {
|
|
410
|
+
expect(readable).toContain(column);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it("an AI setting cannot be set when creating the resource, even by a project owner", () => {
|
|
415
|
+
expect(() => {
|
|
416
|
+
ColumnPermissions.checkDataColumnPermissions(
|
|
417
|
+
resource.model,
|
|
418
|
+
{
|
|
419
|
+
aiRemediationMode: ResourceAiRemediationMode.BypassApproval,
|
|
420
|
+
} as unknown as BaseModel,
|
|
421
|
+
makeProps([Permission.ProjectOwner]),
|
|
422
|
+
DatabaseRequestType.Create,
|
|
423
|
+
);
|
|
424
|
+
}).toThrow(BadDataException);
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
describe("the columns only the server writes", () => {
|
|
429
|
+
it.each(SERVER_WRITTEN_COLUMNS)(
|
|
430
|
+
"%s cannot be created or updated by any role",
|
|
431
|
+
(column: string) => {
|
|
432
|
+
expect(accessControl[column]).toBeDefined();
|
|
433
|
+
expect(accessControl[column]!.create).toEqual([]);
|
|
434
|
+
expect(accessControl[column]!.update).toEqual([]);
|
|
435
|
+
},
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
it.each(SERVER_WRITTEN_COLUMNS)(
|
|
439
|
+
"%s is readable by exactly the roles that may read the resource",
|
|
440
|
+
(column: string) => {
|
|
441
|
+
expect(sorted(accessControl[column]!.read)).toEqual(
|
|
442
|
+
sorted(model.getReadPermissions()),
|
|
443
|
+
);
|
|
444
|
+
},
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
it.each(SERVER_WRITTEN_COLUMNS)(
|
|
448
|
+
"%s is refused even for a project owner and admin",
|
|
449
|
+
(column: string) => {
|
|
450
|
+
expect(() => {
|
|
451
|
+
ColumnPermissions.checkDataColumnPermissions(
|
|
452
|
+
resource.model,
|
|
453
|
+
{
|
|
454
|
+
[column]: column === "aiAccessLastError" ? "x" : new Date(),
|
|
455
|
+
} as unknown as BaseModel,
|
|
456
|
+
makeProps([Permission.ProjectOwner, Permission.ProjectAdmin]),
|
|
457
|
+
DatabaseRequestType.Update,
|
|
458
|
+
);
|
|
459
|
+
}).toThrow(BadDataException);
|
|
460
|
+
},
|
|
461
|
+
);
|
|
462
|
+
|
|
463
|
+
it("lets the same owner update an ordinary column (harness negative control)", () => {
|
|
464
|
+
expect(() => {
|
|
465
|
+
ColumnPermissions.checkDataColumnPermissions(
|
|
466
|
+
resource.model,
|
|
467
|
+
{ name: "prod-1" } as unknown as BaseModel,
|
|
468
|
+
makeProps([Permission.ProjectOwner]),
|
|
469
|
+
DatabaseRequestType.Update,
|
|
470
|
+
);
|
|
471
|
+
}).not.toThrow();
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
it.each(SERVER_WRITTEN_COLUMNS)(
|
|
475
|
+
"%s says only the server sets it",
|
|
476
|
+
(column: string) => {
|
|
477
|
+
expect(description(resource.model, column)).toMatch(
|
|
478
|
+
/Set by the server/,
|
|
479
|
+
);
|
|
480
|
+
},
|
|
481
|
+
);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
describe("defaults and storage", () => {
|
|
485
|
+
it("investigation is off by default, in the API metadata and the column", () => {
|
|
486
|
+
const metadata: ReturnType<BaseModel["getTableColumnMetadata"]> =
|
|
487
|
+
model.getTableColumnMetadata("isAiInvestigationEnabled");
|
|
488
|
+
|
|
489
|
+
expect(metadata.type).toBe(TableColumnType.Boolean);
|
|
490
|
+
expect(metadata.required).toBe(true);
|
|
491
|
+
expect(metadata.isDefaultValueColumn).toBe(true);
|
|
492
|
+
expect(metadata.defaultValue).toBe(false);
|
|
493
|
+
expect(
|
|
494
|
+
declaredColumn(resource.model, "isAiInvestigationEnabled").options,
|
|
495
|
+
).toEqual(
|
|
496
|
+
expect.objectContaining({
|
|
497
|
+
type: ColumnType.Boolean,
|
|
498
|
+
nullable: false,
|
|
499
|
+
default: false,
|
|
500
|
+
}),
|
|
501
|
+
);
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it("remediation is Disabled by default, in the API metadata and the column", () => {
|
|
505
|
+
const metadata: ReturnType<BaseModel["getTableColumnMetadata"]> =
|
|
506
|
+
model.getTableColumnMetadata("aiRemediationMode");
|
|
507
|
+
|
|
508
|
+
expect(metadata.type).toBe(TableColumnType.ShortText);
|
|
509
|
+
expect(metadata.required).toBe(true);
|
|
510
|
+
expect(metadata.isDefaultValueColumn).toBe(true);
|
|
511
|
+
expect(metadata.defaultValue).toBe(ResourceAiRemediationMode.Disabled);
|
|
512
|
+
expect(metadata.example).toBe(
|
|
513
|
+
ResourceAiRemediationMode.RequireApproval,
|
|
514
|
+
);
|
|
515
|
+
expect(
|
|
516
|
+
declaredColumn(resource.model, "aiRemediationMode").options,
|
|
517
|
+
).toEqual(
|
|
518
|
+
expect.objectContaining({
|
|
519
|
+
type: ColumnType.ShortText,
|
|
520
|
+
length: ColumnLength.ShortText,
|
|
521
|
+
nullable: false,
|
|
522
|
+
default: ResourceAiRemediationMode.Disabled,
|
|
523
|
+
}),
|
|
524
|
+
);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
it("every mode fits the mode column", () => {
|
|
528
|
+
for (const mode of Object.values(ResourceAiRemediationMode)) {
|
|
529
|
+
expect(mode.length).toBeLessThanOrEqual(ColumnLength.ShortText);
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
it("the allowlist is an optional JSON array", () => {
|
|
534
|
+
const metadata: ReturnType<BaseModel["getTableColumnMetadata"]> =
|
|
535
|
+
model.getTableColumnMetadata("aiCommandAllowlist");
|
|
536
|
+
|
|
537
|
+
expect(metadata.type).toBe(TableColumnType.JSON);
|
|
538
|
+
expect(metadata.required).toBe(false);
|
|
539
|
+
expect(
|
|
540
|
+
declaredColumn(resource.model, "aiCommandAllowlist").options,
|
|
541
|
+
).toEqual(
|
|
542
|
+
expect.objectContaining({ type: ColumnType.JSON, nullable: true }),
|
|
543
|
+
);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
it.each([
|
|
547
|
+
["aiAccessLastVerifiedAt", TableColumnType.Date, ColumnType.Date],
|
|
548
|
+
["aiAccessConfiguredAt", TableColumnType.Date, ColumnType.Date],
|
|
549
|
+
["aiAccessLastError", TableColumnType.LongText, ColumnType.LongText],
|
|
550
|
+
])(
|
|
551
|
+
"%s is an optional %s",
|
|
552
|
+
(
|
|
553
|
+
column: string,
|
|
554
|
+
tableType: TableColumnType,
|
|
555
|
+
columnType: ColumnType,
|
|
556
|
+
) => {
|
|
557
|
+
expect(model.getTableColumnMetadata(column).type).toBe(tableType);
|
|
558
|
+
expect(model.getTableColumnMetadata(column).required).toBe(false);
|
|
559
|
+
expect(declaredColumn(resource.model, column).options).toEqual(
|
|
560
|
+
expect.objectContaining({ type: columnType, nullable: true }),
|
|
561
|
+
);
|
|
562
|
+
},
|
|
563
|
+
);
|
|
564
|
+
|
|
565
|
+
/*
|
|
566
|
+
* The same database shape as the cluster's analogous column, so the two
|
|
567
|
+
* stacks store (and the drift check sees) the same thing. Only the
|
|
568
|
+
* investigation default differs on purpose: a cluster's is on, a
|
|
569
|
+
* resource's is off until its agent or an operator turns it on.
|
|
570
|
+
*/
|
|
571
|
+
it.each(Object.entries(KUBERNETES_TWIN))(
|
|
572
|
+
"%s is stored like KubernetesCluster.%s",
|
|
573
|
+
(column: string, twin: string) => {
|
|
574
|
+
const ours: ColumnMetadataArgs = declaredColumn(
|
|
575
|
+
resource.model,
|
|
576
|
+
column,
|
|
577
|
+
);
|
|
578
|
+
const theirs: ColumnMetadataArgs = declaredColumn(
|
|
579
|
+
KubernetesCluster,
|
|
580
|
+
twin,
|
|
581
|
+
);
|
|
582
|
+
|
|
583
|
+
expect({
|
|
584
|
+
type: ours.options.type,
|
|
585
|
+
length: ours.options.length,
|
|
586
|
+
nullable: ours.options.nullable,
|
|
587
|
+
}).toEqual({
|
|
588
|
+
type: theirs.options.type,
|
|
589
|
+
length: theirs.options.length,
|
|
590
|
+
nullable: theirs.options.nullable,
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
const ourAcl: ColumnAccessControl = accessControl[column]!;
|
|
594
|
+
const theirAcl: ColumnAccessControl =
|
|
595
|
+
new KubernetesCluster().getColumnAccessControlFor(twin)!;
|
|
596
|
+
|
|
597
|
+
expect({
|
|
598
|
+
create: ourAcl.create,
|
|
599
|
+
updatable: ourAcl.update.length > 0,
|
|
600
|
+
}).toEqual({
|
|
601
|
+
create: theirAcl.create,
|
|
602
|
+
updatable: theirAcl.update.length > 0,
|
|
603
|
+
});
|
|
604
|
+
},
|
|
605
|
+
);
|
|
606
|
+
|
|
607
|
+
it("stored modes are interchangeable with a cluster's", () => {
|
|
608
|
+
expect(
|
|
609
|
+
declaredColumn(resource.model, "aiRemediationMode").options.default,
|
|
610
|
+
).toBe(KubernetesAiRemediationMode.Disabled);
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
describe("the column descriptions (the API and Terraform docs)", () => {
|
|
615
|
+
it("aiRemediationMode carries the canonical mode semantics word for word", () => {
|
|
616
|
+
expect(
|
|
617
|
+
normalizeWhitespace(description(resource.model, "aiRemediationMode")),
|
|
618
|
+
).toContain(canonicalTextFor(resource.noun));
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it("aiRemediationMode names the environment variables the agent reads", () => {
|
|
622
|
+
const text: string = description(resource.model, "aiRemediationMode");
|
|
623
|
+
|
|
624
|
+
expect(text).toContain(`${RESOURCE_AI_ALLOW_WRITES_ENV}=true`);
|
|
625
|
+
expect(text).toContain(RESOURCE_AI_WRITE_TARGETS_ENV);
|
|
626
|
+
expect(text).not.toMatch(/RESOURCE_AI_\w+_ENV/);
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
it("negative control: the parity check catches a drifted Automatic", () => {
|
|
630
|
+
const drifted: string = canonicalTextFor(resource.noun).replace(
|
|
631
|
+
"a riskier change is proposed for approval",
|
|
632
|
+
"a riskier change also runs on its own",
|
|
633
|
+
);
|
|
634
|
+
|
|
635
|
+
expect(drifted).not.toBe(canonicalTextFor(resource.noun));
|
|
636
|
+
expect(
|
|
637
|
+
normalizeWhitespace(description(resource.model, "aiRemediationMode")),
|
|
638
|
+
).not.toContain(drifted);
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
it.each(LOOSENABLE_COLUMNS)(
|
|
642
|
+
"%s names the permissions that may loosen it",
|
|
643
|
+
(column: string) => {
|
|
644
|
+
for (const title of PermissionHelper.getPermissionTitles(
|
|
645
|
+
KUBERNETES_AI_ACCESS_ADMIN_PERMISSIONS,
|
|
646
|
+
)) {
|
|
647
|
+
expect(description(resource.model, column)).toContain(title);
|
|
648
|
+
}
|
|
649
|
+
expect(description(resource.model, column)).toContain(
|
|
650
|
+
`nyone who may edit the ${resource.noun} can`,
|
|
651
|
+
);
|
|
652
|
+
},
|
|
653
|
+
);
|
|
654
|
+
|
|
655
|
+
it("isAiInvestigationEnabled says it is off by default, nothing is changed, and every editor may flip it", () => {
|
|
656
|
+
const text: string = description(
|
|
657
|
+
resource.model,
|
|
658
|
+
"isAiInvestigationEnabled",
|
|
659
|
+
);
|
|
660
|
+
|
|
661
|
+
expect(text).toMatch(/Nothing is ever changed by an investigation/);
|
|
662
|
+
expect(text).toMatch(/Off by default/);
|
|
663
|
+
expect(text).toContain(
|
|
664
|
+
`Anyone who may edit the ${resource.noun} can turn it on or off`,
|
|
665
|
+
);
|
|
666
|
+
expect(text).toContain(info.agentDisplayName);
|
|
667
|
+
expect(text).toMatch(/read-only/);
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
it("aiCommandAllowlist states the limits and the word-by-word rule the matcher applies", () => {
|
|
671
|
+
const text: string = description(resource.model, "aiCommandAllowlist");
|
|
672
|
+
|
|
673
|
+
expect(text.toLowerCase()).toContain(
|
|
674
|
+
`at most ${RESOURCE_ALLOWLIST_MAX_PATTERNS} patterns`,
|
|
675
|
+
);
|
|
676
|
+
expect(text.toLowerCase()).toContain(
|
|
677
|
+
`at most ${RESOURCE_ALLOWLIST_MAX_PATTERN_LENGTH} characters`,
|
|
678
|
+
);
|
|
679
|
+
expect(text).toMatch(/word by word/);
|
|
680
|
+
expect(text).toMatch(/\* stands for exactly one word/);
|
|
681
|
+
expect(text).toMatch(/Denied tier\) never run/);
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
/*
|
|
685
|
+
* The first program is the one a pattern for this resource starts with
|
|
686
|
+
* (a host has several; the description names the first and says there
|
|
687
|
+
* are others, so a program added to the list needs no copy edit here).
|
|
688
|
+
*/
|
|
689
|
+
it("aiCommandAllowlist names the program its agent runs", () => {
|
|
690
|
+
expect(description(resource.model, "aiCommandAllowlist")).toMatch(
|
|
691
|
+
new RegExp(`\\(${info.programs[0]!}\\b`),
|
|
692
|
+
);
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
it.each(["aiAccessLastVerifiedAt", "aiAccessConfiguredAt"])(
|
|
696
|
+
"%s names the resource's AI agent",
|
|
697
|
+
(column: string) => {
|
|
698
|
+
expect(description(resource.model, column)).toContain(
|
|
699
|
+
info.agentDisplayName,
|
|
700
|
+
);
|
|
701
|
+
},
|
|
702
|
+
);
|
|
703
|
+
});
|
|
704
|
+
},
|
|
705
|
+
);
|
|
706
|
+
|
|
707
|
+
describe("who may loosen a resource's AI access", () => {
|
|
708
|
+
/*
|
|
709
|
+
* A resource's mode and allowlist do the job of
|
|
710
|
+
* AutoRemediationRule.executionMode and commandAllowlist, exactly as a
|
|
711
|
+
* cluster's do; the descriptions name that set.
|
|
712
|
+
*/
|
|
713
|
+
it.each(["executionMode", "commandAllowlist"])(
|
|
714
|
+
"is the set that may update AutoRemediationRule.%s",
|
|
715
|
+
(column: string) => {
|
|
716
|
+
const ruleColumn: ColumnAccessControl | null =
|
|
717
|
+
new AutoRemediationRule().getColumnAccessControlFor(column);
|
|
718
|
+
|
|
719
|
+
expect(ruleColumn).not.toBeNull();
|
|
720
|
+
expect(sorted(KUBERNETES_AI_ACCESS_ADMIN_PERMISSIONS)).toEqual(
|
|
721
|
+
sorted(ruleColumn!.update),
|
|
722
|
+
);
|
|
723
|
+
},
|
|
724
|
+
);
|
|
725
|
+
|
|
726
|
+
it.each(caseTable())(
|
|
727
|
+
"holding only Edit Auto Remediation Rule does not let anyone update a %s at all",
|
|
728
|
+
(_name: string, resource: ResourceCase) => {
|
|
729
|
+
expect(() => {
|
|
730
|
+
TablePermission.checkTableLevelPermissions(
|
|
731
|
+
resource.model,
|
|
732
|
+
makeProps([Permission.EditAutoRemediationRule]),
|
|
733
|
+
DatabaseRequestType.Update,
|
|
734
|
+
);
|
|
735
|
+
}).toThrow();
|
|
736
|
+
},
|
|
737
|
+
);
|
|
738
|
+
});
|