//! System permission use cases. //! //! These use cases persist the wanted project/agent policies separately from //! filesystem/bash permissions and resolve them through a read-only runtime //! probe. use std::sync::Arc; use domain::ports::{RuntimePermissionProbe, SystemPermissionStore}; use domain::{ resolve_agent_system_permissions, AgentId, Project, ProjectSystemPermissions, ResolvedAgentSystemPermissions, SystemPermissionSet, }; use crate::error::AppError; /// Reads the full project system permission document. pub struct GetProjectSystemPermissions { store: Arc, } impl GetProjectSystemPermissions { /// Builds the use case. #[must_use] pub fn new(store: Arc) -> Self { Self { store } } /// Executes the read. pub async fn execute( &self, input: GetProjectSystemPermissionsInput, ) -> Result { let permissions = self.store.load_system_permissions(&input.project).await?; Ok(GetProjectSystemPermissionsOutput { permissions }) } } /// Input for [`GetProjectSystemPermissions`]. pub struct GetProjectSystemPermissionsInput { /// Target project. pub project: Project, } /// Output for project system permission reads/mutations. pub struct GetProjectSystemPermissionsOutput { /// Persisted system permission document. pub permissions: ProjectSystemPermissions, } /// Replaces the project default system permissions. pub struct UpdateProjectSystemPermissions { store: Arc, } impl UpdateProjectSystemPermissions { /// Builds the use case. #[must_use] pub fn new(store: Arc) -> Self { Self { store } } /// Executes the mutation. pub async fn execute( &self, input: UpdateProjectSystemPermissionsInput, ) -> Result { let mut doc = self.store.load_system_permissions(&input.project).await?; doc.set_project_default(input.permissions); self.store .save_system_permissions(&input.project, &doc) .await?; Ok(GetProjectSystemPermissionsOutput { permissions: doc }) } } /// Input for [`UpdateProjectSystemPermissions`]. pub struct UpdateProjectSystemPermissionsInput { /// Target project. pub project: Project, /// New project default policy. `None` removes project defaults. pub permissions: Option, } /// Replaces one agent system permission override. pub struct UpdateAgentSystemPermissions { store: Arc, } impl UpdateAgentSystemPermissions { /// Builds the use case. #[must_use] pub fn new(store: Arc) -> Self { Self { store } } /// Executes the mutation. pub async fn execute( &self, input: UpdateAgentSystemPermissionsInput, ) -> Result { let mut doc = self.store.load_system_permissions(&input.project).await?; doc.set_agent_permissions(input.agent_id, input.permissions); self.store .save_system_permissions(&input.project, &doc) .await?; Ok(GetProjectSystemPermissionsOutput { permissions: doc }) } } /// Input for [`UpdateAgentSystemPermissions`]. pub struct UpdateAgentSystemPermissionsInput { /// Target project. pub project: Project, /// Target agent. pub agent_id: AgentId, /// New agent policy. `None` removes the override. pub permissions: Option, } /// Resolves effective system permissions for one agent. pub struct ResolveAgentSystemPermissions { store: Arc, runtime_probe: Arc, } impl ResolveAgentSystemPermissions { /// Builds the use case. #[must_use] pub fn new( store: Arc, runtime_probe: Arc, ) -> Self { Self { store, runtime_probe, } } /// Executes the resolution. pub async fn execute( &self, input: ResolveAgentSystemPermissionsInput, ) -> Result { let doc = self.store.load_system_permissions(&input.project).await?; let runtime = self .runtime_probe .probe_runtime_permissions(&input.project, input.agent_id) .await?; Ok(ResolveAgentSystemPermissionsOutput { permissions: resolve_agent_system_permissions(&doc, input.agent_id, runtime), }) } } /// Input for [`ResolveAgentSystemPermissions`]. pub struct ResolveAgentSystemPermissionsInput { /// Target project. pub project: Project, /// Target agent. pub agent_id: AgentId, } /// Output for [`ResolveAgentSystemPermissions`]. pub struct ResolveAgentSystemPermissionsOutput { /// Resolved system permissions. pub permissions: ResolvedAgentSystemPermissions, }