feat(permissions): expose network permission state (#103)
This commit is contained in:
@ -36,6 +36,7 @@ pub mod pty;
|
||||
pub mod ratelimit;
|
||||
pub mod remote;
|
||||
pub mod runtime;
|
||||
pub mod runtime_permission;
|
||||
pub mod sandbox;
|
||||
pub mod scheduler;
|
||||
pub mod session;
|
||||
@ -87,6 +88,7 @@ pub use pty::PortablePtyAdapter;
|
||||
pub use ratelimit::RateLimitParser;
|
||||
pub use remote::{remote_host, LocalHost};
|
||||
pub use runtime::CliAgentRuntime;
|
||||
pub use runtime_permission::ReadOnlyRuntimePermissionProbe;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub use sandbox::LandlockSandbox;
|
||||
pub use sandbox::{default_enforcer, NoopSandbox};
|
||||
@ -102,8 +104,8 @@ pub use store::{
|
||||
AdaptiveMemoryRecall, BackgroundTaskReconcileReport, EmbedderEnvProbe, FsBackgroundTaskStore,
|
||||
FsDeviceSessionStore, FsEmbedderProfileStore, FsEmbedderPromptStore, FsLiveStateStore,
|
||||
FsMcpToolPermissionStore, FsMemoryStore, FsPermissionStore, FsProfileStore, FsProjectStore,
|
||||
FsSecretStore, FsSkillStore, FsTemplateStore, FsWindowStateStore, HashEmbedder,
|
||||
IdeaiContextStore, NaiveMemoryRecall, OnnxModelInfo, StubEmbedder, VectorMemoryRecall,
|
||||
DEFAULT_OLLAMA_BASE_URL, ONNX_CACHE_SUBDIR, RECOMMENDED_ONNX_MODELS, VECTOR_HTTP_ENABLED,
|
||||
VECTOR_ONNX_ENABLED,
|
||||
FsSecretStore, FsSkillStore, FsSystemPermissionStore, FsTemplateStore, FsWindowStateStore,
|
||||
HashEmbedder, IdeaiContextStore, NaiveMemoryRecall, OnnxModelInfo, StubEmbedder,
|
||||
VectorMemoryRecall, DEFAULT_OLLAMA_BASE_URL, ONNX_CACHE_SUBDIR, RECOMMENDED_ONNX_MODELS,
|
||||
VECTOR_HTTP_ENABLED, VECTOR_ONNX_ENABLED,
|
||||
};
|
||||
|
||||
24
crates/infrastructure/src/runtime_permission.rs
Normal file
24
crates/infrastructure/src/runtime_permission.rs
Normal file
@ -0,0 +1,24 @@
|
||||
//! Read-only runtime permission probe.
|
||||
//!
|
||||
//! V1 deliberately does not claim live control over provider/network sandboxing.
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use domain::ports::{RuntimeError, RuntimePermissionProbe};
|
||||
use domain::{AgentId, Project, RuntimePermissionSnapshot};
|
||||
|
||||
/// Conservative probe used when IdeA cannot inspect or pilot runtime network
|
||||
/// permissions.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ReadOnlyRuntimePermissionProbe;
|
||||
|
||||
#[async_trait]
|
||||
impl RuntimePermissionProbe for ReadOnlyRuntimePermissionProbe {
|
||||
async fn probe_runtime_permissions(
|
||||
&self,
|
||||
_project: &Project,
|
||||
_agent_id: AgentId,
|
||||
) -> Result<RuntimePermissionSnapshot, RuntimeError> {
|
||||
Ok(RuntimePermissionSnapshot::locked_uninspectable())
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,7 @@ mod profile;
|
||||
mod project;
|
||||
mod secrets;
|
||||
mod skill;
|
||||
mod system_permission;
|
||||
mod template;
|
||||
mod vector;
|
||||
mod window_state;
|
||||
@ -40,6 +41,7 @@ pub use profile::{FsEmbedderProfileStore, FsProfileStore};
|
||||
pub use project::FsProjectStore;
|
||||
pub use secrets::FsSecretStore;
|
||||
pub use skill::FsSkillStore;
|
||||
pub use system_permission::FsSystemPermissionStore;
|
||||
pub use template::FsTemplateStore;
|
||||
pub use vector::{should_use_vector, AdaptiveMemoryRecall, VectorMemoryRecall};
|
||||
pub use window_state::FsWindowStateStore;
|
||||
|
||||
68
crates/infrastructure/src/store/system_permission.rs
Normal file
68
crates/infrastructure/src/store/system_permission.rs
Normal file
@ -0,0 +1,68 @@
|
||||
//! Filesystem-backed [`SystemPermissionStore`] for project system permissions.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use domain::ports::{FileSystem, FsError, RemotePath, StoreError, SystemPermissionStore};
|
||||
use domain::{Project, ProjectSystemPermissions};
|
||||
|
||||
const SYSTEM_PERMISSIONS_FILE: &str = "system-permissions.json";
|
||||
|
||||
/// JSON-file implementation for `<project>/.ideai/system-permissions.json`.
|
||||
#[derive(Clone)]
|
||||
pub struct FsSystemPermissionStore {
|
||||
fs: Arc<dyn FileSystem>,
|
||||
}
|
||||
|
||||
impl FsSystemPermissionStore {
|
||||
/// Builds the store from an injected filesystem port.
|
||||
#[must_use]
|
||||
pub fn new(fs: Arc<dyn FileSystem>) -> Self {
|
||||
Self { fs }
|
||||
}
|
||||
|
||||
fn path(project: &Project) -> RemotePath {
|
||||
let root = project.root.as_str().trim_end_matches(['/', '\\']);
|
||||
RemotePath::new(format!("{root}/.ideai/{SYSTEM_PERMISSIONS_FILE}"))
|
||||
}
|
||||
|
||||
async fn ensure_ideai(&self, project: &Project) -> Result<(), StoreError> {
|
||||
let root = project.root.as_str().trim_end_matches(['/', '\\']);
|
||||
self.fs
|
||||
.create_dir_all(&RemotePath::new(format!("{root}/.ideai")))
|
||||
.await
|
||||
.map_err(|e| StoreError::Io(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl SystemPermissionStore for FsSystemPermissionStore {
|
||||
async fn load_system_permissions(
|
||||
&self,
|
||||
project: &Project,
|
||||
) -> Result<ProjectSystemPermissions, StoreError> {
|
||||
match self.fs.read(&Self::path(project)).await {
|
||||
Ok(bytes) => {
|
||||
serde_json::from_slice(&bytes).map_err(|e| StoreError::Serialization(e.to_string()))
|
||||
}
|
||||
Err(FsError::NotFound(_)) => Ok(ProjectSystemPermissions::default()),
|
||||
Err(e) => Err(StoreError::Io(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
async fn save_system_permissions(
|
||||
&self,
|
||||
project: &Project,
|
||||
permissions: &ProjectSystemPermissions,
|
||||
) -> Result<(), StoreError> {
|
||||
self.ensure_ideai(project).await?;
|
||||
let mut bytes = serde_json::to_vec_pretty(permissions)
|
||||
.map_err(|e| StoreError::Serialization(e.to_string()))?;
|
||||
bytes.push(b'\n');
|
||||
self.fs
|
||||
.write(&Self::path(project), &bytes)
|
||||
.await
|
||||
.map_err(|e| StoreError::Io(e.to_string()))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user