From 2af2276e59a3faaeb80898291a26c5a3d9a912a3 Mon Sep 17 00:00:00 2001 From: viyatb-oai Date: Wed, 3 Jun 2026 07:50:00 -0700 Subject: [PATCH] refactor: name Noise relay protocol explicitly Co-authored-by: Codex noreply@openai.com --- codex-rs/cli/src/main.rs | 2 +- codex-rs/core-api/src/lib.rs | 12 +- codex-rs/exec-server/README.md | 2 +- codex-rs/exec-server/src/client.rs | 18 +-- codex-rs/exec-server/src/client_api.rs | 42 +++--- codex-rs/exec-server/src/client_transport.rs | 23 ++- codex-rs/exec-server/src/environment.rs | 12 +- codex-rs/exec-server/src/lib.rs | 20 +-- .../{secure_channel.rs => noise_channel.rs} | 134 +++++++++--------- ...hannel_tests.rs => noise_channel_tests.rs} | 64 ++++----- .../environment.rs | 104 +++++++------- .../environment_tests.rs | 21 ++- .../{secure_relay => noise_relay}/harness.rs | 64 ++++----- .../message_framing.rs | 20 +-- .../message_framing_tests.rs | 14 +- .../src/{secure_relay => noise_relay}/mod.rs | 18 +-- .../ordered_ciphertext.rs | 10 +- .../ordered_ciphertext_tests.rs | 0 codex-rs/exec-server/src/relay.rs | 4 +- codex-rs/exec-server/src/remote.rs | 68 ++++----- codex-rs/exec-server/src/remote_tests.rs | 16 +-- codex-rs/exec-server/tests/relay.rs | 78 +++++----- 22 files changed, 373 insertions(+), 373 deletions(-) rename codex-rs/exec-server/src/{secure_channel.rs => noise_channel.rs} (74%) rename codex-rs/exec-server/src/{secure_channel_tests.rs => noise_channel_tests.rs} (73%) rename codex-rs/exec-server/src/{secure_relay => noise_relay}/environment.rs (83%) rename codex-rs/exec-server/src/{secure_relay => noise_relay}/environment_tests.rs (82%) rename codex-rs/exec-server/src/{secure_relay => noise_relay}/harness.rs (86%) rename codex-rs/exec-server/src/{secure_relay => noise_relay}/message_framing.rs (79%) rename codex-rs/exec-server/src/{secure_relay => noise_relay}/message_framing_tests.rs (73%) rename codex-rs/exec-server/src/{secure_relay => noise_relay}/mod.rs (51%) rename codex-rs/exec-server/src/{secure_relay => noise_relay}/ordered_ciphertext.rs (87%) rename codex-rs/exec-server/src/{secure_relay => noise_relay}/ordered_ciphertext_tests.rs (100%) diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index 5fb065dce9..848d3e16bb 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -1620,7 +1620,7 @@ async fn run_exec_server_command( remote_config.name = name; } if cmd.enable_noise { - remote_config.relay_security = codex_exec_server::RemoteRelaySecurity::Noise; + remote_config.relay_protocol = codex_exec_server::RemoteRelayProtocol::Noise; } codex_exec_server::run_remote_environment(remote_config, runtime_paths).await?; Ok(()) diff --git a/codex-rs/core-api/src/lib.rs b/codex-rs/core-api/src/lib.rs index cb652c664f..81cddce050 100644 --- a/codex-rs/core-api/src/lib.rs +++ b/codex-rs/core-api/src/lib.rs @@ -47,12 +47,12 @@ pub use codex_core::thread_store_from_config; pub use codex_exec_server::EnvironmentManager; pub use codex_exec_server::ExecServerError; pub use codex_exec_server::ExecServerRuntimePaths; -pub use codex_exec_server::SecureChannelIdentity; -pub use codex_exec_server::SecureChannelPublicKey; -pub use codex_exec_server::SecureRendezvousConnectArgs; -pub use codex_exec_server::SecureRendezvousConnectBundle; -pub use codex_exec_server::SecureRendezvousConnectProvider; -pub use codex_exec_server::SharedSecureRendezvousConnectProvider; +pub use codex_exec_server::NoiseChannelIdentity; +pub use codex_exec_server::NoiseChannelPublicKey; +pub use codex_exec_server::NoiseRendezvousConnectArgs; +pub use codex_exec_server::NoiseRendezvousConnectBundle; +pub use codex_exec_server::NoiseRendezvousConnectProvider; +pub use codex_exec_server::SharedNoiseRendezvousConnectProvider; pub use codex_extension_api::empty_extension_registry; pub use codex_features::Feature; pub use codex_features::Features; diff --git a/codex-rs/exec-server/README.md b/codex-rs/exec-server/README.md index 5f93e8bda9..1117885283 100644 --- a/codex-rs/exec-server/README.md +++ b/codex-rs/exec-server/README.md @@ -29,7 +29,7 @@ then reconnects to the service-provided rendezvous websocket as the environment. It uses the legacy relay contract by default for compatibility with existing registries and harnesses. `--enable-noise` explicitly opts into Noise-encrypted relay registration and requires both the registry and harness to support the -secure relay contract. Container entrypoints can make the same explicit choice +Noise relay contract. Container entrypoints can make the same explicit choice by setting `CODEX_EXEC_SERVER_ENABLE_NOISE=true`. It uses the standard Codex ChatGPT sign-in state; run `codex login` first when remote registration needs authentication. Containerized callers that receive an diff --git a/codex-rs/exec-server/src/client.rs b/codex-rs/exec-server/src/client.rs index 09c9b2c807..34b659e861 100644 --- a/codex-rs/exec-server/src/client.rs +++ b/codex-rs/exec-server/src/client.rs @@ -23,9 +23,9 @@ use crate::ProcessId; use crate::client_api::ExecServerClientConnectOptions; use crate::client_api::ExecServerTransportParams; use crate::client_api::HttpClient; +use crate::client_api::NoiseRendezvousConnectArgs; +use crate::client_api::NoiseRendezvousConnectBundle; use crate::client_api::RemoteExecServerConnectArgs; -use crate::client_api::SecureRendezvousConnectArgs; -use crate::client_api::SecureRendezvousConnectBundle; use crate::client_api::StdioExecServerConnectArgs; use crate::connection::JsonRpcConnection; use crate::process::ExecProcessEvent; @@ -117,8 +117,8 @@ impl From for ExecServerClientConnectOptions { } } -impl From for ExecServerClientConnectOptions { - fn from(value: SecureRendezvousConnectArgs) -> Self { +impl From for ExecServerClientConnectOptions { + fn from(value: NoiseRendezvousConnectArgs) -> Self { Self { client_name: value.client_name, initialize_timeout: value.initialize_timeout, @@ -149,10 +149,10 @@ impl RemoteExecServerConnectArgs { } } -impl SecureRendezvousConnectArgs { +impl NoiseRendezvousConnectArgs { pub fn new( - bundle: SecureRendezvousConnectBundle, - harness_identity: crate::SecureChannelIdentity, + bundle: NoiseRendezvousConnectBundle, + harness_identity: crate::NoiseChannelIdentity, client_name: String, ) -> Self { Self { @@ -260,7 +260,7 @@ impl LazyRemoteExecServerClient { if matches!( &self.transport_params, ExecServerTransportParams::WebSocketUrl { .. } - | ExecServerTransportParams::SecureRendezvous { .. } + | ExecServerTransportParams::NoiseRendezvous { .. } ) => { ExecServerClient::connect_for_transport(self.transport_params.clone()).await? @@ -348,7 +348,7 @@ pub enum ExecServerError { #[error("environment registry request failed: {0}")] EnvironmentRegistryRequest(#[from] reqwest::Error), #[error(transparent)] - SecureChannel(#[from] crate::SecureChannelError), + NoiseChannel(#[from] crate::NoiseChannelError), } impl ExecServerClient { diff --git a/codex-rs/exec-server/src/client_api.rs b/codex-rs/exec-server/src/client_api.rs index 30f248b7ea..ef7ffd68c4 100644 --- a/codex-rs/exec-server/src/client_api.rs +++ b/codex-rs/exec-server/src/client_api.rs @@ -9,8 +9,8 @@ use crate::ExecServerError; use crate::HttpRequestParams; use crate::HttpRequestResponse; use crate::HttpResponseBodyStream; -use crate::SecureChannelIdentity; -use crate::SecureChannelPublicKey; +use crate::NoiseChannelIdentity; +use crate::NoiseChannelPublicKey; pub(crate) const DEFAULT_REMOTE_EXEC_SERVER_CONNECT_TIMEOUT: Duration = Duration::from_secs(10); pub(crate) const DEFAULT_REMOTE_EXEC_SERVER_INITIALIZE_TIMEOUT: Duration = Duration::from_secs(10); @@ -33,19 +33,19 @@ pub struct RemoteExecServerConnectArgs { pub resume_session_id: Option, } -/// Registry-authorized material for one secure rendezvous connection attempt. +/// Registry-authorized material for one Noise rendezvous connection attempt. #[derive(Clone)] -pub struct SecureRendezvousConnectBundle { +pub struct NoiseRendezvousConnectBundle { pub websocket_url: String, pub environment_id: String, pub executor_registration_id: String, - pub executor_public_key: SecureChannelPublicKey, + pub executor_public_key: NoiseChannelPublicKey, pub harness_key_authorization: String, } -impl std::fmt::Debug for SecureRendezvousConnectBundle { +impl std::fmt::Debug for NoiseRendezvousConnectBundle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("SecureRendezvousConnectBundle") + f.debug_struct("NoiseRendezvousConnectBundle") .field( "websocket_url", &redacted_websocket_url(&self.websocket_url), @@ -58,20 +58,20 @@ impl std::fmt::Debug for SecureRendezvousConnectBundle { } } -/// Connection arguments for an authenticated secure rendezvous exec-server. +/// Connection arguments for an authenticated Noise rendezvous exec-server. #[derive(Clone)] -pub struct SecureRendezvousConnectArgs { - pub bundle: SecureRendezvousConnectBundle, - pub harness_identity: SecureChannelIdentity, +pub struct NoiseRendezvousConnectArgs { + pub bundle: NoiseRendezvousConnectBundle, + pub harness_identity: NoiseChannelIdentity, pub client_name: String, pub connect_timeout: Duration, pub initialize_timeout: Duration, pub resume_session_id: Option, } -impl std::fmt::Debug for SecureRendezvousConnectArgs { +impl std::fmt::Debug for NoiseRendezvousConnectArgs { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("SecureRendezvousConnectArgs") + f.debug_struct("NoiseRendezvousConnectArgs") .field("bundle", &self.bundle) .field("harness_identity", &"") .field("client_name", &self.client_name) @@ -82,19 +82,19 @@ impl std::fmt::Debug for SecureRendezvousConnectArgs { } } -/// Supplies fresh registry-authorized material for secure rendezvous connections. +/// Supplies fresh registry-authorized material for Noise rendezvous connections. /// /// Implementations must preserve one endpoint-local harness identity while /// refreshing short-lived registry material for every physical connection attempt. -pub trait SecureRendezvousConnectProvider: Send + Sync { +pub trait NoiseRendezvousConnectProvider: Send + Sync { /// Environment ID this provider is authorized to connect to. fn environment_id(&self) -> &str; /// Returns a fresh atomic bundle for one physical connection attempt. - fn connect_args(&self) -> BoxFuture<'_, Result>; + fn connect_args(&self) -> BoxFuture<'_, Result>; } -pub type SharedSecureRendezvousConnectProvider = Arc; +pub type SharedNoiseRendezvousConnectProvider = Arc; /// Stdio connection arguments for a command-backed exec-server. #[derive(Debug, Clone, PartialEq, Eq)] @@ -122,8 +122,8 @@ pub(crate) enum ExecServerTransportParams { connect_timeout: Duration, initialize_timeout: Duration, }, - SecureRendezvous { - provider: SharedSecureRendezvousConnectProvider, + NoiseRendezvous { + provider: SharedNoiseRendezvousConnectProvider, }, #[allow(dead_code)] StdioCommand { @@ -145,8 +145,8 @@ impl std::fmt::Debug for ExecServerTransportParams { .field("connect_timeout", connect_timeout) .field("initialize_timeout", initialize_timeout) .finish(), - Self::SecureRendezvous { provider } => f - .debug_struct("SecureRendezvous") + Self::NoiseRendezvous { provider } => f + .debug_struct("NoiseRendezvous") .field("environment_id", &provider.environment_id()) .finish(), Self::StdioCommand { diff --git a/codex-rs/exec-server/src/client_transport.rs b/codex-rs/exec-server/src/client_transport.rs index b04b1c7e24..8818c0ea47 100644 --- a/codex-rs/exec-server/src/client_transport.rs +++ b/codex-rs/exec-server/src/client_transport.rs @@ -12,15 +12,15 @@ use codex_utils_rustls_provider::ensure_rustls_crypto_provider; use crate::ExecServerClient; use crate::ExecServerError; +use crate::client_api::NoiseRendezvousConnectArgs; use crate::client_api::RemoteExecServerConnectArgs; -use crate::client_api::SecureRendezvousConnectArgs; use crate::client_api::StdioExecServerCommand; use crate::client_api::StdioExecServerConnectArgs; use crate::client_api::redacted_websocket_url; use crate::connection::JsonRpcConnection; +use crate::noise_relay::noise_harness_connection_from_websocket; +use crate::noise_relay::noise_relay_websocket_config; use crate::relay::harness_connection_from_websocket; -use crate::secure_relay::secure_harness_connection_from_websocket; -use crate::secure_relay::secure_relay_websocket_config; const ENVIRONMENT_CLIENT_NAME: &str = "codex-environment"; @@ -43,15 +43,14 @@ impl ExecServerClient { }) .await } - crate::client_api::ExecServerTransportParams::SecureRendezvous { provider } => { + crate::client_api::ExecServerTransportParams::NoiseRendezvous { provider } => { let args = provider.connect_args().await?; if args.bundle.environment_id != provider.environment_id() { return Err(ExecServerError::Protocol( - "secure rendezvous provider returned a different environment id" - .to_string(), + "Noise rendezvous provider returned a different environment id".to_string(), )); } - Self::connect_secure_rendezvous(args).await + Self::connect_noise_rendezvous(args).await } crate::client_api::ExecServerTransportParams::StdioCommand { command, @@ -94,8 +93,8 @@ impl ExecServerClient { Self::connect(connection, args.into()).await } - pub async fn connect_secure_rendezvous( - args: SecureRendezvousConnectArgs, + pub async fn connect_noise_rendezvous( + args: NoiseRendezvousConnectArgs, ) -> Result { ensure_rustls_crypto_provider(); let websocket_url = args.bundle.websocket_url.clone(); @@ -105,7 +104,7 @@ impl ExecServerClient { connect_timeout, connect_async_with_config( websocket_url.as_str(), - Some(secure_relay_websocket_config()), + Some(noise_relay_websocket_config()), /*disable_nagle*/ false, ), ) @@ -119,8 +118,8 @@ impl ExecServerClient { source, })?; - let connection_label = format!("secure exec-server rendezvous websocket {diagnostic_url}"); - let connection = secure_harness_connection_from_websocket( + let connection_label = format!("Noise exec-server rendezvous websocket {diagnostic_url}"); + let connection = noise_harness_connection_from_websocket( stream, connection_label, args.bundle.environment_id.clone(), diff --git a/codex-rs/exec-server/src/environment.rs b/codex-rs/exec-server/src/environment.rs index e5d58f55c2..bb99b1f6bc 100644 --- a/codex-rs/exec-server/src/environment.rs +++ b/codex-rs/exec-server/src/environment.rs @@ -6,7 +6,7 @@ use crate::ExecServerError; use crate::ExecServerRuntimePaths; use crate::ExecutorFileSystem; use crate::HttpClient; -use crate::SharedSecureRendezvousConnectProvider; +use crate::SharedNoiseRendezvousConnectProvider; use crate::client::LazyRemoteExecServerClient; use crate::client::http_client::ReqwestHttpClient; use crate::client_api::ExecServerTransportParams; @@ -280,10 +280,10 @@ impl EnvironmentManager { /// Adds or replaces a named remote environment that connects through an /// authenticated, end-to-end encrypted rendezvous stream. - pub fn upsert_secure_environment( + pub fn upsert_noise_environment( &self, environment_id: String, - provider: SharedSecureRendezvousConnectProvider, + provider: SharedNoiseRendezvousConnectProvider, ) -> Result<(), ExecServerError> { if environment_id.is_empty() { return Err(ExecServerError::Protocol( @@ -292,11 +292,11 @@ impl EnvironmentManager { } if environment_id != provider.environment_id() { return Err(ExecServerError::Protocol( - "secure environment id does not match connection provider".to_string(), + "Noise environment id does not match connection provider".to_string(), )); } let environment = Environment::remote_with_transport( - ExecServerTransportParams::SecureRendezvous { provider }, + ExecServerTransportParams::NoiseRendezvous { provider }, self.local_runtime_paths.clone(), ); self.environments @@ -411,7 +411,7 @@ impl Environment { websocket_url: exec_server_url, .. } => Some(exec_server_url.clone()), - ExecServerTransportParams::SecureRendezvous { .. } => None, + ExecServerTransportParams::NoiseRendezvous { .. } => None, ExecServerTransportParams::StdioCommand { .. } => None, }; let client = LazyRemoteExecServerClient::new(remote_transport.clone()); diff --git a/codex-rs/exec-server/src/lib.rs b/codex-rs/exec-server/src/lib.rs index 5a1bed176d..93df5cc10c 100644 --- a/codex-rs/exec-server/src/lib.rs +++ b/codex-rs/exec-server/src/lib.rs @@ -12,6 +12,8 @@ mod fs_helper_main; mod fs_sandbox; mod local_file_system; mod local_process; +mod noise_channel; +mod noise_relay; mod process; mod process_id; mod protocol; @@ -23,8 +25,6 @@ mod remote_process; mod rpc; mod runtime_paths; mod sandboxed_file_system; -mod secure_channel; -mod secure_relay; mod server; pub use client::ExecServerClient; @@ -33,11 +33,11 @@ pub use client::http_client::HttpResponseBodyStream; pub use client::http_client::ReqwestHttpClient; pub use client_api::ExecServerClientConnectOptions; pub use client_api::HttpClient; +pub use client_api::NoiseRendezvousConnectArgs; +pub use client_api::NoiseRendezvousConnectBundle; +pub use client_api::NoiseRendezvousConnectProvider; pub use client_api::RemoteExecServerConnectArgs; -pub use client_api::SecureRendezvousConnectArgs; -pub use client_api::SecureRendezvousConnectBundle; -pub use client_api::SecureRendezvousConnectProvider; -pub use client_api::SharedSecureRendezvousConnectProvider; +pub use client_api::SharedNoiseRendezvousConnectProvider; pub use codex_file_system::CopyOptions; pub use codex_file_system::CreateDirectoryOptions; pub use codex_file_system::ExecutorFileSystem; @@ -58,6 +58,9 @@ pub use fs_helper::CODEX_FS_HELPER_ARG1; pub use fs_helper_main::main as run_fs_helper_main; pub use local_file_system::LOCAL_FS; pub use local_file_system::LocalFileSystem; +pub use noise_channel::NoiseChannelError; +pub use noise_channel::NoiseChannelIdentity; +pub use noise_channel::NoiseChannelPublicKey; pub use process::ExecBackend; pub use process::ExecProcess; pub use process::ExecProcessEvent; @@ -107,12 +110,9 @@ pub use protocol::WriteParams; pub use protocol::WriteResponse; pub use protocol::WriteStatus; pub use remote::RemoteEnvironmentConfig; -pub use remote::RemoteRelaySecurity; +pub use remote::RemoteRelayProtocol; pub use remote::run_remote_environment; pub use runtime_paths::ExecServerRuntimePaths; -pub use secure_channel::SecureChannelError; -pub use secure_channel::SecureChannelIdentity; -pub use secure_channel::SecureChannelPublicKey; pub use server::DEFAULT_LISTEN_URL; pub use server::ExecServerListenUrlParseError; pub use server::run_main; diff --git a/codex-rs/exec-server/src/secure_channel.rs b/codex-rs/exec-server/src/noise_channel.rs similarity index 74% rename from codex-rs/exec-server/src/secure_channel.rs rename to codex-rs/exec-server/src/noise_channel.rs index bda4109039..a7254150c0 100644 --- a/codex-rs/exec-server/src/secure_channel.rs +++ b/codex-rs/exec-server/src/noise_channel.rs @@ -29,7 +29,7 @@ use serde::Serialize; use crate::aws_lc_ml_kem::AwsLcMlKem768; use crate::aws_lc_ml_kem::PUBLIC_KEY_LEN as MLKEM768_PUBLIC_KEY_LEN; -pub const SECURE_CHANNEL_SUITE: &str = "Noise_hybridIK_X25519+MLKEM768_AESGCM_SHA256"; +pub const NOISE_CHANNEL_SUITE: &str = "Noise_hybridIK_X25519+MLKEM768_AESGCM_SHA256"; const X25519_PUBLIC_KEY_LEN: usize = 32; const MAX_TRANSPORT_RECORDS_PER_DIRECTION: u64 = u32::MAX as u64; @@ -40,22 +40,22 @@ type Transport = TransportState; type DhKeyPair = KeyPair<::PubKey, ::PrivateKey>; type KemKeyPair = KeyPair<::PubKey, ::SecretKey>; -/// Public key material for the exec-server secure relay Noise suite. +/// Public key material for the exec-server Noise-over-relay suite. /// /// The suite field is part of the serialized contract. A key from a different /// suite must not be interpreted as compatible merely because one component has /// a familiar byte length. #[derive(Clone, Eq, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] -pub struct SecureChannelPublicKey { +pub struct NoiseChannelPublicKey { suite: String, x25519_public_key: String, mlkem768_public_key: String, } -impl std::fmt::Debug for SecureChannelPublicKey { +impl std::fmt::Debug for NoiseChannelPublicKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("SecureChannelPublicKey") + f.debug_struct("NoiseChannelPublicKey") .field("suite", &self.suite) .field("x25519_public_key", &"") .field("mlkem768_public_key", &"") @@ -63,16 +63,16 @@ impl std::fmt::Debug for SecureChannelPublicKey { } } -impl SecureChannelPublicKey { +impl NoiseChannelPublicKey { /// Validate suite selection, encoding, and exact key lengths. - pub fn validate(&self) -> Result<(), SecureChannelError> { + pub fn validate(&self) -> Result<(), NoiseChannelError> { let _ = self.decode()?; Ok(()) } fn from_keypairs(dh: &DhKeyPair, kem: &KemKeyPair) -> Self { Self { - suite: SECURE_CHANNEL_SUITE.to_string(), + suite: NOISE_CHANNEL_SUITE.to_string(), x25519_public_key: STANDARD.encode(dh.public), mlkem768_public_key: STANDARD.encode(kem.public.as_slice()), } @@ -80,7 +80,7 @@ impl SecureChannelPublicKey { fn from_raw(dh: &::PubKey, kem: &::PubKey) -> Self { Self { - suite: SECURE_CHANNEL_SUITE.to_string(), + suite: NOISE_CHANNEL_SUITE.to_string(), x25519_public_key: STANDARD.encode(dh), mlkem768_public_key: STANDARD.encode(kem.as_slice()), } @@ -88,23 +88,23 @@ impl SecureChannelPublicKey { fn decode( &self, - ) -> Result<(::PubKey, ::PubKey), SecureChannelError> { - if self.suite != SECURE_CHANNEL_SUITE { - return Err(SecureChannelError::InvalidPublicKey( - "unsupported secure channel suite", + ) -> Result<(::PubKey, ::PubKey), NoiseChannelError> { + if self.suite != NOISE_CHANNEL_SUITE { + return Err(NoiseChannelError::InvalidPublicKey( + "unsupported Noise channel suite", )); } let dh = STANDARD .decode(&self.x25519_public_key) - .map_err(|_| SecureChannelError::InvalidPublicKey("invalid X25519 public key"))?; - let dh: [u8; X25519_PUBLIC_KEY_LEN] = dh.try_into().map_err(|_| { - SecureChannelError::InvalidPublicKey("invalid X25519 public key length") - })?; + .map_err(|_| NoiseChannelError::InvalidPublicKey("invalid X25519 public key"))?; + let dh: [u8; X25519_PUBLIC_KEY_LEN] = dh + .try_into() + .map_err(|_| NoiseChannelError::InvalidPublicKey("invalid X25519 public key length"))?; let kem = STANDARD .decode(&self.mlkem768_public_key) - .map_err(|_| SecureChannelError::InvalidPublicKey("invalid ML-KEM-768 public key"))?; + .map_err(|_| NoiseChannelError::InvalidPublicKey("invalid ML-KEM-768 public key"))?; if kem.len() != MLKEM768_PUBLIC_KEY_LEN { - return Err(SecureChannelError::InvalidPublicKey( + return Err(NoiseChannelError::InvalidPublicKey( "invalid ML-KEM-768 public key length", )); } @@ -116,37 +116,37 @@ impl SecureChannelPublicKey { } } -/// Endpoint-local static identity for the exec-server secure relay Noise suite. +/// Endpoint-local static identity for the exec-server Noise-over-relay suite. /// /// Private components never cross the process boundary. Cloning is used only to /// construct Clatter handshake state for reconnects within the same process. #[derive(Clone)] -pub struct SecureChannelIdentity { +pub struct NoiseChannelIdentity { dh: DhKeyPair, kem: KemKeyPair, } -impl std::fmt::Debug for SecureChannelIdentity { +impl std::fmt::Debug for NoiseChannelIdentity { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("SecureChannelIdentity") + f.debug_struct("NoiseChannelIdentity") .field("public_key", &self.public_key()) .finish_non_exhaustive() } } -impl SecureChannelIdentity { +impl NoiseChannelIdentity { /// Generate independent classical and post-quantum static keypairs. - pub fn generate() -> Result { + pub fn generate() -> Result { let dh = X25519::genkey() - .map_err(|error| SecureChannelError::KeyGeneration(error.to_string()))?; + .map_err(|error| NoiseChannelError::KeyGeneration(error.to_string()))?; let kem = AwsLcMlKem768::genkey() - .map_err(|error| SecureChannelError::KeyGeneration(error.to_string()))?; + .map_err(|error| NoiseChannelError::KeyGeneration(error.to_string()))?; Ok(Self { dh, kem }) } /// Return the distributable public half of this endpoint identity. - pub fn public_key(&self) -> SecureChannelPublicKey { - SecureChannelPublicKey::from_keypairs(&self.dh, &self.kem) + pub fn public_key(&self) -> NoiseChannelPublicKey { + NoiseChannelPublicKey::from_keypairs(&self.dh, &self.kem) } } @@ -160,11 +160,11 @@ impl InitiatorHandshake { /// `payload` is encrypted by the first IK message. The relay uses it for /// the short-lived registry authorization naming this harness public key. pub(crate) fn start( - identity: &SecureChannelIdentity, - responder_public_key: &SecureChannelPublicKey, + identity: &NoiseChannelIdentity, + responder_public_key: &NoiseChannelPublicKey, prologue: &[u8], payload: &[u8], - ) -> Result<(Self, Vec), SecureChannelError> { + ) -> Result<(Self, Vec), NoiseChannelError> { let (responder_dh, responder_kem) = responder_public_key.decode()?; // IK authenticates both static identities. Supplying both responder @@ -186,16 +186,16 @@ impl InitiatorHandshake { /// /// The responder message carries no application payload in v1. Rejecting /// one keeps future protocol additions from becoming an implicit channel. - pub(crate) fn finish(mut self, response: &[u8]) -> Result { + pub(crate) fn finish(mut self, response: &[u8]) -> Result { ensure_noise_frame_len(response.len(), "handshake response is too large")?; let mut payload = [0u8; MAX_MESSAGE_LEN]; let payload_len = self.handshake.read_message(response, &mut payload)?; if payload_len != 0 { - return Err(SecureChannelError::InvalidMessage( + return Err(NoiseChannelError::InvalidMessage( "handshake response payload must be empty", )); } - Ok(SecureTransport { + Ok(NoiseTransport { transport: self.handshake.finalize()?, }) } @@ -203,7 +203,7 @@ impl InitiatorHandshake { pub(crate) struct PendingResponderHandshake { handshake: Handshake, - initiator_public_key: SecureChannelPublicKey, + initiator_public_key: NoiseChannelPublicKey, payload: Vec, } @@ -213,10 +213,10 @@ impl PendingResponderHandshake { /// This split is intentional: callers must authorize `initiator_public_key` /// with the registry before calling [`Self::complete`]. pub(crate) fn read_request( - identity: &SecureChannelIdentity, + identity: &NoiseChannelIdentity, prologue: &[u8], request: &[u8], - ) -> Result { + ) -> Result { ensure_noise_frame_len(request.len(), "handshake request is too large")?; let params = HybridHandshakeParams::new(noise_hybrid_ik(), false) .with_prologue(prologue) @@ -229,17 +229,17 @@ impl PendingResponderHandshake { // message authenticates and decrypts successfully. let remote = handshake .get_remote_static() - .ok_or(SecureChannelError::InvalidMessage( + .ok_or(NoiseChannelError::InvalidMessage( "handshake request is missing initiator static key", ))?; Ok(Self { handshake, - initiator_public_key: SecureChannelPublicKey::from_raw(remote.dh(), remote.kem()), + initiator_public_key: NoiseChannelPublicKey::from_raw(remote.dh(), remote.kem()), payload: payload[..payload_len].to_vec(), }) } - pub(crate) fn initiator_public_key(&self) -> &SecureChannelPublicKey { + pub(crate) fn initiator_public_key(&self) -> &NoiseChannelPublicKey { &self.initiator_public_key } @@ -248,11 +248,11 @@ impl PendingResponderHandshake { } /// Finish the responder handshake after external harness authorization. - pub(crate) fn complete(mut self) -> Result<(SecureTransport, Vec), SecureChannelError> { + pub(crate) fn complete(mut self) -> Result<(NoiseTransport, Vec), NoiseChannelError> { let mut response = [0u8; MAX_MESSAGE_LEN]; let response_len = self.handshake.write_message(&[], &mut response)?; Ok(( - SecureTransport { + NoiseTransport { transport: self.handshake.finalize()?, }, response[..response_len].to_vec(), @@ -260,23 +260,23 @@ impl PendingResponderHandshake { } } -pub(crate) struct SecureTransport { +pub(crate) struct NoiseTransport { transport: Transport, } -impl SecureTransport { +impl NoiseTransport { /// Encrypt exactly one ordered transport record. /// /// The caller owns relay sequence assignment and must never encrypt the /// same logical record twice under different transport nonces. - pub(crate) fn encrypt(&mut self, plaintext: &[u8]) -> Result, SecureChannelError> { + pub(crate) fn encrypt(&mut self, plaintext: &[u8]) -> Result, NoiseChannelError> { if self.transport.sending_nonce() >= MAX_TRANSPORT_RECORDS_PER_DIRECTION { - return Err(SecureChannelError::InvalidState( + return Err(NoiseChannelError::InvalidState( "transport record nonce exhausted", )); } let frame_len = plaintext.len().checked_add(AesGcm::tag_len()).ok_or( - SecureChannelError::InvalidMessage("transport plaintext is too large"), + NoiseChannelError::InvalidMessage("transport plaintext is too large"), )?; ensure_noise_frame_len(frame_len, "transport plaintext is too large")?; Ok(self.transport.send_vec(plaintext)?) @@ -286,14 +286,14 @@ impl SecureTransport { /// /// Clatter advances the receiving nonce during this call, so callers must /// reorder and deduplicate relay frames before invoking it. - pub(crate) fn decrypt(&mut self, ciphertext: &[u8]) -> Result, SecureChannelError> { + pub(crate) fn decrypt(&mut self, ciphertext: &[u8]) -> Result, NoiseChannelError> { if self.transport.receiving_nonce() >= MAX_TRANSPORT_RECORDS_PER_DIRECTION { - return Err(SecureChannelError::InvalidState( + return Err(NoiseChannelError::InvalidState( "transport record nonce exhausted", )); } if ciphertext.len() < AesGcm::tag_len() { - return Err(SecureChannelError::InvalidMessage( + return Err(NoiseChannelError::InvalidMessage( "transport ciphertext is too short", )); } @@ -307,11 +307,11 @@ impl SecureTransport { /// A handshake captured from one environment, exec-server registration, or /// relay stream cannot be replayed into another because every participant must /// construct the same prologue before the first Noise message is processed. -pub(crate) fn secure_channel_prologue( +pub(crate) fn noise_channel_prologue( environment_id: &str, executor_registration_id: &str, stream_id: &str, -) -> Result, SecureChannelError> { +) -> Result, NoiseChannelError> { let mut prologue = Vec::new(); append_prologue_part(&mut prologue, PROLOGUE_DOMAIN)?; append_prologue_part(&mut prologue, environment_id.as_bytes())?; @@ -320,11 +320,11 @@ pub(crate) fn secure_channel_prologue( Ok(prologue) } -fn append_prologue_part(prologue: &mut Vec, part: &[u8]) -> Result<(), SecureChannelError> { +fn append_prologue_part(prologue: &mut Vec, part: &[u8]) -> Result<(), NoiseChannelError> { // Length prefixes make component boundaries unambiguous. Raw concatenation // would allow different identifier tuples to produce the same prologue. let len = u32::try_from(part.len()).map_err(|_| { - SecureChannelError::InvalidMessage("secure channel prologue part is too large") + NoiseChannelError::InvalidMessage("Noise channel prologue part is too large") })?; prologue.extend_from_slice(&len.to_be_bytes()); prologue.extend_from_slice(part); @@ -334,41 +334,41 @@ fn append_prologue_part(prologue: &mut Vec, part: &[u8]) -> Result<(), Secur fn ensure_noise_frame_len( frame_len: usize, message: &'static str, -) -> Result<(), SecureChannelError> { +) -> Result<(), NoiseChannelError> { if frame_len > MAX_MESSAGE_LEN { - return Err(SecureChannelError::InvalidMessage(message)); + return Err(NoiseChannelError::InvalidMessage(message)); } Ok(()) } #[derive(Debug, thiserror::Error)] -pub enum SecureChannelError { - #[error("secure channel key generation failed: {0}")] +pub enum NoiseChannelError { + #[error("Noise channel key generation failed: {0}")] KeyGeneration(String), - #[error("invalid secure channel public key: {0}")] + #[error("invalid Noise channel public key: {0}")] InvalidPublicKey(&'static str), - #[error("invalid secure channel state: {0}")] + #[error("invalid Noise channel state: {0}")] InvalidState(&'static str), - #[error("invalid secure channel message: {0}")] + #[error("invalid Noise channel message: {0}")] InvalidMessage(&'static str), - #[error("secure channel handshake failed: {0}")] + #[error("Noise channel handshake failed: {0}")] Handshake(String), - #[error("secure channel transport failed: {0}")] + #[error("Noise channel transport failed: {0}")] Transport(String), } -impl From for SecureChannelError { +impl From for NoiseChannelError { fn from(error: clatter::error::HandshakeError) -> Self { Self::Handshake(error.to_string()) } } -impl From for SecureChannelError { +impl From for NoiseChannelError { fn from(error: clatter::error::TransportError) -> Self { Self::Transport(error.to_string()) } } #[cfg(test)] -#[path = "secure_channel_tests.rs"] +#[path = "noise_channel_tests.rs"] mod tests; diff --git a/codex-rs/exec-server/src/secure_channel_tests.rs b/codex-rs/exec-server/src/noise_channel_tests.rs similarity index 73% rename from codex-rs/exec-server/src/secure_channel_tests.rs rename to codex-rs/exec-server/src/noise_channel_tests.rs index ff6d64753b..e404dc1232 100644 --- a/codex-rs/exec-server/src/secure_channel_tests.rs +++ b/codex-rs/exec-server/src/noise_channel_tests.rs @@ -2,19 +2,19 @@ use pretty_assertions::assert_eq; use super::InitiatorHandshake; use super::MAX_TRANSPORT_RECORDS_PER_DIRECTION; +use super::NOISE_CHANNEL_SUITE; +use super::NoiseChannelError; +use super::NoiseChannelIdentity; +use super::NoiseChannelPublicKey; use super::PendingResponderHandshake; -use super::SECURE_CHANNEL_SUITE; -use super::SecureChannelError; -use super::SecureChannelIdentity; -use super::SecureChannelPublicKey; -use super::secure_channel_prologue; +use super::noise_channel_prologue; #[test] fn hybrid_ik_roundtrip_authenticates_both_endpoints() { - let initiator = SecureChannelIdentity::generate().expect("generate initiator identity"); - let responder = SecureChannelIdentity::generate().expect("generate responder identity"); + let initiator = NoiseChannelIdentity::generate().expect("generate initiator identity"); + let responder = NoiseChannelIdentity::generate().expect("generate responder identity"); let prologue = - secure_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); + noise_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); let authorization = b"harness-key-authorization"; let (initiator_handshake, request) = InitiatorHandshake::start( @@ -66,11 +66,11 @@ fn hybrid_ik_roundtrip_authenticates_both_endpoints() { #[test] fn initiator_rejects_wrong_responder_key() { - let initiator = SecureChannelIdentity::generate().expect("generate initiator identity"); - let expected_responder = SecureChannelIdentity::generate().expect("generate expected identity"); - let actual_responder = SecureChannelIdentity::generate().expect("generate actual identity"); + let initiator = NoiseChannelIdentity::generate().expect("generate initiator identity"); + let expected_responder = NoiseChannelIdentity::generate().expect("generate expected identity"); + let actual_responder = NoiseChannelIdentity::generate().expect("generate actual identity"); let prologue = - secure_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); + noise_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); let (_initiator_handshake, request) = InitiatorHandshake::start( &initiator, @@ -87,12 +87,12 @@ fn initiator_rejects_wrong_responder_key() { #[test] fn responder_rejects_mismatched_prologue() { - let initiator = SecureChannelIdentity::generate().expect("generate initiator identity"); - let responder = SecureChannelIdentity::generate().expect("generate responder identity"); + let initiator = NoiseChannelIdentity::generate().expect("generate initiator identity"); + let responder = NoiseChannelIdentity::generate().expect("generate responder identity"); let initiator_prologue = - secure_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); + noise_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); let responder_prologue = - secure_channel_prologue("env-1", "registration-1", "stream-2").expect("build prologue"); + noise_channel_prologue("env-1", "registration-1", "stream-2").expect("build prologue"); let (_initiator_handshake, request) = InitiatorHandshake::start( &initiator, &responder.public_key(), @@ -109,7 +109,7 @@ fn responder_rejects_mismatched_prologue() { #[test] fn prologue_encoding_is_stable_and_unambiguous() { let prologue = - secure_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); + noise_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); assert_eq!( prologue, @@ -123,10 +123,10 @@ fn prologue_encoding_is_stable_and_unambiguous() { #[test] fn transport_rejects_tampered_ciphertext() { - let initiator = SecureChannelIdentity::generate().expect("generate initiator identity"); - let responder = SecureChannelIdentity::generate().expect("generate responder identity"); + let initiator = NoiseChannelIdentity::generate().expect("generate initiator identity"); + let responder = NoiseChannelIdentity::generate().expect("generate responder identity"); let prologue = - secure_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); + noise_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); let (initiator_handshake, request) = InitiatorHandshake::start( &initiator, &responder.public_key(), @@ -153,10 +153,10 @@ fn transport_rejects_tampered_ciphertext() { #[test] fn transport_rejects_exhausted_receiving_nonce_before_decryption() { - let initiator = SecureChannelIdentity::generate().expect("generate initiator identity"); - let responder = SecureChannelIdentity::generate().expect("generate responder identity"); + let initiator = NoiseChannelIdentity::generate().expect("generate initiator identity"); + let responder = NoiseChannelIdentity::generate().expect("generate responder identity"); let prologue = - secure_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); + noise_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); let (initiator_handshake, request) = InitiatorHandshake::start( &initiator, &responder.public_key(), @@ -182,7 +182,7 @@ fn transport_rejects_exhausted_receiving_nonce_before_decryption() { assert!(matches!( responder_transport.decrypt(&ciphertext), - Err(SecureChannelError::InvalidState( + Err(NoiseChannelError::InvalidState( "transport record nonce exhausted" )) )); @@ -190,10 +190,10 @@ fn transport_rejects_exhausted_receiving_nonce_before_decryption() { #[test] fn transport_rejects_replayed_ciphertext() { - let initiator = SecureChannelIdentity::generate().expect("generate initiator identity"); - let responder = SecureChannelIdentity::generate().expect("generate responder identity"); + let initiator = NoiseChannelIdentity::generate().expect("generate initiator identity"); + let responder = NoiseChannelIdentity::generate().expect("generate responder identity"); let prologue = - secure_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); + noise_channel_prologue("env-1", "registration-1", "stream-1").expect("build prologue"); let (initiator_handshake, request) = InitiatorHandshake::start( &initiator, &responder.public_key(), @@ -222,19 +222,19 @@ fn transport_rejects_replayed_ciphertext() { ); assert!(matches!( responder_transport.decrypt(&ciphertext), - Err(SecureChannelError::Transport(_)) + Err(NoiseChannelError::Transport(_)) )); } #[test] fn public_key_validation_rejects_unknown_suite() { - let key = SecureChannelIdentity::generate() + let key = NoiseChannelIdentity::generate() .expect("generate identity") .public_key(); let json = serde_json::to_value(key).expect("serialize key"); let mut object = json.as_object().expect("key object").clone(); object.insert("suite".to_string(), serde_json::json!("unknown")); - let key: SecureChannelPublicKey = + let key: NoiseChannelPublicKey = serde_json::from_value(serde_json::Value::Object(object)).expect("deserialize key"); assert!(key.validate().is_err()); @@ -242,11 +242,11 @@ fn public_key_validation_rejects_unknown_suite() { #[test] fn public_key_serializes_with_expected_suite() { - let key = SecureChannelIdentity::generate() + let key = NoiseChannelIdentity::generate() .expect("generate identity") .public_key(); let json = serde_json::to_value(key).expect("serialize key"); - assert_eq!(json["suite"], SECURE_CHANNEL_SUITE); + assert_eq!(json["suite"], NOISE_CHANNEL_SUITE); } diff --git a/codex-rs/exec-server/src/secure_relay/environment.rs b/codex-rs/exec-server/src/noise_relay/environment.rs similarity index 83% rename from codex-rs/exec-server/src/secure_relay/environment.rs rename to codex-rs/exec-server/src/noise_relay/environment.rs index ce8d37edff..2143f5f35a 100644 --- a/codex-rs/exec-server/src/secure_relay/environment.rs +++ b/codex-rs/exec-server/src/noise_relay/environment.rs @@ -21,25 +21,27 @@ use crate::connection::CHANNEL_CAPACITY; use crate::connection::JsonRpcConnection; use crate::connection::JsonRpcConnectionEvent; use crate::connection::JsonRpcTransport; +use crate::noise_channel::NoiseChannelIdentity; +use crate::noise_channel::NoiseChannelPublicKey; +use crate::noise_channel::NoiseTransport; +use crate::noise_channel::PendingResponderHandshake; +use crate::noise_channel::noise_channel_prologue; +use crate::noise_relay::message_framing::JsonRpcMessageDecoder; +use crate::noise_relay::message_framing::NOISE_RECORD_PLAINTEXT_LEN; +use crate::noise_relay::message_framing::frame_jsonrpc_message; +use crate::noise_relay::ordered_ciphertext::OrderedCiphertextFrames; +use crate::noise_relay::take_next_sequence; use crate::relay::RelayFrameBodyKind; use crate::relay::decode_relay_message_frame; use crate::relay::encode_relay_message_frame; use crate::relay_proto::RelayData; use crate::relay_proto::RelayMessageFrame; -use crate::secure_channel::PendingResponderHandshake; -use crate::secure_channel::SecureChannelIdentity; -use crate::secure_channel::SecureChannelPublicKey; -use crate::secure_channel::SecureTransport; -use crate::secure_channel::secure_channel_prologue; -use crate::secure_relay::message_framing::JsonRpcMessageDecoder; -use crate::secure_relay::message_framing::SECURE_RECORD_PLAINTEXT_LEN; -use crate::secure_relay::message_framing::frame_jsonrpc_message; -use crate::secure_relay::ordered_ciphertext::OrderedCiphertextFrames; -use crate::secure_relay::take_next_sequence; use crate::server::ConnectionProcessor; -const SECURE_RELAY_RESET_REASON: &str = "secure_relay_protocol_error"; -const MAX_ACTIVE_SECURE_RELAY_STREAMS: usize = 128; +// This value is already part of the relay wire contract. Keep it stable even +// though the source module now uses the more precise Noise terminology. +const NOISE_RELAY_RESET_REASON: &str = "secure_relay_protocol_error"; +const MAX_ACTIVE_NOISE_RELAY_STREAMS: usize = 128; const MAX_PENDING_HANDSHAKE_VALIDATIONS: usize = 32; const HARNESS_KEY_VALIDATION_TIMEOUT: Duration = Duration::from_secs(10); @@ -51,7 +53,7 @@ const HARNESS_KEY_VALIDATION_TIMEOUT: Duration = Duration::from_secs(10); pub(crate) trait HarnessKeyValidator: Send + Sync { fn validate_harness_key( &self, - harness_public_key: &SecureChannelPublicKey, + harness_public_key: &NoiseChannelPublicKey, authorization: &str, ) -> impl std::future::Future> + Send; } @@ -62,12 +64,12 @@ pub(crate) trait HarnessKeyValidator: Send + Sync { /// outer websocket and rendezvous route are treated as untrusted delivery: /// malformed, unauthorized, or cryptographically invalid streams fail closed /// without creating a `JsonRpcConnection`. -pub(crate) async fn run_secure_multiplexed_environment( +pub(crate) async fn run_noise_multiplexed_environment( stream: WebSocketStream, processor: ConnectionProcessor, environment_id: String, executor_registration_id: String, - identity: SecureChannelIdentity, + identity: NoiseChannelIdentity, validator: V, ) where S: AsyncRead + AsyncWrite + Unpin + Send + 'static, @@ -76,7 +78,7 @@ pub(crate) async fn run_secure_multiplexed_environment( let mut websocket = stream; let (physical_outgoing_tx, mut physical_outgoing_rx) = mpsc::channel::>(CHANNEL_CAPACITY); - let mut streams: HashMap = HashMap::new(); + let mut streams: HashMap = HashMap::new(); let mut pending_handshakes: HashMap = HashMap::new(); let mut validation_tasks: JoinSet = JoinSet::new(); let mut next_validation_id = 0u64; @@ -115,12 +117,12 @@ pub(crate) async fn run_secure_multiplexed_environment( continue; }; if let Err(error) = validation_result.result { - warn!("secure relay harness key validation failed: {error}"); + warn!("Noise relay harness key validation failed: {error}"); send_reset(&physical_outgoing_tx, validation_result.stream_id).await; continue; } - if streams.len() >= MAX_ACTIVE_SECURE_RELAY_STREAMS { - warn!("secure relay has too many active streams"); + if streams.len() >= MAX_ACTIVE_NOISE_RELAY_STREAMS { + warn!("Noise relay has too many active streams"); send_reset(&physical_outgoing_tx, validation_result.stream_id).await; continue; } @@ -131,7 +133,7 @@ pub(crate) async fn run_secure_multiplexed_environment( let (transport, response) = match pending.handshake.complete() { Ok(completed) => completed, Err(error) => { - warn!("failed to complete secure relay handshake: {error}"); + warn!("failed to complete Noise relay handshake: {error}"); send_reset(&physical_outgoing_tx, validation_result.stream_id).await; continue; } @@ -149,7 +151,7 @@ pub(crate) async fn run_secure_multiplexed_environment( } streams.insert( validation_result.stream_id.clone(), - spawn_secure_virtual_stream( + spawn_noise_virtual_stream( validation_result.stream_id, processor.clone(), physical_outgoing_tx.clone(), @@ -158,7 +160,7 @@ pub(crate) async fn run_secure_multiplexed_environment( ); } Some(Err(error)) => { - warn!("secure relay harness key validation task failed: {error}"); + warn!("Noise relay harness key validation task failed: {error}"); let stream_ids = pending_handshakes.keys().cloned().collect::>(); pending_handshakes.clear(); for stream_id in stream_ids { @@ -173,18 +175,18 @@ pub(crate) async fn run_secure_multiplexed_environment( Some(Ok(Message::Binary(payload))) => match decode_relay_message_frame(payload.as_ref()) { Ok(frame) => frame, Err(error) => { - warn!("dropping malformed secure relay frame from harness: {error}"); + warn!("dropping malformed Noise relay frame from harness: {error}"); continue; } }, Some(Ok(Message::Close(_))) | None => break, Some(Ok(Message::Ping(_) | Message::Pong(_) | Message::Frame(_))) => continue, Some(Ok(Message::Text(_))) => { - warn!("dropping non-binary secure relay frame from harness"); + warn!("dropping non-binary Noise relay frame from harness"); continue; } Some(Err(error)) => { - debug!("secure multiplexed environment websocket read failed: {error}"); + debug!("Noise multiplexed environment websocket read failed: {error}"); break; } } @@ -193,7 +195,7 @@ pub(crate) async fn run_secure_multiplexed_environment( let kind = match frame.validate() { Ok(kind) => kind, Err(error) => { - warn!("dropping invalid secure relay frame: {error}"); + warn!("dropping invalid Noise relay frame: {error}"); continue; } }; @@ -206,24 +208,24 @@ pub(crate) async fn run_secure_multiplexed_environment( send_reset(&physical_outgoing_tx, stream_id).await; continue; } - if streams.len() >= MAX_ACTIVE_SECURE_RELAY_STREAMS { - warn!("secure relay has too many active streams"); + if streams.len() >= MAX_ACTIVE_NOISE_RELAY_STREAMS { + warn!("Noise relay has too many active streams"); send_reset(&physical_outgoing_tx, stream_id).await; continue; } if validation_tasks.len() >= MAX_PENDING_HANDSHAKE_VALIDATIONS { - warn!("secure relay has too many pending harness key validations"); + warn!("Noise relay has too many pending harness key validations"); send_reset(&physical_outgoing_tx, stream_id).await; continue; } - let prologue = match secure_channel_prologue( + let prologue = match noise_channel_prologue( &environment_id, &executor_registration_id, &stream_id, ) { Ok(prologue) => prologue, Err(error) => { - warn!("failed to build secure relay prologue: {error}"); + warn!("failed to build Noise relay prologue: {error}"); send_reset(&physical_outgoing_tx, stream_id).await; continue; } @@ -231,7 +233,7 @@ pub(crate) async fn run_secure_multiplexed_environment( let request = match frame.into_handshake_payload() { Ok(request) => request, Err(error) => { - warn!("failed to read secure relay handshake frame: {error}"); + warn!("failed to read Noise relay handshake frame: {error}"); send_reset(&physical_outgoing_tx, stream_id).await; continue; } @@ -240,7 +242,7 @@ pub(crate) async fn run_secure_multiplexed_environment( match PendingResponderHandshake::read_request(&identity, &prologue, &request) { Ok(pending) => pending, Err(error) => { - warn!("failed to read secure relay handshake request: {error}"); + warn!("failed to read Noise relay handshake request: {error}"); send_reset(&physical_outgoing_tx, stream_id).await; continue; } @@ -252,7 +254,7 @@ pub(crate) async fn run_secure_multiplexed_environment( let authorization = match std::str::from_utf8(pending.payload()) { Ok(authorization) => authorization.to_string(), Err(_) => { - warn!("secure relay handshake authorization is not UTF-8"); + warn!("Noise relay handshake authorization is not UTF-8"); send_reset(&physical_outgoing_tx, stream_id).await; continue; } @@ -260,7 +262,7 @@ pub(crate) async fn run_secure_multiplexed_environment( let harness_public_key = pending.initiator_public_key().clone(); let validation_id = next_validation_id; let Some(next_id) = next_validation_id.checked_add(1) else { - warn!("secure relay harness key validation id exhausted"); + warn!("Noise relay harness key validation id exhausted"); send_reset(&physical_outgoing_tx, stream_id).await; continue; }; @@ -286,7 +288,7 @@ pub(crate) async fn run_secure_multiplexed_environment( { Ok(result) => result, Err(_) => Err(ExecServerError::Protocol( - "timed out validating secure relay harness key".to_string(), + "timed out validating Noise relay harness key".to_string(), )), }; HarnessKeyValidationResult { @@ -308,14 +310,14 @@ pub(crate) async fn run_secure_multiplexed_environment( let data = match frame.into_data() { Ok(data) => data, Err(error) => { - warn!("dropping malformed secure relay data frame: {error}"); + warn!("dropping malformed Noise relay data frame: {error}"); streams.remove(&stream_id); send_reset(&physical_outgoing_tx, stream_id).await; continue; } }; if let Err(error) = stream.receive_data(data).await { - warn!("failed to process secure relay payload: {error}"); + warn!("failed to process Noise relay payload: {error}"); streams.remove(&stream_id); send_reset(&physical_outgoing_tx, stream_id).await; } @@ -348,15 +350,15 @@ struct HarnessKeyValidationResult { result: Result<(), ExecServerError>, } -struct SecureVirtualStream { +struct NoiseVirtualStream { incoming_tx: mpsc::Sender, disconnected_tx: watch::Sender, - transport: Arc>, + transport: Arc>, inbound_ciphertexts: OrderedCiphertextFrames, inbound_decoder: JsonRpcMessageDecoder, } -impl SecureVirtualStream { +impl NoiseVirtualStream { async fn disconnect(self, reason: Option) { let _ = self.disconnected_tx.send(true); let _ = self @@ -388,12 +390,12 @@ impl SecureVirtualStream { } } -fn spawn_secure_virtual_stream( +fn spawn_noise_virtual_stream( stream_id: String, processor: ConnectionProcessor, physical_outgoing_tx: mpsc::Sender>, - transport: SecureTransport, -) -> SecureVirtualStream { + transport: NoiseTransport, +) -> NoiseVirtualStream { let (json_outgoing_tx, mut json_outgoing_rx) = mpsc::channel(CHANNEL_CAPACITY); let (incoming_tx, incoming_rx) = mpsc::channel(CHANNEL_CAPACITY); let (disconnected_tx, disconnected_rx) = watch::channel(false); @@ -409,15 +411,15 @@ fn spawn_secure_virtual_stream( let framed = match frame_jsonrpc_message(&message) { Ok(framed) => framed, Err(error) => { - warn!("failed to frame secure virtual stream JSON-RPC payload: {error}"); + warn!("failed to frame Noise virtual stream JSON-RPC payload: {error}"); break; } }; - for plaintext_record in framed.chunks(SECURE_RECORD_PLAINTEXT_LEN) { + for plaintext_record in framed.chunks(NOISE_RECORD_PLAINTEXT_LEN) { let seq = match take_next_sequence(&mut next_seq) { Ok(seq) => seq, Err(error) => { - warn!("secure virtual stream sequence exhausted: {error}"); + warn!("Noise virtual stream sequence exhausted: {error}"); break 'writer; } }; @@ -430,7 +432,7 @@ fn spawn_secure_virtual_stream( let ciphertext = match ciphertext { Ok(ciphertext) => ciphertext, Err(error) => { - warn!("failed to encrypt secure virtual stream payload: {error}"); + warn!("failed to encrypt Noise virtual stream payload: {error}"); break 'writer; } }; @@ -449,7 +451,7 @@ fn spawn_secure_virtual_stream( // exits, including processor shutdown or a cryptographic/send failure. // Otherwise the peer could wait indefinitely on a dead stream. let reset = - RelayMessageFrame::reset(writer_stream_id, SECURE_RELAY_RESET_REASON.to_string()); + RelayMessageFrame::reset(writer_stream_id, NOISE_RELAY_RESET_REASON.to_string()); let _ = physical_outgoing_tx .send(encode_relay_message_frame(&reset)) .await; @@ -466,7 +468,7 @@ fn spawn_secure_virtual_stream( processor.run_connection(connection).await; }); - SecureVirtualStream { + NoiseVirtualStream { incoming_tx, disconnected_tx, transport, @@ -476,7 +478,7 @@ fn spawn_secure_virtual_stream( } async fn send_reset(physical_outgoing_tx: &mpsc::Sender>, stream_id: String) { - let reset = RelayMessageFrame::reset(stream_id, SECURE_RELAY_RESET_REASON.to_string()); + let reset = RelayMessageFrame::reset(stream_id, NOISE_RELAY_RESET_REASON.to_string()); let _ = physical_outgoing_tx .send(encode_relay_message_frame(&reset)) .await; diff --git a/codex-rs/exec-server/src/secure_relay/environment_tests.rs b/codex-rs/exec-server/src/noise_relay/environment_tests.rs similarity index 82% rename from codex-rs/exec-server/src/secure_relay/environment_tests.rs rename to codex-rs/exec-server/src/noise_relay/environment_tests.rs index 7678fd5e22..a1910efcd9 100644 --- a/codex-rs/exec-server/src/secure_relay/environment_tests.rs +++ b/codex-rs/exec-server/src/noise_relay/environment_tests.rs @@ -13,15 +13,15 @@ use tokio_tungstenite::connect_async; use tokio_tungstenite::tungstenite::Message; use super::HarnessKeyValidator; -use super::run_secure_multiplexed_environment; +use super::run_noise_multiplexed_environment; use crate::ExecServerError; use crate::ExecServerRuntimePaths; +use crate::noise_channel::InitiatorHandshake; +use crate::noise_channel::NoiseChannelIdentity; +use crate::noise_channel::NoiseChannelPublicKey; +use crate::noise_channel::noise_channel_prologue; use crate::relay::encode_relay_message_frame; use crate::relay_proto::RelayMessageFrame; -use crate::secure_channel::InitiatorHandshake; -use crate::secure_channel::SecureChannelIdentity; -use crate::secure_channel::SecureChannelPublicKey; -use crate::secure_channel::secure_channel_prologue; use crate::server::ConnectionProcessor; const ENVIRONMENT_ID: &str = "environment-1"; @@ -36,7 +36,7 @@ struct BlockingValidator { impl HarnessKeyValidator for BlockingValidator { fn validate_harness_key( &self, - _harness_public_key: &SecureChannelPublicKey, + _harness_public_key: &NoiseChannelPublicKey, _authorization: &str, ) -> impl std::future::Future> + Send { let calls = Arc::clone(&self.calls); @@ -58,10 +58,10 @@ async fn pending_harness_key_validation_does_not_block_new_handshakes() -> Resul let environment_websocket = accept_async(socket).await?; let (mut harness_websocket, _response) = harness_connection.await??; - let environment_identity = SecureChannelIdentity::generate()?; - let harness_identity = SecureChannelIdentity::generate()?; + let environment_identity = NoiseChannelIdentity::generate()?; + let harness_identity = NoiseChannelIdentity::generate()?; let calls = Arc::new(AtomicUsize::new(0)); - let environment_task = tokio::spawn(run_secure_multiplexed_environment( + let environment_task = tokio::spawn(run_noise_multiplexed_environment( environment_websocket, ConnectionProcessor::new(ExecServerRuntimePaths::new( std::env::current_exe()?, @@ -77,8 +77,7 @@ async fn pending_harness_key_validation_does_not_block_new_handshakes() -> Resul )); for stream_id in ["stream-1", "stream-2"] { - let prologue = - secure_channel_prologue(ENVIRONMENT_ID, EXECUTOR_REGISTRATION_ID, stream_id)?; + let prologue = noise_channel_prologue(ENVIRONMENT_ID, EXECUTOR_REGISTRATION_ID, stream_id)?; let (_handshake, request) = InitiatorHandshake::start( &harness_identity, &environment_identity.public_key(), diff --git a/codex-rs/exec-server/src/secure_relay/harness.rs b/codex-rs/exec-server/src/noise_relay/harness.rs similarity index 86% rename from codex-rs/exec-server/src/secure_relay/harness.rs rename to codex-rs/exec-server/src/noise_relay/harness.rs index 8c694050cd..3c30a0cabb 100644 --- a/codex-rs/exec-server/src/secure_relay/harness.rs +++ b/codex-rs/exec-server/src/noise_relay/harness.rs @@ -14,21 +14,21 @@ use crate::connection::CHANNEL_CAPACITY; use crate::connection::JsonRpcConnection; use crate::connection::JsonRpcConnectionEvent; use crate::connection::JsonRpcTransport; +use crate::noise_channel::InitiatorHandshake; +use crate::noise_channel::NoiseChannelIdentity; +use crate::noise_channel::NoiseChannelPublicKey; +use crate::noise_channel::NoiseTransport; +use crate::noise_channel::noise_channel_prologue; +use crate::noise_relay::message_framing::JsonRpcMessageDecoder; +use crate::noise_relay::message_framing::NOISE_RECORD_PLAINTEXT_LEN; +use crate::noise_relay::message_framing::frame_jsonrpc_message; +use crate::noise_relay::ordered_ciphertext::OrderedCiphertextFrames; +use crate::noise_relay::take_next_sequence; use crate::relay::RelayFrameBodyKind; use crate::relay::decode_relay_message_frame; use crate::relay::encode_relay_message_frame; use crate::relay_proto::RelayData; use crate::relay_proto::RelayMessageFrame; -use crate::secure_channel::InitiatorHandshake; -use crate::secure_channel::SecureChannelIdentity; -use crate::secure_channel::SecureChannelPublicKey; -use crate::secure_channel::SecureTransport; -use crate::secure_channel::secure_channel_prologue; -use crate::secure_relay::message_framing::JsonRpcMessageDecoder; -use crate::secure_relay::message_framing::SECURE_RECORD_PLAINTEXT_LEN; -use crate::secure_relay::message_framing::frame_jsonrpc_message; -use crate::secure_relay::ordered_ciphertext::OrderedCiphertextFrames; -use crate::secure_relay::take_next_sequence; /// Adapt one harness rendezvous websocket into an authenticated JSON-RPC connection. /// @@ -36,13 +36,13 @@ use crate::secure_relay::take_next_sequence; /// hybrid IK against the registry-pinned exec-server key. Rendezvous can see /// stream metadata and ciphertext, but never JSON-RPC plaintext or either /// endpoint's private key. -pub(crate) fn secure_harness_connection_from_websocket( +pub(crate) fn noise_harness_connection_from_websocket( stream: T, connection_label: String, environment_id: String, executor_registration_id: String, - identity: SecureChannelIdentity, - responder_public_key: SecureChannelPublicKey, + identity: NoiseChannelIdentity, + responder_public_key: NoiseChannelPublicKey, harness_key_authorization: String, ) -> JsonRpcConnection where @@ -61,13 +61,13 @@ where // virtual relay stream before emitting any handshake bytes. A captured // handshake cannot be spliced onto a different routed connection. let prologue = - match secure_channel_prologue(&environment_id, &executor_registration_id, &stream_id) { + match noise_channel_prologue(&environment_id, &executor_registration_id, &stream_id) { Ok(prologue) => prologue, Err(error) => { send_disconnected( &incoming_tx, &disconnected_tx, - format!("failed to build secure relay prologue: {error}"), + format!("failed to build Noise relay prologue: {error}"), ) .await; return; @@ -84,7 +84,7 @@ where send_disconnected( &incoming_tx, &disconnected_tx, - format!("failed to start secure relay handshake: {error}"), + format!("failed to start Noise relay handshake: {error}"), ) .await; return; @@ -119,7 +119,7 @@ where send_disconnected( &incoming_tx, &disconnected_tx, - "secure relay websocket closed during handshake".to_string(), + "Noise relay websocket closed during handshake".to_string(), ) .await; return; @@ -130,7 +130,7 @@ where send_disconnected( &incoming_tx, &disconnected_tx, - "secure relay websocket closed during handshake".to_string(), + "Noise relay websocket closed during handshake".to_string(), ) .await; return; @@ -140,7 +140,7 @@ where send_disconnected( &incoming_tx, &disconnected_tx, - "secure relay transport expects binary protobuf frames".to_string(), + "Noise relay transport expects binary protobuf frames".to_string(), ) .await; return; @@ -150,7 +150,7 @@ where &incoming_tx, &disconnected_tx, format!( - "failed to read secure relay websocket from {connection_label}: {error}" + "failed to read Noise relay websocket from {connection_label}: {error}" ), ) .await; @@ -163,7 +163,7 @@ where send_disconnected( &incoming_tx, &disconnected_tx, - format!("failed to parse secure relay frame: {error}"), + format!("failed to parse Noise relay frame: {error}"), ) .await; return; @@ -188,7 +188,7 @@ where send_disconnected( &incoming_tx, &disconnected_tx, - format!("secure relay handshake failed: {error}"), + format!("Noise relay handshake failed: {error}"), ) .await; return; @@ -201,7 +201,7 @@ where &disconnected_tx, frame .into_reset_reason() - .unwrap_or_else(|| "secure relay reset during handshake".to_string()), + .unwrap_or_else(|| "Noise relay reset during handshake".to_string()), ) .await; return; @@ -215,7 +215,7 @@ where send_disconnected( &incoming_tx, &disconnected_tx, - "secure relay received data before handshake completion".to_string(), + "Noise relay received data before handshake completion".to_string(), ) .await; return; @@ -238,22 +238,22 @@ where let framed = match frame_jsonrpc_message(&message) { Ok(framed) => framed, Err(error) => { - warn!("failed to frame JSON-RPC payload for secure relay: {error}"); + warn!("failed to frame JSON-RPC payload for Noise relay: {error}"); break; } }; - for plaintext_record in framed.chunks(SECURE_RECORD_PLAINTEXT_LEN) { + for plaintext_record in framed.chunks(NOISE_RECORD_PLAINTEXT_LEN) { let seq = match take_next_sequence(&mut next_outbound_seq) { Ok(seq) => seq, Err(error) => { - warn!("secure relay sequence exhausted: {error}"); + warn!("Noise relay sequence exhausted: {error}"); break 'relay; } }; let ciphertext = match transport.encrypt(plaintext_record) { Ok(ciphertext) => ciphertext, Err(error) => { - warn!("failed to encrypt JSON-RPC payload for secure relay: {error}"); + warn!("failed to encrypt JSON-RPC payload for Noise relay: {error}"); break 'relay; } }; @@ -320,7 +320,7 @@ where Ok(RelayFrameBodyKind::Handshake) | Err(_) => { send_malformed( &incoming_tx, - "secure relay received invalid post-handshake frame".to_string(), + "Noise relay received invalid post-handshake frame".to_string(), ) .await; break; @@ -332,13 +332,13 @@ where Ok(Message::Text(_)) => { send_malformed( &incoming_tx, - "secure relay transport expects binary protobuf frames".to_string(), + "Noise relay transport expects binary protobuf frames".to_string(), ) .await; break; } Err(error) => { - debug!("secure relay websocket read failed: {error}"); + debug!("Noise relay websocket read failed: {error}"); break; } } @@ -359,7 +359,7 @@ where async fn receive_data( inbound_ciphertexts: &mut OrderedCiphertextFrames, - transport: &mut SecureTransport, + transport: &mut NoiseTransport, decoder: &mut JsonRpcMessageDecoder, data: RelayData, incoming_tx: &mpsc::Sender, diff --git a/codex-rs/exec-server/src/secure_relay/message_framing.rs b/codex-rs/exec-server/src/noise_relay/message_framing.rs similarity index 79% rename from codex-rs/exec-server/src/secure_relay/message_framing.rs rename to codex-rs/exec-server/src/noise_relay/message_framing.rs index 98e9b86596..0b69f46b48 100644 --- a/codex-rs/exec-server/src/secure_relay/message_framing.rs +++ b/codex-rs/exec-server/src/noise_relay/message_framing.rs @@ -3,8 +3,8 @@ use codex_app_server_protocol::JSONRPCMessage; use crate::ExecServerError; const LENGTH_PREFIX_BYTES: usize = size_of::(); -const MAX_SECURE_JSONRPC_MESSAGE_LEN: usize = 64 * 1024 * 1024; -pub(crate) const SECURE_RECORD_PLAINTEXT_LEN: usize = 60 * 1024; +const MAX_NOISE_JSONRPC_MESSAGE_LEN: usize = 64 * 1024 * 1024; +pub(crate) const NOISE_RECORD_PLAINTEXT_LEN: usize = 60 * 1024; /// Serialize one JSON-RPC message into the encrypted record byte stream. /// @@ -16,9 +16,9 @@ pub(crate) fn frame_jsonrpc_message(message: &JSONRPCMessage) -> Result, let mut framed = vec![0; LENGTH_PREFIX_BYTES]; serde_json::to_writer(&mut framed, message)?; let message_len = framed.len() - LENGTH_PREFIX_BYTES; - if message_len > MAX_SECURE_JSONRPC_MESSAGE_LEN { + if message_len > MAX_NOISE_JSONRPC_MESSAGE_LEN { return Err(ExecServerError::Protocol( - "secure relay JSON-RPC message exceeds maximum length".to_string(), + "Noise relay JSON-RPC message exceeds maximum length".to_string(), )); } framed[..LENGTH_PREFIX_BYTES].copy_from_slice(&(message_len as u32).to_be_bytes()); @@ -37,9 +37,9 @@ impl JsonRpcMessageDecoder { &mut self, plaintext_record: &[u8], ) -> Result, ExecServerError> { - if plaintext_record.len() > SECURE_RECORD_PLAINTEXT_LEN { + if plaintext_record.len() > NOISE_RECORD_PLAINTEXT_LEN { return Err(ExecServerError::Protocol( - "secure relay plaintext record exceeds maximum length".to_string(), + "Noise relay plaintext record exceeds maximum length".to_string(), )); } self.buffered.extend_from_slice(plaintext_record); @@ -63,9 +63,9 @@ impl JsonRpcMessageDecoder { } // Even before a message is complete, keep reassembly memory bounded. - if self.buffered.len() > LENGTH_PREFIX_BYTES + MAX_SECURE_JSONRPC_MESSAGE_LEN { + if self.buffered.len() > LENGTH_PREFIX_BYTES + MAX_NOISE_JSONRPC_MESSAGE_LEN { return Err(ExecServerError::Protocol( - "secure relay JSON-RPC reassembly buffer exceeds maximum length".to_string(), + "Noise relay JSON-RPC reassembly buffer exceeds maximum length".to_string(), )); } Ok(messages) @@ -78,9 +78,9 @@ impl JsonRpcMessageDecoder { let message_len = u32::from_be_bytes([prefix[0], prefix[1], prefix[2], prefix[3]]) as usize; // Zero-length is never a JSON-RPC message, and rejecting an oversized // declaration immediately avoids waiting for attacker-controlled data. - if message_len == 0 || message_len > MAX_SECURE_JSONRPC_MESSAGE_LEN { + if message_len == 0 || message_len > MAX_NOISE_JSONRPC_MESSAGE_LEN { return Err(ExecServerError::Protocol( - "secure relay JSON-RPC message has invalid length".to_string(), + "Noise relay JSON-RPC message has invalid length".to_string(), )); } Ok(Some(message_len)) diff --git a/codex-rs/exec-server/src/secure_relay/message_framing_tests.rs b/codex-rs/exec-server/src/noise_relay/message_framing_tests.rs similarity index 73% rename from codex-rs/exec-server/src/secure_relay/message_framing_tests.rs rename to codex-rs/exec-server/src/noise_relay/message_framing_tests.rs index a94c67f8d3..c3df14bf56 100644 --- a/codex-rs/exec-server/src/secure_relay/message_framing_tests.rs +++ b/codex-rs/exec-server/src/noise_relay/message_framing_tests.rs @@ -3,8 +3,8 @@ use codex_app_server_protocol::JSONRPCNotification; use pretty_assertions::assert_eq; use super::JsonRpcMessageDecoder; -use super::MAX_SECURE_JSONRPC_MESSAGE_LEN; -use super::SECURE_RECORD_PLAINTEXT_LEN; +use super::MAX_NOISE_JSONRPC_MESSAGE_LEN; +use super::NOISE_RECORD_PLAINTEXT_LEN; use super::frame_jsonrpc_message; use crate::ExecServerError; @@ -21,7 +21,7 @@ fn fragments_and_reassembles_large_jsonrpc_message() { let mut decoder = JsonRpcMessageDecoder::default(); let mut decoded = Vec::new(); - for record in framed.chunks(SECURE_RECORD_PLAINTEXT_LEN) { + for record in framed.chunks(NOISE_RECORD_PLAINTEXT_LEN) { decoded.extend(decoder.push(record).unwrap()); } @@ -31,12 +31,12 @@ fn fragments_and_reassembles_large_jsonrpc_message() { #[test] fn rejects_declared_message_length_above_limit_without_payload() { let mut decoder = JsonRpcMessageDecoder::default(); - let declared_len = (MAX_SECURE_JSONRPC_MESSAGE_LEN as u32 + 1).to_be_bytes(); + let declared_len = (MAX_NOISE_JSONRPC_MESSAGE_LEN as u32 + 1).to_be_bytes(); assert!(matches!( decoder.push(&declared_len), Err(ExecServerError::Protocol(message)) - if message == "secure relay JSON-RPC message has invalid length" + if message == "Noise relay JSON-RPC message has invalid length" )); } @@ -45,8 +45,8 @@ fn rejects_oversized_plaintext_record() { let mut decoder = JsonRpcMessageDecoder::default(); assert!(matches!( - decoder.push(&vec![0; SECURE_RECORD_PLAINTEXT_LEN + 1]), + decoder.push(&vec![0; NOISE_RECORD_PLAINTEXT_LEN + 1]), Err(ExecServerError::Protocol(message)) - if message == "secure relay plaintext record exceeds maximum length" + if message == "Noise relay plaintext record exceeds maximum length" )); } diff --git a/codex-rs/exec-server/src/secure_relay/mod.rs b/codex-rs/exec-server/src/noise_relay/mod.rs similarity index 51% rename from codex-rs/exec-server/src/secure_relay/mod.rs rename to codex-rs/exec-server/src/noise_relay/mod.rs index d2b896ac06..2399a8cc8c 100644 --- a/codex-rs/exec-server/src/secure_relay/mod.rs +++ b/codex-rs/exec-server/src/noise_relay/mod.rs @@ -8,18 +8,18 @@ use tokio_tungstenite::tungstenite::protocol::WebSocketConfig; use crate::ExecServerError; pub(crate) use environment::HarnessKeyValidator; -pub(crate) use environment::run_secure_multiplexed_environment; -pub(crate) use harness::secure_harness_connection_from_websocket; +pub(crate) use environment::run_noise_multiplexed_environment; +pub(crate) use harness::noise_harness_connection_from_websocket; -// This bounds allocation in tungstenite before protobuf and secure-record +// This bounds allocation in tungstenite before protobuf and Noise record // validation run. It comfortably fits one maximum Noise record plus metadata. -const MAX_SECURE_RELAY_WEBSOCKET_MESSAGE_SIZE: usize = 256 * 1024; +const MAX_NOISE_RELAY_WEBSOCKET_MESSAGE_SIZE: usize = 256 * 1024; -/// Return the websocket limits required by every secure relay endpoint. -pub(crate) fn secure_relay_websocket_config() -> WebSocketConfig { +/// Return the websocket limits required by every Noise relay endpoint. +pub(crate) fn noise_relay_websocket_config() -> WebSocketConfig { WebSocketConfig::default() - .max_frame_size(Some(MAX_SECURE_RELAY_WEBSOCKET_MESSAGE_SIZE)) - .max_message_size(Some(MAX_SECURE_RELAY_WEBSOCKET_MESSAGE_SIZE)) + .max_frame_size(Some(MAX_NOISE_RELAY_WEBSOCKET_MESSAGE_SIZE)) + .max_message_size(Some(MAX_NOISE_RELAY_WEBSOCKET_MESSAGE_SIZE)) } fn take_next_sequence(next_seq: &mut u32) -> Result { @@ -27,7 +27,7 @@ fn take_next_sequence(next_seq: &mut u32) -> Result { // Noise nonce. Reusing zero after u32::MAX would be ambiguous and unsafe. let seq = *next_seq; *next_seq = next_seq.checked_add(1).ok_or_else(|| { - ExecServerError::Protocol("secure relay sequence number exhausted".to_string()) + ExecServerError::Protocol("Noise relay sequence number exhausted".to_string()) })?; Ok(seq) } diff --git a/codex-rs/exec-server/src/secure_relay/ordered_ciphertext.rs b/codex-rs/exec-server/src/noise_relay/ordered_ciphertext.rs similarity index 87% rename from codex-rs/exec-server/src/secure_relay/ordered_ciphertext.rs rename to codex-rs/exec-server/src/noise_relay/ordered_ciphertext.rs index 57fc957991..f122d49707 100644 --- a/codex-rs/exec-server/src/secure_relay/ordered_ciphertext.rs +++ b/codex-rs/exec-server/src/noise_relay/ordered_ciphertext.rs @@ -11,7 +11,7 @@ const MAX_PENDING_BYTES: usize = 1024 * 1024; /// Relay delivery can be duplicated or reordered, but Noise transport nonces /// are strictly ordered. This type absorbs only a small reliable-delivery /// window and releases ciphertexts exactly once in nonce order. It must sit -/// before `SecureTransport::decrypt`; attempting to decrypt a future record +/// before `NoiseTransport::decrypt`; attempting to decrypt a future record /// would advance or desynchronize cryptographic state. #[derive(Default)] pub(crate) struct OrderedCiphertextFrames { @@ -39,7 +39,7 @@ impl OrderedCiphertextFrames { // while forcing unbounded pre-decryption state. if seq - self.next_seq > MAX_REORDER_DISTANCE { return Err(ExecServerError::Protocol( - "secure relay ciphertext exceeds reorder window".to_string(), + "Noise relay ciphertext exceeds reorder window".to_string(), )); } let pending_bytes = self @@ -47,12 +47,12 @@ impl OrderedCiphertextFrames { .checked_add(payload.len()) .ok_or_else(|| { ExecServerError::Protocol( - "secure relay pending ciphertext byte count overflowed".to_string(), + "Noise relay pending ciphertext byte count overflowed".to_string(), ) })?; if self.pending.len() >= MAX_PENDING_FRAMES || pending_bytes > MAX_PENDING_BYTES { return Err(ExecServerError::Protocol( - "secure relay pending ciphertext buffer is full".to_string(), + "Noise relay pending ciphertext buffer is full".to_string(), )); } self.pending.insert(seq, payload); @@ -74,7 +74,7 @@ impl OrderedCiphertextFrames { fn advance(&mut self) -> Result<(), ExecServerError> { self.next_seq = self.next_seq.checked_add(1).ok_or_else(|| { - ExecServerError::Protocol("secure relay sequence number exhausted".to_string()) + ExecServerError::Protocol("Noise relay sequence number exhausted".to_string()) })?; Ok(()) } diff --git a/codex-rs/exec-server/src/secure_relay/ordered_ciphertext_tests.rs b/codex-rs/exec-server/src/noise_relay/ordered_ciphertext_tests.rs similarity index 100% rename from codex-rs/exec-server/src/secure_relay/ordered_ciphertext_tests.rs rename to codex-rs/exec-server/src/noise_relay/ordered_ciphertext_tests.rs diff --git a/codex-rs/exec-server/src/relay.rs b/codex-rs/exec-server/src/relay.rs index e9574921b0..04c5e5061e 100644 --- a/codex-rs/exec-server/src/relay.rs +++ b/codex-rs/exec-server/src/relay.rs @@ -94,7 +94,7 @@ impl RelayMessageFrame { } /// Validate cleartext routing metadata before a frame reaches either the - /// direct JSON-RPC parser or the secure relay state machine. + /// direct JSON-RPC parser or the Noise relay state machine. /// /// The encrypted path intentionally leaves this metadata visible to /// rendezvous, so it must be canonical and tightly bounded everywhere. @@ -377,7 +377,7 @@ where /// The physical websocket carries protobuf [`RelayMessageFrame`] values. Each /// frame's `stream_id` selects an independent logical JSON-RPC connection, so a /// single registered exec-server can serve multiple orchestrator sessions. -/// This runner intentionally preserves the protocol used before secure relay +/// This runner intentionally preserves the protocol used before Noise relay /// support was introduced. Callers must select the separate secure runner when /// Noise protection was explicitly negotiated during registration. /// diff --git a/codex-rs/exec-server/src/remote.rs b/codex-rs/exec-server/src/remote.rs index dd83234a14..0d6acfcd52 100644 --- a/codex-rs/exec-server/src/remote.rs +++ b/codex-rs/exec-server/src/remote.rs @@ -14,12 +14,12 @@ use codex_utils_rustls_provider::ensure_rustls_crypto_provider; use crate::ExecServerError; use crate::ExecServerRuntimePaths; -use crate::SecureChannelIdentity; -use crate::SecureChannelPublicKey; +use crate::NoiseChannelIdentity; +use crate::NoiseChannelPublicKey; +use crate::noise_relay::HarnessKeyValidator; +use crate::noise_relay::noise_relay_websocket_config; +use crate::noise_relay::run_noise_multiplexed_environment; use crate::relay::run_multiplexed_environment; -use crate::secure_relay::HarnessKeyValidator; -use crate::secure_relay::run_secure_multiplexed_environment; -use crate::secure_relay::secure_relay_websocket_config; use crate::server::ConnectionProcessor; const ERROR_BODY_PREVIEW_BYTES: usize = 4096; @@ -59,7 +59,7 @@ impl EnvironmentRegistryClient { /// Register using the original body-less registry contract. /// /// This remains the default so a new exec-server can still connect through - /// registries and harnesses that have not rolled out secure relay support. + /// registries and harnesses that have not rolled out Noise relay support. async fn register_legacy_environment( &self, environment_id: &str, @@ -76,15 +76,15 @@ impl EnvironmentRegistryClient { self.parse_json_response(response).await } - /// Register the exec-server's static Noise identity with a secure-aware registry. + /// Register the exec-server's static Noise identity with a Noise-aware registry. /// /// Supplying this request body is the protocol-level opt in. Registries can - /// therefore distinguish secure registrations from the legacy body-less + /// therefore distinguish Noise registrations from the legacy body-less /// contract without guessing based on binary version or rollout state. async fn register_noise_environment( &self, environment_id: &str, - executor_public_key: &SecureChannelPublicKey, + executor_public_key: &NoiseChannelPublicKey, ) -> Result { let response = self .http @@ -94,7 +94,7 @@ impl EnvironmentRegistryClient { )) .headers(self.auth_provider.to_auth_headers()) .json(&EnvironmentRegistryRegistrationRequest { - security_profile: SECURE_RELAY_SECURITY_PROFILE, + security_profile: NOISE_RELAY_SECURITY_PROFILE, executor_public_key, }) .send() @@ -106,7 +106,7 @@ impl EnvironmentRegistryClient { &self, environment_id: &str, executor_registration_id: &str, - harness_public_key: &SecureChannelPublicKey, + harness_public_key: &NoiseChannelPublicKey, harness_key_authorization: &str, ) -> Result<(), ExecServerError> { let response = self @@ -149,12 +149,12 @@ impl EnvironmentRegistryClient { } } -const SECURE_RELAY_SECURITY_PROFILE: &str = "noise_hybrid_ik_v1"; +const NOISE_RELAY_SECURITY_PROFILE: &str = "noise_hybrid_ik_v1"; #[derive(Serialize)] struct EnvironmentRegistryRegistrationRequest<'a> { security_profile: &'static str, - executor_public_key: &'a SecureChannelPublicKey, + executor_public_key: &'a NoiseChannelPublicKey, } #[derive(Debug, Clone, Eq, PartialEq, Deserialize)] @@ -174,7 +174,7 @@ struct EnvironmentRegistryNoiseRegistrationResponse { #[derive(Serialize)] struct EnvironmentRegistryHarnessKeyValidationRequest<'a> { executor_registration_id: &'a str, - harness_public_key: &'a SecureChannelPublicKey, + harness_public_key: &'a NoiseChannelPublicKey, harness_key_authorization: &'a str, } @@ -191,7 +191,7 @@ struct RegistryHarnessKeyValidator { impl HarnessKeyValidator for RegistryHarnessKeyValidator { async fn validate_harness_key( &self, - harness_public_key: &SecureChannelPublicKey, + harness_public_key: &NoiseChannelPublicKey, authorization: &str, ) -> Result<(), ExecServerError> { self.client @@ -205,28 +205,28 @@ impl HarnessKeyValidator for RegistryHarnessKeyValidator { } } -/// Security mode used for an exec-server's registered remote relay. +/// Protocol used for an exec-server's registered remote relay. /// /// Legacy is intentionally the default during rollout. Noise must be selected /// explicitly so mixed-version deployments keep the original registry and relay -/// contract until both endpoints are ready for the secure protocol. +/// contract until both endpoints are ready for Noise. #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] -pub enum RemoteRelaySecurity { +pub enum RemoteRelayProtocol { #[default] Legacy, Noise, } -enum RemoteRelaySecurityState { +enum RemoteRelayProtocolState { Legacy, - Noise(SecureChannelIdentity), + Noise(NoiseChannelIdentity), } enum RegisteredRemoteEnvironment { Legacy(EnvironmentRegistryRegistrationResponse), Noise { response: EnvironmentRegistryNoiseRegistrationResponse, - identity: SecureChannelIdentity, + identity: NoiseChannelIdentity, }, } @@ -252,7 +252,7 @@ pub struct RemoteEnvironmentConfig { pub base_url: String, pub environment_id: String, pub name: String, - pub relay_security: RemoteRelaySecurity, + pub relay_protocol: RemoteRelayProtocol, auth_provider: SharedAuthProvider, } @@ -262,7 +262,7 @@ impl std::fmt::Debug for RemoteEnvironmentConfig { .field("base_url", &self.base_url) .field("environment_id", &self.environment_id) .field("name", &self.name) - .field("relay_security", &self.relay_security) + .field("relay_protocol", &self.relay_protocol) .field("auth_provider", &"") .finish() } @@ -279,7 +279,7 @@ impl RemoteEnvironmentConfig { base_url, environment_id, name: "codex-exec-server".to_string(), - relay_security: RemoteRelaySecurity::Legacy, + relay_protocol: RemoteRelayProtocol::Legacy, auth_provider, }) } @@ -295,26 +295,26 @@ pub async fn run_remote_environment( let client = EnvironmentRegistryClient::new(config.base_url.clone(), config.auth_provider.clone())?; let processor = ConnectionProcessor::new(runtime_paths); - let security_state = match config.relay_security { - RemoteRelaySecurity::Legacy => RemoteRelaySecurityState::Legacy, - RemoteRelaySecurity::Noise => { - RemoteRelaySecurityState::Noise(SecureChannelIdentity::generate()?) + let protocol_state = match config.relay_protocol { + RemoteRelayProtocol::Legacy => RemoteRelayProtocolState::Legacy, + RemoteRelayProtocol::Noise => { + RemoteRelayProtocolState::Noise(NoiseChannelIdentity::generate()?) } }; let mut backoff = Duration::from_secs(1); loop { - let registration = match &security_state { - RemoteRelaySecurityState::Legacy => RegisteredRemoteEnvironment::Legacy( + let registration = match &protocol_state { + RemoteRelayProtocolState::Legacy => RegisteredRemoteEnvironment::Legacy( client .register_legacy_environment(&config.environment_id) .await?, ), - RemoteRelaySecurityState::Noise(identity) => { + RemoteRelayProtocolState::Noise(identity) => { let response = client .register_noise_environment(&config.environment_id, &identity.public_key()) .await?; - if response.security_profile != SECURE_RELAY_SECURITY_PROFILE { + if response.security_profile != NOISE_RELAY_SECURITY_PROFILE { return Err(ExecServerError::Protocol(format!( "environment registry returned unsupported security profile `{}`", response.security_profile @@ -337,7 +337,7 @@ pub async fn run_remote_environment( ); let websocket_config = match ®istration { RegisteredRemoteEnvironment::Legacy(_) => None, - RegisteredRemoteEnvironment::Noise { .. } => Some(secure_relay_websocket_config()), + RegisteredRemoteEnvironment::Noise { .. } => Some(noise_relay_websocket_config()), }; match timeout( @@ -357,7 +357,7 @@ pub async fn run_remote_environment( run_multiplexed_environment(websocket, processor.clone()).await; } RegisteredRemoteEnvironment::Noise { response, identity } => { - run_secure_multiplexed_environment( + run_noise_multiplexed_environment( websocket, processor.clone(), response.environment_id, diff --git a/codex-rs/exec-server/src/remote_tests.rs b/codex-rs/exec-server/src/remote_tests.rs index 1b77285ecc..1f94b644c2 100644 --- a/codex-rs/exec-server/src/remote_tests.rs +++ b/codex-rs/exec-server/src/remote_tests.rs @@ -75,20 +75,20 @@ async fn register_environment_posts_with_auth_provider_headers() { #[tokio::test] async fn register_noise_environment_posts_security_profile_and_public_key() { let server = MockServer::start().await; - let executor_public_key = SecureChannelIdentity::generate() + let executor_public_key = NoiseChannelIdentity::generate() .expect("identity") .public_key(); Mock::given(method("POST")) .and(path("/cloud/environment/environment-requested/register")) .and(header("authorization", "Bearer registry-token")) .and(body_partial_json(serde_json::json!({ - "security_profile": SECURE_RELAY_SECURITY_PROFILE, + "security_profile": NOISE_RELAY_SECURITY_PROFILE, "executor_public_key": executor_public_key.clone(), }))) .respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({ "environment_id": "environment-requested", - "url": "wss://rendezvous.test/secure", - "security_profile": SECURE_RELAY_SECURITY_PROFILE, + "url": "wss://rendezvous.test/noise", + "security_profile": NOISE_RELAY_SECURITY_PROFILE, "executor_registration_id": "registration-1", }))) .mount(&server) @@ -99,14 +99,14 @@ async fn register_noise_environment_posts_security_profile_and_public_key() { let response = client .register_noise_environment("environment-requested", &executor_public_key) .await - .expect("register secure environment"); + .expect("register Noise environment"); assert_eq!( response, EnvironmentRegistryNoiseRegistrationResponse { environment_id: "environment-requested".to_string(), - url: "wss://rendezvous.test/secure".to_string(), - security_profile: SECURE_RELAY_SECURITY_PROFILE.to_string(), + url: "wss://rendezvous.test/noise".to_string(), + security_profile: NOISE_RELAY_SECURITY_PROFILE.to_string(), executor_registration_id: "registration-1".to_string(), } ); @@ -174,7 +174,7 @@ fn remote_environment_config_accepts_cloud_environment_id() { .expect("config"); assert_eq!(config.environment_id, environment_id); - assert_eq!(config.relay_security, RemoteRelaySecurity::Legacy); + assert_eq!(config.relay_protocol, RemoteRelayProtocol::Legacy); } #[test] diff --git a/codex-rs/exec-server/tests/relay.rs b/codex-rs/exec-server/tests/relay.rs index 1e9107b40a..a11ea9ace6 100644 --- a/codex-rs/exec-server/tests/relay.rs +++ b/codex-rs/exec-server/tests/relay.rs @@ -22,14 +22,14 @@ use codex_exec_server::ExecServerClient; use codex_exec_server::ExecServerError; use codex_exec_server::ExecServerRuntimePaths; use codex_exec_server::FsReadFileParams; +use codex_exec_server::NoiseChannelIdentity; +use codex_exec_server::NoiseChannelPublicKey; +use codex_exec_server::NoiseRendezvousConnectArgs; +use codex_exec_server::NoiseRendezvousConnectBundle; +use codex_exec_server::NoiseRendezvousConnectProvider; use codex_exec_server::ProcessId; use codex_exec_server::RemoteEnvironmentConfig; -use codex_exec_server::RemoteRelaySecurity; -use codex_exec_server::SecureChannelIdentity; -use codex_exec_server::SecureChannelPublicKey; -use codex_exec_server::SecureRendezvousConnectArgs; -use codex_exec_server::SecureRendezvousConnectBundle; -use codex_exec_server::SecureRendezvousConnectProvider; +use codex_exec_server::RemoteRelayProtocol; use codex_utils_absolute_path::AbsolutePathBuf; use futures::FutureExt; use futures::SinkExt; @@ -56,7 +56,7 @@ use wiremock::matchers::header; use wiremock::matchers::method; use wiremock::matchers::path; -const ENVIRONMENT_ID: &str = "env-secure-relay-test"; +const ENVIRONMENT_ID: &str = "env-noise-relay-test"; const EXECUTOR_REGISTRATION_ID: &str = "registration-1"; const HARNESS_KEY_AUTHORIZATION: &str = "harness-key-authorization"; const REGISTRY_TOKEN: &str = "registry-token"; @@ -74,16 +74,16 @@ impl AuthProvider for StaticRegistryAuthProvider { } } -struct FailingSecureConnectProvider { +struct FailingNoiseConnectProvider { attempts: Arc, } -impl SecureRendezvousConnectProvider for FailingSecureConnectProvider { +impl NoiseRendezvousConnectProvider for FailingNoiseConnectProvider { fn environment_id(&self) -> &str { ENVIRONMENT_ID } - fn connect_args(&self) -> BoxFuture<'_, Result> { + fn connect_args(&self) -> BoxFuture<'_, Result> { self.attempts.fetch_add(1, Ordering::SeqCst); async { Err(ExecServerError::Protocol( @@ -94,20 +94,20 @@ impl SecureRendezvousConnectProvider for FailingSecureConnectProvider { } } -struct WrongEnvironmentSecureConnectProvider { - harness_identity: SecureChannelIdentity, - executor_public_key: SecureChannelPublicKey, +struct WrongEnvironmentNoiseConnectProvider { + harness_identity: NoiseChannelIdentity, + executor_public_key: NoiseChannelPublicKey, } -impl SecureRendezvousConnectProvider for WrongEnvironmentSecureConnectProvider { +impl NoiseRendezvousConnectProvider for WrongEnvironmentNoiseConnectProvider { fn environment_id(&self) -> &str { ENVIRONMENT_ID } - fn connect_args(&self) -> BoxFuture<'_, Result> { + fn connect_args(&self) -> BoxFuture<'_, Result> { async move { - Ok(SecureRendezvousConnectArgs::new( - SecureRendezvousConnectBundle { + Ok(NoiseRendezvousConnectArgs::new( + NoiseRendezvousConnectBundle { websocket_url: "ws://127.0.0.1:1".to_string(), environment_id: "wrong-environment".to_string(), executor_registration_id: EXECUTOR_REGISTRATION_ID.to_string(), @@ -115,7 +115,7 @@ impl SecureRendezvousConnectProvider for WrongEnvironmentSecureConnectProvider { harness_key_authorization: HARNESS_KEY_AUTHORIZATION.to_string(), }, self.harness_identity.clone(), - "secure-relay-test".to_string(), + "noise-relay-test".to_string(), )) } .boxed() @@ -150,7 +150,7 @@ async fn remote_environment_uses_legacy_relay_by_default() -> Result<()> { ENVIRONMENT_ID.to_string(), static_registry_auth_provider(), )?; - assert_eq!(config.relay_security, RemoteRelaySecurity::Legacy); + assert_eq!(config.relay_protocol, RemoteRelayProtocol::Legacy); let remote_environment = tokio::spawn(codex_exec_server::run_remote_environment( config, runtime_paths, @@ -205,18 +205,18 @@ async fn remote_environment_uses_legacy_relay_by_default() -> Result<()> { } #[tokio::test] -async fn secure_environment_refreshes_bundle_for_each_connection_attempt() -> Result<()> { +async fn noise_environment_refreshes_bundle_for_each_connection_attempt() -> Result<()> { let attempts = Arc::new(AtomicUsize::new(0)); let manager = EnvironmentManager::without_environments(); - manager.upsert_secure_environment( + manager.upsert_noise_environment( ENVIRONMENT_ID.to_string(), - Arc::new(FailingSecureConnectProvider { + Arc::new(FailingNoiseConnectProvider { attempts: Arc::clone(&attempts), }), )?; let backend = manager .get_environment(ENVIRONMENT_ID) - .context("secure environment should be materialized")? + .context("Noise environment should be materialized")? .get_exec_backend(); for attempt in 1..=2 { @@ -244,18 +244,18 @@ async fn secure_environment_refreshes_bundle_for_each_connection_attempt() -> Re } #[tokio::test] -async fn secure_environment_rejects_provider_bundle_for_another_environment() -> Result<()> { +async fn noise_environment_rejects_provider_bundle_for_another_environment() -> Result<()> { let manager = EnvironmentManager::without_environments(); - manager.upsert_secure_environment( + manager.upsert_noise_environment( ENVIRONMENT_ID.to_string(), - Arc::new(WrongEnvironmentSecureConnectProvider { - harness_identity: SecureChannelIdentity::generate()?, - executor_public_key: SecureChannelIdentity::generate()?.public_key(), + Arc::new(WrongEnvironmentNoiseConnectProvider { + harness_identity: NoiseChannelIdentity::generate()?, + executor_public_key: NoiseChannelIdentity::generate()?.public_key(), }), )?; let backend = manager .get_environment(ENVIRONMENT_ID) - .context("secure environment should be materialized")? + .context("Noise environment should be materialized")? .get_exec_backend(); let result = backend @@ -274,7 +274,7 @@ async fn secure_environment_rejects_provider_bundle_for_another_environment() -> assert!(matches!( result, Err(ExecServerError::Protocol(ref message)) - if message == "secure rendezvous provider returned a different environment id" + if message == "Noise rendezvous provider returned a different environment id" )); Ok(()) } @@ -313,7 +313,7 @@ async fn remote_environment_routes_encrypted_exec_server_rpc() -> Result<()> { ENVIRONMENT_ID.to_string(), static_registry_auth_provider(), )?; - config.relay_security = RemoteRelaySecurity::Noise; + config.relay_protocol = RemoteRelayProtocol::Noise; let remote_environment = tokio::spawn(codex_exec_server::run_remote_environment( config, runtime_paths, @@ -321,9 +321,9 @@ async fn remote_environment_routes_encrypted_exec_server_rpc() -> Result<()> { let environment_websocket = accept_websocket(&listener, "environment").await?; let executor_public_key = registered_executor_public_key(®istry).await?; - let harness_identity = SecureChannelIdentity::generate()?; - let client_args = SecureRendezvousConnectArgs::new( - SecureRendezvousConnectBundle { + let harness_identity = NoiseChannelIdentity::generate()?; + let client_args = NoiseRendezvousConnectArgs::new( + NoiseRendezvousConnectBundle { websocket_url: format!("{rendezvous_url}/relay?role=harness"), environment_id: ENVIRONMENT_ID.to_string(), executor_registration_id: EXECUTOR_REGISTRATION_ID.to_string(), @@ -331,10 +331,10 @@ async fn remote_environment_routes_encrypted_exec_server_rpc() -> Result<()> { harness_key_authorization: HARNESS_KEY_AUTHORIZATION.to_string(), }, harness_identity, - "secure-relay-test".to_string(), + "noise-relay-test".to_string(), ); let client_task = - tokio::spawn(async move { ExecServerClient::connect_secure_rendezvous(client_args).await }); + tokio::spawn(async move { ExecServerClient::connect_noise_rendezvous(client_args).await }); let harness_websocket = accept_websocket(&listener, "harness").await?; let captured_frames = Arc::new(Mutex::new(Vec::new())); let relay_task = tokio::spawn(proxy_relay_frames( @@ -344,7 +344,7 @@ async fn remote_environment_routes_encrypted_exec_server_rpc() -> Result<()> { )); let client = timeout(TEST_TIMEOUT, client_task) .await - .context("secure harness client should connect")???; + .context("Noise harness client should connect")???; let response = client .exec(ExecParams { @@ -403,7 +403,7 @@ async fn accept_websocket( .map_err(Into::into) } -async fn registered_executor_public_key(registry: &MockServer) -> Result { +async fn registered_executor_public_key(registry: &MockServer) -> Result { let requests = registry .received_requests() .await @@ -468,7 +468,7 @@ fn assert_relay_data_is_encrypted(captured_frames: &Mutex>>) -> Resu let payload = String::from_utf8_lossy(&data.payload); assert!(!payload.contains("initialize")); assert!(!payload.contains("process/start")); - assert!(!payload.contains("secure-relay-test")); + assert!(!payload.contains("noise-relay-test")); } assert!( data_frames >= 4,