use cageforge_command::{CommandRequest, EnvironmentBase, StdioMode, TimeoutPolicy};
use cageforge_policy::{FilesystemMode, NetworkMode};
use cageforge_policy_compose::EffectiveSandbox;
use crate::{BackendCapabilities, BackendCapability};
pub(super) fn add_command_capabilities(
required: &mut BackendCapabilities,
command: &CommandRequest,
) {
required
.capabilities
.insert(BackendCapability::WorkingDirectory);
for mode in [
command.stdio().stdin(),
command.stdio().stdout(),
command.stdio().stderr(),
] {
required.capabilities.insert(match mode {
StdioMode::Inherit => BackendCapability::StdioInherit,
StdioMode::Null => BackendCapability::StdioNull,
StdioMode::Pipe => BackendCapability::StdioPipe,
});
}
required
.capabilities
.insert(match command.timeout_policy() {
TimeoutPolicy::BackendDefault => BackendCapability::TimeoutBackendDefault,
TimeoutPolicy::Limit(_) => BackendCapability::TimeoutLimit,
TimeoutPolicy::Disabled => BackendCapability::TimeoutDisabled,
});
}
pub(super) fn add_filesystem_capabilities(
required: &mut BackendCapabilities,
sandbox: &EffectiveSandbox,
) {
let requirements = sandbox.filesystem().requirements();
let mode = requirements.mode();
required.capabilities.insert(match mode {
FilesystemMode::Restricted => BackendCapability::FilesystemRestricted,
FilesystemMode::Unrestricted => BackendCapability::FilesystemUnrestricted,
FilesystemMode::External => BackendCapability::FilesystemExternal,
});
if sandbox.workspace_roots().is_some() || sandbox.workspace_root_limit().is_some() {
required
.capabilities
.insert(BackendCapability::FilesystemScopes);
required
.capabilities
.insert(BackendCapability::FilesystemWorkspaceScopes);
}
if mode != FilesystemMode::Restricted {
return;
}
if requirements.glob_scan_depth() {
required
.capabilities
.insert(BackendCapability::FilesystemGlobScanDepth);
}
if requirements.protected_paths() {
required
.capabilities
.insert(BackendCapability::FilesystemProtectedPaths);
}
if requirements.scopes() {
required
.capabilities
.insert(BackendCapability::FilesystemScopes);
}
if requirements.absolute_scopes() {
required
.capabilities
.insert(BackendCapability::FilesystemAbsoluteScopes);
}
if requirements.workspace_scopes() || sandbox.workspace_roots().is_some() {
required
.capabilities
.insert(BackendCapability::FilesystemWorkspaceScopes);
}
if requirements.root_scopes() {
required
.capabilities
.insert(BackendCapability::FilesystemRootScopes);
}
if requirements.minimal_scopes() {
required
.capabilities
.insert(BackendCapability::FilesystemMinimalScopes);
}
if requirements.tmpdir_scopes() {
required
.capabilities
.insert(BackendCapability::FilesystemTmpdirScopes);
}
if requirements.conventional_temporary_scopes() {
required
.capabilities
.insert(BackendCapability::FilesystemConventionalTemporaryScopes);
}
if requirements.globs() {
required
.capabilities
.insert(BackendCapability::FilesystemGlobs);
}
if requirements.read_only_subpaths() {
required
.capabilities
.insert(BackendCapability::FilesystemReadOnlySubpaths);
}
if requirements.missing_path_behavior() {
required
.capabilities
.insert(BackendCapability::FilesystemMissingPathBehavior);
}
}
pub(super) fn add_network_capabilities(
required: &mut BackendCapabilities,
sandbox: &EffectiveSandbox,
) {
let requirements = sandbox.network().requirements();
let mode = requirements.mode();
required.capabilities.insert(match mode {
NetworkMode::Disabled => BackendCapability::NetworkDisabled,
NetworkMode::Enabled => BackendCapability::NetworkEnabled,
NetworkMode::External => BackendCapability::NetworkExternal,
});
if requirements.windows_named_pipe_rules() {
required
.capabilities
.insert(BackendCapability::NetworkWindowsNamedPipeRules);
}
if mode != NetworkMode::Enabled {
return;
}
if requirements.resolved_targets() {
required
.capabilities
.insert(BackendCapability::NetworkResolvedTargets);
}
if requirements.domain_rules() {
required
.capabilities
.insert(BackendCapability::NetworkDomainRules);
}
if requirements.local_address_restrictions() {
required
.capabilities
.insert(BackendCapability::NetworkLocalAddressRestrictions);
}
if requirements.local_ipc_isolation() {
required
.capabilities
.insert(BackendCapability::NetworkLocalIpcIsolation);
}
if requirements.local_ipc_rules() {
required
.capabilities
.insert(BackendCapability::NetworkLocalIpcRules);
}
if requirements.local_ipc_deny_rules() {
required
.capabilities
.insert(BackendCapability::NetworkLocalIpcDenyRules);
}
}
pub(super) fn add_environment_capabilities(
required: &mut BackendCapabilities,
sandbox: &EffectiveSandbox,
) {
let requirements = sandbox.environment().requirements();
required.capabilities.insert(match requirements.base() {
EnvironmentBase::All => BackendCapability::EnvironmentAll,
EnvironmentBase::Core => BackendCapability::EnvironmentCore,
EnvironmentBase::None => BackendCapability::EnvironmentNone,
});
if requirements.filters() {
required
.capabilities
.insert(BackendCapability::EnvironmentFilters);
}
if requirements.overrides() {
required
.capabilities
.insert(BackendCapability::EnvironmentOverrides);
}
}