use std::collections::BTreeSet;
use std::marker::PhantomData;
use std::path::PathBuf;
use std::sync::Arc;
use cageforge_command::CommandRequest;
use cageforge_policy_compose::{CompositionError, EffectivePathContext, EffectiveSandbox};
use thiserror::Error;
#[derive(Debug, Clone, Copy)]
pub struct BackendRequest<'a> {
pub(super) command: &'a CommandRequest,
pub(super) sandbox: &'a EffectiveSandbox,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct BackendCapabilities {
pub(crate) capabilities: BTreeSet<BackendCapability>,
}
pub struct PreparedBackendRequest<'a, B: SandboxBackend> {
pub(super) request: BackendRequest<'a>,
pub(super) path_context: EffectivePathContext,
pub(super) working_directory: PathBuf,
pub(super) capabilities: BackendCapabilities,
pub(super) backend_identity: BackendIdentity,
pub(super) backend: PhantomData<fn() -> B>,
}
#[derive(Clone)]
pub struct BackendIdentity(pub(super) Arc<()>);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum BackendCapability {
CommandExecution,
WorkingDirectory,
StdioInherit,
StdioNull,
StdioPipe,
TimeoutBackendDefault,
TimeoutLimit,
TimeoutDisabled,
FilesystemRestricted,
FilesystemUnrestricted,
FilesystemExternal,
FilesystemScopes,
FilesystemExecutableMapping,
FilesystemAbsoluteScopes,
FilesystemWorkspaceScopes,
FilesystemRootScopes,
FilesystemMinimalScopes,
FilesystemTmpdirScopes,
FilesystemConventionalTemporaryScopes,
FilesystemGlobs,
FilesystemGlobScanDepth,
FilesystemReadOnlySubpaths,
FilesystemMissingPathBehavior,
FilesystemProtectedPaths,
NetworkDisabled,
NetworkEnabled,
NetworkExternal,
NetworkDomainRules,
NetworkLocalAddressRestrictions,
NetworkResolvedTargets,
NetworkLocalIpcIsolation,
NetworkLocalIpcRules,
NetworkLocalIpcDenyRules,
NetworkWindowsNamedPipeRules,
EnvironmentAll,
EnvironmentCore,
EnvironmentNone,
EnvironmentFilters,
EnvironmentOverrides,
}
#[derive(Debug, Error, Clone, PartialEq, Eq)]
pub enum BackendContractError {
#[error("backend cannot safely enforce required capability: {capability}")]
UnsupportedCapability {
capability: BackendCapability,
},
#[error("command environment does not match the composed requested environment")]
CommandEnvironmentMismatch,
#[error("invalid backend runtime context: {source}")]
InvalidRuntimeContext {
#[source]
source: CompositionError,
},
#[error("environment preparation failed: {source}")]
EnvironmentPreparation {
#[source]
source: CompositionError,
},
#[error("filesystem policy evaluation failed: {source}")]
FilesystemEvaluation {
#[source]
source: CompositionError,
},
#[error("working directory {path:?} is denied by the effective filesystem policy")]
WorkingDirectoryDenied {
path: PathBuf,
},
#[error("relative working directory {path:?} requires a runtime current directory")]
WorkingDirectoryResolution {
path: PathBuf,
},
#[error("runtime current directory is required for backend preflight")]
MissingRuntimeCurrentDirectory,
#[error("network policy evaluation failed: {source}")]
NetworkEvaluation {
#[source]
source: CompositionError,
},
#[error("prepared backend request belongs to a different backend instance")]
BackendIdentityMismatch,
#[error("backend capabilities changed after request preparation")]
BackendCapabilitiesMismatch,
}
pub trait SandboxBackend {
fn identity(&self) -> &BackendIdentity;
fn capabilities(&self) -> BackendCapabilities;
}