mcp_exec/
config.rs

1//! Configuration primitives describing how the executor resolves, verifies, and
2//! runs Wasm components.
3
4use std::collections::HashMap;
5use std::fmt;
6use std::sync::Arc;
7use std::time::Duration;
8
9use greentic_types::TenantCtx;
10
11use crate::store::ToolStore;
12
13/// Configuration for a single executor invocation.
14#[derive(Clone)]
15pub struct ExecConfig {
16    pub store: ToolStore,
17    pub security: VerifyPolicy,
18    pub runtime: RuntimePolicy,
19    pub http_enabled: bool,
20    /// Optional secrets-store binding implementing greentic:secrets/store@1.0.0.
21    /// When absent, secrets imports will return a host error.
22    pub secrets_store: Option<DynSecretsStore>,
23}
24
25/// Policy describing how artifacts must be verified prior to execution.
26#[derive(Clone, Debug, Default)]
27pub struct VerifyPolicy {
28    /// Whether artifacts without a matching digest/signature are still allowed.
29    pub allow_unverified: bool,
30    /// Expected digests (hex encoded) keyed by component identifier.
31    pub required_digests: HashMap<String, String>,
32    /// Signers that are trusted to vouch for artifacts.
33    pub trusted_signers: Vec<String>,
34}
35
36/// Runtime resource limits applied to the Wasm execution.
37#[derive(Clone, Debug)]
38pub struct RuntimePolicy {
39    pub fuel: Option<u64>,
40    pub max_memory: Option<u64>,
41    pub wallclock_timeout: Duration,
42    pub per_call_timeout: Duration,
43    pub max_attempts: u32,
44    pub base_backoff: Duration,
45}
46
47impl Default for RuntimePolicy {
48    fn default() -> Self {
49        Self {
50            fuel: None,
51            max_memory: None,
52            wallclock_timeout: Duration::from_secs(30),
53            per_call_timeout: Duration::from_secs(10),
54            max_attempts: 1,
55            base_backoff: Duration::from_millis(100),
56        }
57    }
58}
59
60/// Host-facing secrets-store trait mirroring greentic:secrets/store@1.0.0.
61pub trait SecretsStore: Send + Sync {
62    /// Read bytes for the scoped secret name.
63    fn read(&self, scope: &TenantCtx, name: &str) -> Result<Vec<u8>, String>;
64
65    /// Upsert bytes for the scoped secret name. Defaults to an error when not implemented.
66    fn write(&self, scope: &TenantCtx, name: &str, bytes: &[u8]) -> Result<(), String> {
67        let _ = (scope, name, bytes);
68        Err("write-not-implemented".into())
69    }
70
71    /// Delete the scoped secret. Defaults to an error when not implemented.
72    fn delete(&self, scope: &TenantCtx, name: &str) -> Result<(), String> {
73        let _ = (scope, name);
74        Err("delete-not-implemented".into())
75    }
76}
77
78/// Shared secrets-store handle.
79pub type DynSecretsStore = Arc<dyn SecretsStore>;
80
81impl fmt::Debug for ExecConfig {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        f.debug_struct("ExecConfig")
84            .field("store", &self.store)
85            .field("security", &self.security)
86            .field("runtime", &self.runtime)
87            .field("http_enabled", &self.http_enabled)
88            .field(
89                "secrets_store",
90                &self.secrets_store.as_ref().map(|_| "<dyn SecretsStore>"),
91            )
92            .finish()
93    }
94}