Skip to main content

parallax_security/
lib.rs

1//! Capability tokens and resource-limit policies for Parallax.
2
3#![deny(unsafe_code)]
4#![warn(missing_docs)]
5
6use parallax_core::{ExecutionLimits, Remediation};
7use serde::{Deserialize, Serialize};
8use std::time::Duration;
9
10/// Sandbox / security policy applied to guest executions.
11#[derive(Clone, Debug, Serialize, Deserialize)]
12pub struct SandboxPolicy {
13    /// Execution limits.
14    pub limits: ExecutionLimits,
15    /// Whether guest code may perform network I/O (not enforced in MVP workers).
16    pub allow_network: bool,
17    /// Whether guest code may read arbitrary filesystem paths.
18    pub allow_fs_read: bool,
19    /// Whether guest code may write to the filesystem.
20    pub allow_fs_write: bool,
21    /// Maximum concurrent workers managed by the runtime.
22    pub max_concurrent_workers: usize,
23}
24
25impl Default for SandboxPolicy {
26    fn default() -> Self {
27        Self {
28            limits: ExecutionLimits::default(),
29            allow_network: false,
30            allow_fs_read: true,
31            allow_fs_write: false,
32            max_concurrent_workers: 4,
33        }
34    }
35}
36
37impl SandboxPolicy {
38    /// Strict policy for untrusted code.
39    pub fn strict() -> Self {
40        Self {
41            limits: ExecutionLimits {
42                timeout: Duration::from_secs(5),
43                max_output_bytes: 256 * 1024,
44                max_message_bytes: 4 * 1024 * 1024,
45                max_memory_bytes: Some(64 * 1024 * 1024),
46                max_fuel: Some(1_000_000),
47            },
48            allow_network: false,
49            allow_fs_read: false,
50            allow_fs_write: false,
51            max_concurrent_workers: 2,
52        }
53    }
54
55    /// Validate that configured limits are sane.
56    pub fn validate(&self) -> Result<(), String> {
57        if self.limits.timeout.is_zero() {
58            return Err("timeout must be > 0".into());
59        }
60        if self.max_concurrent_workers == 0 {
61            return Err("max_concurrent_workers must be >= 1".into());
62        }
63        Ok(())
64    }
65}
66
67/// Granted capability token recorded in snapshots / state.
68#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
69pub struct CapabilityToken {
70    /// Token name.
71    pub name: String,
72    /// Optional scope description.
73    pub scope: Option<String>,
74}
75
76impl CapabilityToken {
77    /// Construct a named token.
78    pub fn new(name: impl Into<String>) -> Self {
79        Self {
80            name: name.into(),
81            scope: None,
82        }
83    }
84}
85
86/// Helper remediations for common security violations.
87pub fn remediation_for_network() -> Remediation {
88    Remediation::with_detail(
89        "Disable network-dependent guest code or raise allow_network in policy",
90        "MVP adapters do not grant network access by default",
91    )
92}