1#![deny(unsafe_code)]
4#![warn(missing_docs)]
5
6use parallax_core::{ExecutionLimits, Remediation};
7use serde::{Deserialize, Serialize};
8use std::time::Duration;
9
10#[derive(Clone, Debug, Serialize, Deserialize)]
12pub struct SandboxPolicy {
13 pub limits: ExecutionLimits,
15 pub allow_network: bool,
17 pub allow_fs_read: bool,
19 pub allow_fs_write: bool,
21 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 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 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#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
69pub struct CapabilityToken {
70 pub name: String,
72 pub scope: Option<String>,
74}
75
76impl CapabilityToken {
77 pub fn new(name: impl Into<String>) -> Self {
79 Self {
80 name: name.into(),
81 scope: None,
82 }
83 }
84}
85
86pub 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}