diff --git a/lib/apps/fabro-server/src/spawn_env.rs b/lib/apps/fabro-server/src/spawn_env.rs index bfea6b038..346053c93 100644 --- a/lib/apps/fabro-server/src/spawn_env.rs +++ b/lib/apps/fabro-server/src/spawn_env.rs @@ -50,6 +50,18 @@ const WORKER_ENV_ALLOWLIST: &[&str] = &[ EnvVars::AWS_CONTAINER_CREDENTIALS_RELATIVE_URI, EnvVars::AWS_CONTAINER_CREDENTIALS_FULL_URI, EnvVars::AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE, + // Petri's sandbox-driver plugins are resolved in the worker, where a + // Petri run executes: the plugin path, checksum and dev-mode overrides + // cross with `PATH`, so the worker finds the plugins the server would. + EnvVars::PETRI_SANDBOX_HOST_PLUGIN, + EnvVars::PETRI_SANDBOX_HOST_SHA256, + EnvVars::PETRI_SANDBOX_DOCKER_PLUGIN, + EnvVars::PETRI_SANDBOX_DOCKER_SHA256, + EnvVars::PETRI_SANDBOX_DAYTONA_PLUGIN, + EnvVars::PETRI_SANDBOX_DAYTONA_SHA256, + EnvVars::PETRI_SANDBOX_PLUGIN_DEV, + EnvVars::PETRI_SANDBOX_DOCKER_HOST_ADDRESS, + EnvVars::PETRI_SANDBOX_ACTION_HOST_IMAGE, ]; const RENDER_GRAPH_ENV_ALLOWLIST: &[&str] = &[EnvVars::PATH, EnvVars::HOME, EnvVars::TMPDIR]; @@ -144,6 +156,11 @@ mod tests { ("FABRO_DEV_TOKEN".to_string(), "garbage".to_string()), ("FABRO_WORKER_TOKEN".to_string(), "leak".to_string()), ("MY_API_KEY".to_string(), "blocked".to_string()), + ( + "PETRI_SANDBOX_HOST_PLUGIN".to_string(), + "/opt/petri/sandbox-driver-host".to_string(), + ), + ("PETRI_SANDBOX_PLUGIN_DEV".to_string(), "1".to_string()), ]); let mut cmd = env_command(); apply_allowlist(&mut cmd, WORKER_ENV_ALLOWLIST, &|name| { @@ -178,6 +195,16 @@ mod tests { Some("xterm-256color") ); assert_eq!(actual.get("NO_COLOR").map(String::as_str), Some("1")); + // Petri's plugin overrides cross so the worker resolves the same + // sandbox-driver plugins the server would. + assert_eq!( + actual.get("PETRI_SANDBOX_HOST_PLUGIN").map(String::as_str), + Some("/opt/petri/sandbox-driver-host") + ); + assert_eq!( + actual.get("PETRI_SANDBOX_PLUGIN_DEV").map(String::as_str), + Some("1") + ); assert_eq!(actual.get("CLICOLOR").map(String::as_str), Some("0")); assert_eq!(actual.get("CLICOLOR_FORCE").map(String::as_str), Some("1")); // Bedrock SigV4 chain inputs cross into the worker so it can re-resolve diff --git a/lib/foundation/fabro-static/src/env_vars.rs b/lib/foundation/fabro-static/src/env_vars.rs index 016e8936b..11178bef6 100644 --- a/lib/foundation/fabro-static/src/env_vars.rs +++ b/lib/foundation/fabro-static/src/env_vars.rs @@ -42,6 +42,34 @@ impl EnvVars { pub const FABRO_WEB_URL: &'static str = "FABRO_WEB_URL"; pub const FABRO_WORKER_TOKEN: &'static str = "FABRO_WORKER_TOKEN"; + // Petri's sandbox-driver plugins: where each provider's plugin executable + // is, its checksum override, dev mode for unpinned plugins, and how a + // remote Docker daemon's containers reach this machine. A run's worker + // resolves the plugins, so these cross into the worker process. + pub const PETRI_SANDBOX_HOST_PLUGIN: &'static str = "PETRI_SANDBOX_HOST_PLUGIN"; + pub const PETRI_SANDBOX_HOST_SHA256: &'static str = "PETRI_SANDBOX_HOST_SHA256"; + pub const PETRI_SANDBOX_DOCKER_PLUGIN: &'static str = "PETRI_SANDBOX_DOCKER_PLUGIN"; + pub const PETRI_SANDBOX_DOCKER_SHA256: &'static str = "PETRI_SANDBOX_DOCKER_SHA256"; + pub const PETRI_SANDBOX_DAYTONA_PLUGIN: &'static str = "PETRI_SANDBOX_DAYTONA_PLUGIN"; + pub const PETRI_SANDBOX_DAYTONA_SHA256: &'static str = "PETRI_SANDBOX_DAYTONA_SHA256"; + pub const PETRI_SANDBOX_PLUGIN_DEV: &'static str = "PETRI_SANDBOX_PLUGIN_DEV"; + pub const PETRI_SANDBOX_DOCKER_HOST_ADDRESS: &'static str = "PETRI_SANDBOX_DOCKER_HOST_ADDRESS"; + pub const PETRI_SANDBOX_ACTION_HOST_IMAGE: &'static str = "PETRI_SANDBOX_ACTION_HOST_IMAGE"; + + /// Every Petri plugin variable, in one list for the process boundaries + /// that forward them. + pub const PETRI_SANDBOX_PLUGIN_VARS: &'static [&'static str] = &[ + Self::PETRI_SANDBOX_HOST_PLUGIN, + Self::PETRI_SANDBOX_HOST_SHA256, + Self::PETRI_SANDBOX_DOCKER_PLUGIN, + Self::PETRI_SANDBOX_DOCKER_SHA256, + Self::PETRI_SANDBOX_DAYTONA_PLUGIN, + Self::PETRI_SANDBOX_DAYTONA_SHA256, + Self::PETRI_SANDBOX_PLUGIN_DEV, + Self::PETRI_SANDBOX_DOCKER_HOST_ADDRESS, + Self::PETRI_SANDBOX_ACTION_HOST_IMAGE, + ]; + // LLM providers and tool integrations pub const ANTHROPIC_API_KEY: &'static str = "ANTHROPIC_API_KEY"; pub const AWS_BEARER_TOKEN_BEDROCK: &'static str = "AWS_BEARER_TOKEN_BEDROCK"; @@ -197,6 +225,15 @@ mod tests { EnvVars::FABRO_VERBOSE, EnvVars::FABRO_WEB_URL, EnvVars::FABRO_WORKER_TOKEN, + EnvVars::PETRI_SANDBOX_HOST_PLUGIN, + EnvVars::PETRI_SANDBOX_HOST_SHA256, + EnvVars::PETRI_SANDBOX_DOCKER_PLUGIN, + EnvVars::PETRI_SANDBOX_DOCKER_SHA256, + EnvVars::PETRI_SANDBOX_DAYTONA_PLUGIN, + EnvVars::PETRI_SANDBOX_DAYTONA_SHA256, + EnvVars::PETRI_SANDBOX_PLUGIN_DEV, + EnvVars::PETRI_SANDBOX_DOCKER_HOST_ADDRESS, + EnvVars::PETRI_SANDBOX_ACTION_HOST_IMAGE, EnvVars::ANTHROPIC_API_KEY, EnvVars::ANTHROPIC_BASE_URL, EnvVars::AWS_BEARER_TOKEN_BEDROCK, diff --git a/lib/foundation/fabro-test/src/lib.rs b/lib/foundation/fabro-test/src/lib.rs index dadcaee70..44a665d13 100644 --- a/lib/foundation/fabro-test/src/lib.rs +++ b/lib/foundation/fabro-test/src/lib.rs @@ -177,6 +177,11 @@ pub fn isolated_env(home_dir: &Path) -> HashMap { if let Some(path) = std::env::var_os(EnvVars::PATH).and_then(|value| value.into_string().ok()) { env.insert(EnvVars::PATH.to_string(), path); } + for name in EnvVars::PETRI_SANDBOX_PLUGIN_VARS { + if let Some(value) = std::env::var_os(name).and_then(|value| value.into_string().ok()) { + env.insert((*name).to_string(), value); + } + } env.insert(EnvVars::NO_COLOR.to_string(), "1".to_string()); env.insert(EnvVars::HOME.to_string(), home_dir.display().to_string()); env.insert( @@ -216,6 +221,14 @@ fn apply_test_isolation_with_lookup( if let Some(path) = lookup(EnvVars::PATH) { cmd.env(EnvVars::PATH, path); } + // Petri resolves its sandbox-driver plugins from these, in the server a + // test starts and in the workers that server launches; a developer's + // plugin override reaches them like `PATH` does. + for name in EnvVars::PETRI_SANDBOX_PLUGIN_VARS { + if let Some(value) = lookup(name) { + cmd.env(name, value); + } + } cmd.env(EnvVars::NO_COLOR, "1"); cmd.env(EnvVars::HOME, home_dir); cmd.env(EnvVars::FABRO_NO_UPGRADE_CHECK, "true")