CodexConnector/src/lib.rs

1958 lines
65 KiB
Rust

use std::collections::HashSet;
use std::io::{Read, Write};
use std::net::{SocketAddr, TcpStream};
use std::time::Duration;
#[cfg(feature = "daemon")]
use std::collections::HashMap;
#[cfg(feature = "daemon")]
use std::path::Path;
use aes_gcm::aead::{Aead, Payload};
use aes_gcm::{Aes256Gcm, KeyInit, Nonce};
#[cfg(feature = "daemon")]
use cultcache_rs::{CultCache, DatabaseEntry, OwnedRedbMessagePackBackingStore};
use rand_core::{OsRng, RngCore};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use thiserror::Error;
use zeroize::{Zeroize, Zeroizing};
#[cfg(feature = "daemon")]
mod daemon;
#[cfg(all(feature = "daemon", target_os = "linux"))]
mod idunn_health;
#[cfg(feature = "daemon")]
mod provider_backend;
#[cfg(feature = "daemon")]
pub use daemon::CodexCallerConfig;
#[cfg(feature = "daemon")]
pub use daemon::CodexDaemonConfig;
#[cfg(feature = "daemon")]
pub use daemon::CodexDaemonError;
#[cfg(feature = "daemon")]
pub use daemon::load_daemon_config;
#[cfg(feature = "daemon")]
pub use daemon::serve;
#[cfg(feature = "daemon")]
pub use daemon::write_daemon_config;
#[cfg(feature = "daemon")]
pub use provider_backend::CodexAppServerConfig;
#[cfg(feature = "daemon")]
pub use provider_backend::CodexAuthMode;
#[cfg(feature = "daemon")]
pub use provider_backend::CodexAuthReadiness;
#[cfg(feature = "daemon")]
pub use provider_backend::CodexProviderBackend;
#[cfg(feature = "daemon")]
pub use provider_backend::CodexProviderBackendError;
pub const PROVIDER_REQUEST_SCHEMA_ID: &str = "gamecult.codex.provider_request.v2";
pub const INVOCATION_SCHEMA_ID: &str = "gamecult.codex.transport_invocation.v2";
pub const RESULT_SCHEMA_ID: &str = "gamecult.codex.transport_result.v2";
pub const RECEIPT_SCHEMA_ID: &str = "gamecult.codex.transport_receipt.v2";
pub const ENVELOPE_SCHEMA_ID: &str = "gamecult.codex.transport_envelope.v2";
#[derive(Clone, PartialEq, Eq)]
pub struct CodexTransportKey([u8; 32]);
impl CodexTransportKey {
pub fn from_connection_secret(secret: &str) -> Result<Self, ServiceError> {
if secret.trim().is_empty() || secret.trim() != secret {
return Err(ServiceError::InvalidAdmission);
}
Ok(Self(Sha256::digest(secret.as_bytes()).into()))
}
}
impl Drop for CodexTransportKey {
fn drop(&mut self) {
self.0.zeroize();
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodexProviderRequest {
pub schema_id: String,
pub request_id: String,
pub conversation_id: String,
pub model: String,
pub instructions: String,
pub input: Vec<CodexInputItem>,
pub reasoning_effort: Option<String>,
pub reasoning_summary: Option<String>,
pub service_tier: Option<String>,
pub output_format_name: Option<String>,
pub previous_response_id: Option<String>,
pub tools: Vec<CodexToolDefinition>,
pub tool_choice: CodexToolChoice,
pub parallel_tool_calls: bool,
pub output_schema_json: Option<String>,
pub max_output_tokens: Option<u32>,
pub prompt_cache_key: Option<String>,
}
impl CodexProviderRequest {
pub fn new(
request_id: impl Into<String>,
conversation_id: impl Into<String>,
model: impl Into<String>,
instructions: impl Into<String>,
) -> Self {
Self {
schema_id: PROVIDER_REQUEST_SCHEMA_ID.to_string(),
request_id: request_id.into(),
conversation_id: conversation_id.into(),
model: model.into(),
instructions: instructions.into(),
input: Vec::new(),
reasoning_effort: None,
reasoning_summary: None,
service_tier: None,
output_format_name: None,
previous_response_id: None,
tools: Vec::new(),
tool_choice: CodexToolChoice::Auto,
parallel_tool_calls: false,
output_schema_json: None,
max_output_tokens: None,
prompt_cache_key: None,
}
}
pub fn validate(&self) -> Result<(), ContractError> {
if self.schema_id != PROVIDER_REQUEST_SCHEMA_ID {
return Err(ContractError::Schema);
}
require_id(&self.request_id, "request_id")?;
require_id(&self.conversation_id, "conversation_id")?;
require_id(&self.model, "model")?;
require_content(&self.instructions, "instructions")?;
if matches!(self.max_output_tokens, Some(0)) {
return Err(ContractError::Invalid("max_output_tokens"));
}
if self
.prompt_cache_key
.as_deref()
.is_some_and(|value| value.trim().is_empty())
{
return Err(ContractError::Invalid("prompt_cache_key"));
}
for (value, field) in [
(self.reasoning_effort.as_deref(), "reasoning_effort"),
(self.reasoning_summary.as_deref(), "reasoning_summary"),
(self.service_tier.as_deref(), "service_tier"),
(self.output_format_name.as_deref(), "output_format_name"),
(self.previous_response_id.as_deref(), "previous_response_id"),
] {
if let Some(value) = value {
require_id(value, field)?;
}
}
if let Some(schema) = &self.output_schema_json {
require_content(schema, "output_schema_json")?;
require_json_object(schema, "output_schema_json")?;
require_provider_name(
self.output_format_name
.as_deref()
.ok_or(ContractError::Invalid("output_format_name"))?,
"output_format_name",
)?;
} else if self.output_format_name.is_some() {
return Err(ContractError::Invalid("output_schema_json"));
}
if self.tools.is_empty() && self.tool_choice == CodexToolChoice::Required {
return Err(ContractError::Invalid("tool_choice"));
}
let mut tool_names = HashSet::new();
for tool in &self.tools {
require_provider_name(&tool.name, "tool.name")?;
require_content(&tool.description, "tool.description")?;
require_content(&tool.parameters_json, "tool.parameters_json")?;
require_json_object(&tool.parameters_json, "tool.parameters_json")?;
if !tool_names.insert(tool.name.as_str()) {
return Err(ContractError::DuplicateTool(tool.name.clone()));
}
}
for item in &self.input {
match item {
CodexInputItem::UserText { text } | CodexInputItem::AssistantText { text } => {
require_content(text, "input.text")?;
}
CodexInputItem::ToolCall {
call_id,
name,
arguments,
} => {
require_provider_call_id(call_id, "input.call_id")?;
require_provider_name(name, "input.tool_name")?;
require_content(arguments, "input.arguments")?;
}
CodexInputItem::ToolResult { call_id, output } => {
require_provider_call_id(call_id, "input.call_id")?;
require_content(output, "input.output")?;
}
}
}
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CodexToolChoice {
Auto,
Required,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CodexInputItem {
UserText {
text: String,
},
AssistantText {
text: String,
},
ToolCall {
call_id: String,
name: String,
arguments: String,
},
ToolResult {
call_id: String,
output: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodexToolDefinition {
pub name: String,
pub description: String,
pub parameters_json: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodexTransportInvocation {
pub schema_id: String,
pub caller_runtime_id: String,
pub expires_at_unix_ms: u64,
pub native_request_sha256: [u8; 32],
pub provider_request_sha256: [u8; 32],
pub request: CodexProviderRequest,
}
impl CodexTransportInvocation {
pub fn new(
caller_runtime_id: impl Into<String>,
expires_at_unix_ms: u64,
native_request_sha256: [u8; 32],
request: CodexProviderRequest,
) -> Result<Self, ContractError> {
let provider_request_sha256 = provider_request_sha256(&request)?;
Ok(Self {
schema_id: INVOCATION_SCHEMA_ID.to_string(),
caller_runtime_id: caller_runtime_id.into(),
expires_at_unix_ms,
native_request_sha256,
provider_request_sha256,
request,
})
}
pub fn validate(&self, now_unix_ms: u64, max_expiry_skew_ms: u64) -> Result<(), ContractError> {
if self.schema_id != INVOCATION_SCHEMA_ID {
return Err(ContractError::Schema);
}
require_id(&self.caller_runtime_id, "caller_runtime_id")?;
if self.native_request_sha256 == [0; 32] {
return Err(ContractError::Invalid("native_request_sha256"));
}
self.request.validate()?;
if self.provider_request_sha256 != provider_request_sha256(&self.request)? {
return Err(ContractError::ProviderDigest);
}
if self.expires_at_unix_ms < now_unix_ms
|| self.expires_at_unix_ms > now_unix_ms.saturating_add(max_expiry_skew_ms)
{
return Err(ContractError::Expiry);
}
Ok(())
}
pub fn request_id(&self) -> &str {
&self.request.request_id
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodexTransportResult {
pub schema_id: String,
pub request_id: String,
pub caller_runtime_id: String,
pub disposition: CodexTransportDisposition,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CodexTransportDisposition {
Refused(CodexRefusal),
Transported {
events: Vec<CodexTransportEvent>,
receipt: Box<CodexTransportReceipt>,
},
}
impl CodexTransportResult {
pub fn refused(invocation: &CodexTransportInvocation, reason: CodexRefusal) -> Self {
Self {
schema_id: RESULT_SCHEMA_ID.to_string(),
request_id: invocation.request_id().to_string(),
caller_runtime_id: invocation.caller_runtime_id.clone(),
disposition: CodexTransportDisposition::Refused(reason),
}
}
pub fn transported(
invocation: &CodexTransportInvocation,
events: Vec<CodexTransportEvent>,
receipt: CodexTransportReceipt,
) -> Self {
Self {
schema_id: RESULT_SCHEMA_ID.to_string(),
request_id: invocation.request_id().to_string(),
caller_runtime_id: invocation.caller_runtime_id.clone(),
disposition: CodexTransportDisposition::Transported {
events,
receipt: Box::new(receipt),
},
}
}
pub fn validate_against(
&self,
invocation: &CodexTransportInvocation,
) -> Result<(), ContractError> {
if self.schema_id != RESULT_SCHEMA_ID {
return Err(ContractError::Schema);
}
if self.request_id != invocation.request_id()
|| self.caller_runtime_id != invocation.caller_runtime_id
{
return Err(ContractError::Identity);
}
if let CodexTransportDisposition::Transported { events, receipt } = &self.disposition {
for (expected, event) in events.iter().enumerate() {
if event.sequence != expected as u64 {
return Err(ContractError::EventSequence);
}
event.validate()?;
}
receipt.validate_against(invocation)?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CodexTransportEventPayload {
TextDelta {
text: String,
},
ToolCall {
call_id: String,
name: String,
arguments: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodexTransportEvent {
pub sequence: u64,
pub payload: CodexTransportEventPayload,
}
impl CodexTransportEvent {
fn validate(&self) -> Result<(), ContractError> {
match &self.payload {
CodexTransportEventPayload::TextDelta { text } => require_content(text, "event.text"),
CodexTransportEventPayload::ToolCall {
call_id,
name,
arguments,
} => {
require_id(call_id, "event.call_id")?;
require_id(name, "event.tool_name")?;
require_content(arguments, "event.arguments")
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodexTransportReceipt {
pub schema_id: String,
pub request_id: String,
pub caller_runtime_id: String,
pub native_request_sha256: [u8; 32],
pub provider_request_sha256: [u8; 32],
pub model: String,
pub transport: String,
pub outcome: CodexTransportOutcome,
}
impl CodexTransportReceipt {
pub fn validate_against(
&self,
invocation: &CodexTransportInvocation,
) -> Result<(), ContractError> {
if self.schema_id != RECEIPT_SCHEMA_ID {
return Err(ContractError::Schema);
}
if self.request_id != invocation.request_id()
|| self.caller_runtime_id != invocation.caller_runtime_id
|| self.model != invocation.request.model
{
return Err(ContractError::Identity);
}
if self.provider_request_sha256 != invocation.provider_request_sha256 {
return Err(ContractError::ProviderDigest);
}
if self.native_request_sha256 != invocation.native_request_sha256 {
return Err(ContractError::NativeDigest);
}
require_id(&self.transport, "receipt.transport")?;
match &self.outcome {
CodexTransportOutcome::Completed {
provider_response_id: Some(value),
..
} => require_id(value, "receipt.provider_response_id")?,
CodexTransportOutcome::Failed {
failure_kind,
message,
} => {
require_id(failure_kind, "receipt.failure_kind")?;
require_content(message, "receipt.failure_message")?;
}
CodexTransportOutcome::Completed {
provider_response_id: None,
..
} => {}
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CodexTransportOutcome {
Completed {
provider_response_id: Option<String>,
input_tokens: Option<u64>,
output_tokens: Option<u64>,
reasoning_output_tokens: Option<u64>,
cached_input_tokens: Option<u64>,
},
Failed {
failure_kind: String,
message: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CodexRefusal {
Expired,
IdentitySubstitution,
ProviderDigestSubstitution,
Policy,
Capacity,
InFlight,
Indeterminate,
ReplayConflict,
Malformed,
}
pub fn canonical_provider_request_bytes(
request: &CodexProviderRequest,
) -> Result<Vec<u8>, ContractError> {
request.validate()?;
rmp_serde::to_vec(request).map_err(|_| ContractError::Encoding)
}
pub fn provider_request_sha256(request: &CodexProviderRequest) -> Result<[u8; 32], ContractError> {
Ok(Sha256::digest(canonical_provider_request_bytes(request)?).into())
}
pub fn canonical_responses_body(
request: &CodexProviderRequest,
) -> Result<serde_json::Value, ContractError> {
request.validate()?;
let input = request
.input
.iter()
.map(|item| match item {
CodexInputItem::UserText { text } => serde_json::json!({
"type": "message",
"role": "user",
"content": [{"type": "input_text", "text": text}],
}),
CodexInputItem::AssistantText { text } => serde_json::json!({
"type": "message",
"role": "assistant",
"content": [{"type": "output_text", "text": text}],
}),
CodexInputItem::ToolCall {
call_id,
name,
arguments,
} => serde_json::json!({
"type": "function_call",
"call_id": call_id,
"name": name,
"arguments": arguments,
}),
CodexInputItem::ToolResult { call_id, output } => serde_json::json!({
"type": "function_call_output",
"call_id": call_id,
"output": output,
}),
})
.collect::<Vec<_>>();
let tools = request
.tools
.iter()
.map(|tool| {
Ok(serde_json::json!({
"type": "function",
"name": tool.name,
"description": tool.description,
"parameters": serde_json::from_str::<serde_json::Value>(&tool.parameters_json)
.map_err(|_| ContractError::Invalid("tool.parameters_json"))?,
"strict": true,
}))
})
.collect::<Result<Vec<_>, ContractError>>()?;
let mut body = serde_json::json!({
"model": request.model,
"instructions": request.instructions,
"input": input,
"tools": tools,
"tool_choice": match request.tool_choice {
CodexToolChoice::Auto => "auto",
CodexToolChoice::Required => "required",
},
"parallel_tool_calls": request.parallel_tool_calls,
"store": false,
"stream": true,
"include": [],
});
let object = body
.as_object_mut()
.expect("the statically constructed Responses body is an object");
if request.reasoning_effort.is_some() || request.reasoning_summary.is_some() {
let mut reasoning = serde_json::Map::new();
if let Some(effort) = &request.reasoning_effort {
reasoning.insert("effort".to_string(), serde_json::json!(effort));
}
if let Some(summary) = &request.reasoning_summary {
reasoning.insert("summary".to_string(), serde_json::json!(summary));
}
object.insert("reasoning".to_string(), reasoning.into());
}
for (name, value) in [
(
"service_tier",
request
.service_tier
.as_ref()
.map(|value| serde_json::json!(value)),
),
(
"previous_response_id",
request
.previous_response_id
.as_ref()
.map(|value| serde_json::json!(value)),
),
(
"prompt_cache_key",
request
.prompt_cache_key
.as_ref()
.map(|value| serde_json::json!(value)),
),
(
"max_output_tokens",
request
.max_output_tokens
.map(|value| serde_json::json!(value)),
),
] {
if let Some(value) = value {
object.insert(name.to_string(), value);
}
}
if let (Some(name), Some(schema)) = (
request.output_format_name.as_ref(),
request.output_schema_json.as_ref(),
) {
object.insert(
"text".to_string(),
serde_json::json!({
"format": {
"type": "json_schema",
"name": name,
"strict": true,
"schema": serde_json::from_str::<serde_json::Value>(schema)
.map_err(|_| ContractError::Invalid("output_schema_json"))?,
}
}),
);
}
Ok(body)
}
pub fn canonical_responses_body_bytes(
request: &CodexProviderRequest,
) -> Result<Vec<u8>, ContractError> {
serde_json::to_vec(&canonical_responses_body(request)?).map_err(|_| ContractError::Encoding)
}
pub fn canonical_invocation_bytes(
invocation: &CodexTransportInvocation,
) -> Result<Vec<u8>, ContractError> {
invocation.request.validate()?;
if invocation.provider_request_sha256 != provider_request_sha256(&invocation.request)? {
return Err(ContractError::ProviderDigest);
}
rmp_serde::to_vec(invocation).map_err(|_| ContractError::Encoding)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CodexEnvelopeKind {
Invocation,
Result,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodexTransportEnvelope {
pub schema_id: String,
pub caller_runtime_id: String,
pub request_id: String,
pub message_kind: CodexEnvelopeKind,
pub nonce: [u8; 12],
pub ciphertext: Vec<u8>,
}
pub fn encrypt_invocation(
invocation: &CodexTransportInvocation,
security: &CodexTransportKey,
) -> Result<CodexTransportEnvelope, ServiceError> {
let plaintext = canonical_invocation_bytes(invocation)?;
encrypt_message(
&invocation.caller_runtime_id,
invocation.request_id(),
CodexEnvelopeKind::Invocation,
&plaintext,
security,
)
}
pub fn decrypt_invocation(
envelope: &CodexTransportEnvelope,
security: &CodexTransportKey,
) -> Result<CodexTransportInvocation, ServiceError> {
validate_envelope(envelope, CodexEnvelopeKind::Invocation)?;
let plaintext = decrypt_message(envelope, security)?;
let invocation: CodexTransportInvocation =
rmp_serde::from_slice(&plaintext).map_err(|_| ServiceError::Encoding)?;
if invocation.caller_runtime_id != envelope.caller_runtime_id
|| invocation.request_id() != envelope.request_id
{
return Err(ServiceError::OuterIdentity);
}
Ok(invocation)
}
pub fn encrypt_result(
result: &CodexTransportResult,
security: &CodexTransportKey,
) -> Result<CodexTransportEnvelope, ServiceError> {
let plaintext = rmp_serde::to_vec(result).map_err(|_| ServiceError::Encoding)?;
encrypt_message(
&result.caller_runtime_id,
&result.request_id,
CodexEnvelopeKind::Result,
&plaintext,
security,
)
}
pub fn decrypt_result(
envelope: &CodexTransportEnvelope,
security: &CodexTransportKey,
invocation: &CodexTransportInvocation,
) -> Result<CodexTransportResult, ServiceError> {
validate_envelope(envelope, CodexEnvelopeKind::Result)?;
let plaintext = decrypt_message(envelope, security)?;
let result: CodexTransportResult =
rmp_serde::from_slice(&plaintext).map_err(|_| ServiceError::Encoding)?;
if result.caller_runtime_id != envelope.caller_runtime_id
|| result.request_id != envelope.request_id
{
return Err(ServiceError::OuterIdentity);
}
result.validate_against(invocation)?;
Ok(result)
}
#[derive(Clone)]
pub struct CodexConnectorClient {
endpoint: SocketAddr,
security: CodexTransportKey,
max_frame_bytes: usize,
response_timeout: Option<Duration>,
}
impl CodexConnectorClient {
pub fn new(
endpoint: SocketAddr,
connection_key: impl Into<String>,
max_frame_bytes: usize,
response_timeout: Option<Duration>,
) -> Result<Self, CodexConnectorClientError> {
if endpoint.port() == 0
|| endpoint.ip().is_unspecified()
|| endpoint.ip().is_multicast()
|| endpoint.ip() == std::net::Ipv4Addr::BROADCAST
|| !(4096..=u32::MAX as usize).contains(&max_frame_bytes)
|| response_timeout.is_some_and(|timeout| timeout.is_zero())
{
return Err(CodexConnectorClientError::InvalidConfig);
}
let connection_key = Zeroizing::new(connection_key.into());
let security = CodexTransportKey::from_connection_secret(connection_key.as_str())?;
Ok(Self {
endpoint,
security,
max_frame_bytes,
response_timeout,
})
}
pub fn execute(
&self,
invocation: &CodexTransportInvocation,
) -> Result<CodexTransportResult, CodexConnectorClientError> {
let request = rmp_serde::to_vec(&encrypt_invocation(invocation, &self.security)?)
.map_err(|_| CodexConnectorClientError::Encoding)?;
let connect_timeout = self
.response_timeout
.unwrap_or(Duration::from_secs(10))
.min(Duration::from_secs(10));
let mut stream = TcpStream::connect_timeout(&self.endpoint, connect_timeout)
.map_err(CodexConnectorClientError::Connection)?;
stream
.set_read_timeout(self.response_timeout)
.and_then(|()| stream.set_write_timeout(self.response_timeout))
.map_err(CodexConnectorClientError::Connection)?;
write_transport_frame(&mut stream, &request, self.max_frame_bytes)
.map_err(client_frame_error)?;
let response =
read_transport_frame(&mut stream, self.max_frame_bytes).map_err(client_frame_error)?;
let envelope =
rmp_serde::from_slice(&response).map_err(|_| CodexConnectorClientError::Encoding)?;
decrypt_result(&envelope, &self.security, invocation).map_err(Into::into)
}
}
#[cfg(test)]
mod client_endpoint_tests {
use super::*;
#[test]
fn client_admits_explicit_unicast_and_refuses_non_destinations() {
for endpoint in ["127.0.0.1:4103", "172.19.0.1:4103", "[::1]:4103"] {
assert!(
CodexConnectorClient::new(
endpoint.parse().unwrap(),
"bounded-client-endpoint-key",
64 * 1024,
Some(Duration::from_secs(1)),
)
.is_ok(),
"{endpoint} should be an admissible explicit destination"
);
}
for endpoint in [
"0.0.0.0:4103",
"255.255.255.255:4103",
"224.0.0.1:4103",
"[::]:4103",
"[ff02::1]:4103",
"127.0.0.1:0",
] {
assert!(matches!(
CodexConnectorClient::new(
endpoint.parse().unwrap(),
"bounded-client-endpoint-key",
64 * 1024,
Some(Duration::from_secs(1)),
),
Err(CodexConnectorClientError::InvalidConfig)
));
}
}
}
#[derive(Debug, Error)]
pub enum CodexConnectorClientError {
#[error("invalid connector client configuration")]
InvalidConfig,
#[error("connector client connection failed")]
Connection(#[source] std::io::Error),
#[error("connector frame exceeded its bound")]
FrameSize,
#[error("connector MessagePack encoding failed")]
Encoding,
#[error(transparent)]
Transport(#[from] ServiceError),
}
#[derive(Debug)]
enum TransportFrameError {
Connection(std::io::Error),
Size,
}
fn client_frame_error(error: TransportFrameError) -> CodexConnectorClientError {
match error {
TransportFrameError::Connection(error) => CodexConnectorClientError::Connection(error),
TransportFrameError::Size => CodexConnectorClientError::FrameSize,
}
}
fn read_transport_frame(
reader: &mut impl Read,
max_frame_bytes: usize,
) -> Result<Vec<u8>, TransportFrameError> {
let mut length = [0_u8; 4];
reader
.read_exact(&mut length)
.map_err(TransportFrameError::Connection)?;
let length = u32::from_be_bytes(length) as usize;
if length == 0 || length > max_frame_bytes {
return Err(TransportFrameError::Size);
}
let mut payload = vec![0_u8; length];
reader
.read_exact(&mut payload)
.map_err(TransportFrameError::Connection)?;
Ok(payload)
}
fn write_transport_frame(
writer: &mut impl Write,
payload: &[u8],
max_frame_bytes: usize,
) -> Result<(), TransportFrameError> {
if payload.is_empty() || payload.len() > max_frame_bytes || payload.len() > u32::MAX as usize {
return Err(TransportFrameError::Size);
}
writer
.write_all(&(payload.len() as u32).to_be_bytes())
.and_then(|()| writer.write_all(payload))
.and_then(|()| writer.flush())
.map_err(TransportFrameError::Connection)
}
fn encrypt_message(
caller_runtime_id: &str,
request_id: &str,
message_kind: CodexEnvelopeKind,
plaintext: &[u8],
security: &CodexTransportKey,
) -> Result<CodexTransportEnvelope, ServiceError> {
require_id(caller_runtime_id, "caller_runtime_id")?;
require_id(request_id, "request_id")?;
let mut nonce = [0; 12];
OsRng.fill_bytes(&mut nonce);
let cipher = Aes256Gcm::new_from_slice(&security.0).map_err(|_| ServiceError::Encryption)?;
let aad = envelope_aad(
ENVELOPE_SCHEMA_ID,
caller_runtime_id,
request_id,
message_kind,
)?;
let ciphertext = cipher
.encrypt(
Nonce::from_slice(&nonce),
Payload {
msg: plaintext,
aad: &aad,
},
)
.map_err(|_| ServiceError::Encryption)?;
Ok(CodexTransportEnvelope {
schema_id: ENVELOPE_SCHEMA_ID.to_string(),
caller_runtime_id: caller_runtime_id.to_string(),
request_id: request_id.to_string(),
message_kind,
nonce,
ciphertext,
})
}
fn decrypt_message(
envelope: &CodexTransportEnvelope,
security: &CodexTransportKey,
) -> Result<Vec<u8>, ServiceError> {
let cipher = Aes256Gcm::new_from_slice(&security.0).map_err(|_| ServiceError::Encryption)?;
let aad = envelope_aad(
&envelope.schema_id,
&envelope.caller_runtime_id,
&envelope.request_id,
envelope.message_kind,
)?;
cipher
.decrypt(
Nonce::from_slice(&envelope.nonce),
Payload {
msg: &envelope.ciphertext,
aad: &aad,
},
)
.map_err(|_| ServiceError::Encryption)
}
fn envelope_aad(
schema_id: &str,
caller_runtime_id: &str,
request_id: &str,
message_kind: CodexEnvelopeKind,
) -> Result<Vec<u8>, ServiceError> {
rmp_serde::to_vec(&(schema_id, caller_runtime_id, request_id, message_kind))
.map_err(|_| ServiceError::Encoding)
}
fn validate_envelope(
envelope: &CodexTransportEnvelope,
expected_kind: CodexEnvelopeKind,
) -> Result<(), ServiceError> {
if envelope.schema_id != ENVELOPE_SCHEMA_ID || envelope.message_kind != expected_kind {
return Err(ServiceError::Envelope);
}
require_id(&envelope.caller_runtime_id, "caller_runtime_id")?;
require_id(&envelope.request_id, "request_id")?;
if envelope.ciphertext.is_empty() {
return Err(ServiceError::Envelope);
}
Ok(())
}
#[cfg(feature = "daemon")]
pub struct CodexCallerAdmission {
caller_runtime_id: String,
connection_key_epoch: u32,
security: CodexTransportKey,
allowed_models: HashSet<String>,
max_concurrent_requests: usize,
max_payload_bytes: usize,
max_output_tokens: u32,
}
#[cfg(feature = "daemon")]
impl CodexCallerAdmission {
pub fn new(
caller_runtime_id: impl Into<String>,
connection_key: impl Into<String>,
connection_key_epoch: u32,
allowed_models: impl IntoIterator<Item = String>,
max_concurrent_requests: usize,
max_payload_bytes: usize,
max_output_tokens: u32,
) -> Result<Self, ServiceError> {
let caller_runtime_id = caller_runtime_id.into();
require_id(&caller_runtime_id, "caller_runtime_id")?;
let allowed_models = allowed_models.into_iter().collect::<HashSet<_>>();
if connection_key_epoch == 0
|| allowed_models.is_empty()
|| allowed_models
.iter()
.any(|model| require_id(model, "allowed_model").is_err())
|| max_concurrent_requests == 0
|| max_payload_bytes == 0
|| max_output_tokens == 0
{
return Err(ServiceError::InvalidAdmission);
}
let connection_key = Zeroizing::new(connection_key.into());
let security = CodexTransportKey::from_connection_secret(connection_key.as_str())?;
Ok(Self {
caller_runtime_id,
connection_key_epoch,
security,
allowed_models,
max_concurrent_requests,
max_payload_bytes,
max_output_tokens,
})
}
pub fn caller_runtime_id(&self) -> &str {
&self.caller_runtime_id
}
}
#[cfg(feature = "daemon")]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct RequestIdentity {
caller_runtime_id: String,
request_id: String,
}
#[cfg(feature = "daemon")]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
enum CodexReplayState {
Active,
Completed { response: CodexTransportEnvelope },
}
#[cfg(feature = "daemon")]
#[derive(Clone, Debug, PartialEq, Eq, DatabaseEntry)]
#[cultcache(type = "gamecult.codex.replay_record.v1")]
struct CodexReplayRecord {
#[cultcache(key = 0)]
caller_runtime_id: String,
#[cultcache(key = 1)]
request_id: String,
#[cultcache(key = 2)]
connection_key_epoch: u32,
#[cultcache(key = 3)]
invocation_sha256: [u8; 32],
#[cultcache(key = 4)]
expires_at_unix_ms: u64,
#[cultcache(key = 5)]
state: CodexReplayState,
}
#[cfg(feature = "daemon")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CodexExecutionClaim {
invocation: CodexTransportInvocation,
invocation_sha256: [u8; 32],
}
#[cfg(feature = "daemon")]
impl CodexExecutionClaim {
pub fn invocation(&self) -> &CodexTransportInvocation {
&self.invocation
}
}
#[cfg(feature = "daemon")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CodexTransportAdmission {
Execute(Box<CodexExecutionClaim>),
Reply(CodexTransportEnvelope),
}
#[cfg(feature = "daemon")]
pub struct CodexTransportService {
callers: HashMap<String, CodexCallerAdmission>,
live: HashSet<RequestIdentity>,
replay_store: CultCache,
max_expiry_skew_ms: u64,
}
#[cfg(feature = "daemon")]
impl CodexTransportService {
pub fn open(
replay_store_path: &Path,
admissions: impl IntoIterator<Item = CodexCallerAdmission>,
max_expiry_skew_ms: u64,
) -> Result<Self, ServiceError> {
if max_expiry_skew_ms == 0 {
return Err(ServiceError::InvalidAdmission);
}
let mut callers = HashMap::new();
let mut keys = HashSet::new();
for admission in admissions {
if !keys.insert(admission.security.0) {
return Err(ServiceError::SharedCallerKey);
}
let caller_runtime_id = admission.caller_runtime_id.clone();
if callers.insert(caller_runtime_id, admission).is_some() {
return Err(ServiceError::DuplicateCaller);
}
}
if callers.is_empty() {
return Err(ServiceError::InvalidAdmission);
}
let mut replay_store = CultCache::new();
replay_store
.register_entry_type::<CodexReplayRecord>()
.map_err(replay_store_error)?;
replay_store.add_generic_backing_store(
OwnedRedbMessagePackBackingStore::new(replay_store_path).map_err(replay_store_error)?,
);
replay_store
.pull_all_backing_stores()
.map_err(replay_store_error)?;
for (key, record) in replay_store
.get_all_with_keys::<CodexReplayRecord>()
.map_err(replay_store_error)?
{
let identity = RequestIdentity {
caller_runtime_id: record.caller_runtime_id.clone(),
request_id: record.request_id.clone(),
};
if key != replay_key(&identity)
|| record.invocation_sha256 == [0; 32]
|| record.expires_at_unix_ms == 0
{
return Err(ServiceError::InvalidReplayRecord);
}
let Some(caller) = callers.get(&record.caller_runtime_id) else {
continue;
};
if record.connection_key_epoch != caller.connection_key_epoch {
return Err(ServiceError::ReplayCallerKeyMismatch);
}
}
Ok(Self {
callers,
live: HashSet::new(),
replay_store,
max_expiry_skew_ms,
})
}
pub fn begin(
&mut self,
envelope: &CodexTransportEnvelope,
now_unix_ms: u64,
) -> Result<CodexTransportAdmission, ServiceError> {
validate_envelope(envelope, CodexEnvelopeKind::Invocation)?;
let caller = self
.callers
.get(&envelope.caller_runtime_id)
.ok_or(ServiceError::CallerNotAdmitted)?;
if envelope.ciphertext.len() > caller.max_payload_bytes {
return Err(ServiceError::PayloadTooLarge);
}
let security = caller.security.clone();
let max_concurrent_requests = caller.max_concurrent_requests;
let invocation = decrypt_invocation(envelope, &security)?;
if let Err(error) = invocation.validate(now_unix_ms, self.max_expiry_skew_ms) {
return self.reply_refusal(&invocation, contract_refusal(&error), &security);
}
if !caller.allowed_models.contains(&invocation.request.model)
|| invocation
.request
.max_output_tokens
.is_some_and(|limit| limit > caller.max_output_tokens)
{
return self.reply_refusal(&invocation, CodexRefusal::Policy, &security);
}
let identity = RequestIdentity {
caller_runtime_id: invocation.caller_runtime_id.clone(),
request_id: invocation.request_id().to_string(),
};
let invocation_sha256: [u8; 32] =
Sha256::digest(canonical_invocation_bytes(&invocation)?).into();
if let Some(record) = self
.replay_store
.get::<CodexReplayRecord>(&replay_key(&identity))
.map_err(replay_store_error)?
{
if record.invocation_sha256 != invocation_sha256 {
return self.reply_refusal(&invocation, CodexRefusal::ReplayConflict, &security);
}
return match record.state {
CodexReplayState::Completed { response } => {
Ok(CodexTransportAdmission::Reply(response))
}
CodexReplayState::Active => {
let refusal = if self.live.contains(&identity) {
CodexRefusal::InFlight
} else {
CodexRefusal::Indeterminate
};
self.reply_refusal(&invocation, refusal, &security)
}
};
}
let active_for_caller = self
.live
.iter()
.filter(|key| key.caller_runtime_id == invocation.caller_runtime_id)
.count();
if active_for_caller >= max_concurrent_requests {
return self.reply_refusal(&invocation, CodexRefusal::Capacity, &security);
}
let replay_record = CodexReplayRecord {
caller_runtime_id: identity.caller_runtime_id.clone(),
request_id: identity.request_id.clone(),
connection_key_epoch: caller.connection_key_epoch,
invocation_sha256,
expires_at_unix_ms: invocation.expires_at_unix_ms,
state: CodexReplayState::Active,
};
self.replay_store
.put(replay_key(&identity), &replay_record)
.map_err(replay_store_error)?;
self.live.insert(identity);
Ok(CodexTransportAdmission::Execute(Box::new(
CodexExecutionClaim {
invocation,
invocation_sha256,
},
)))
}
pub fn complete(
&mut self,
claim: CodexExecutionClaim,
result: CodexTransportResult,
) -> Result<CodexTransportEnvelope, ServiceError> {
if !matches!(
&result.disposition,
CodexTransportDisposition::Transported { .. }
) {
return Err(ServiceError::InvalidCompletion);
}
result.validate_against(&claim.invocation)?;
let identity = RequestIdentity {
caller_runtime_id: claim.invocation.caller_runtime_id.clone(),
request_id: claim.invocation.request_id().to_string(),
};
if !self.live.contains(&identity) {
return Err(ServiceError::NoActiveRequest);
}
let active = self
.replay_store
.get::<CodexReplayRecord>(&replay_key(&identity))
.map_err(replay_store_error)?
.ok_or(ServiceError::NoActiveRequest)?;
if active.invocation_sha256 != claim.invocation_sha256
|| !matches!(active.state, CodexReplayState::Active)
{
return Err(ServiceError::ActiveRequestMismatch);
}
let caller = self
.callers
.get(&identity.caller_runtime_id)
.ok_or(ServiceError::CallerNotAdmitted)?;
let response = encrypt_result(&result, &caller.security)?;
let replay_record = CodexReplayRecord {
caller_runtime_id: identity.caller_runtime_id.clone(),
request_id: identity.request_id.clone(),
connection_key_epoch: caller.connection_key_epoch,
invocation_sha256: claim.invocation_sha256,
expires_at_unix_ms: claim.invocation.expires_at_unix_ms,
state: CodexReplayState::Completed {
response: response.clone(),
},
};
self.replay_store
.put(replay_key(&identity), &replay_record)
.map_err(replay_store_error)?;
self.live.remove(&identity);
Ok(response)
}
fn reply_refusal(
&self,
invocation: &CodexTransportInvocation,
refusal: CodexRefusal,
security: &CodexTransportKey,
) -> Result<CodexTransportAdmission, ServiceError> {
Ok(CodexTransportAdmission::Reply(encrypt_result(
&CodexTransportResult::refused(invocation, refusal),
security,
)?))
}
}
#[cfg(feature = "daemon")]
fn replay_key(identity: &RequestIdentity) -> String {
let mut hasher = Sha256::new();
hasher.update((identity.caller_runtime_id.len() as u64).to_be_bytes());
hasher.update(identity.caller_runtime_id.as_bytes());
hasher.update((identity.request_id.len() as u64).to_be_bytes());
hasher.update(identity.request_id.as_bytes());
const HEX: &[u8; 16] = b"0123456789abcdef";
let digest = hasher.finalize();
let mut key = String::with_capacity(64);
for byte in digest {
key.push(HEX[(byte >> 4) as usize] as char);
key.push(HEX[(byte & 0x0f) as usize] as char);
}
key
}
#[cfg(feature = "daemon")]
fn replay_store_error(error: impl std::fmt::Display) -> ServiceError {
ServiceError::ReplayStore(error.to_string())
}
#[cfg(feature = "daemon")]
fn contract_refusal(error: &ContractError) -> CodexRefusal {
match error {
ContractError::Expiry => CodexRefusal::Expired,
ContractError::Identity => CodexRefusal::IdentitySubstitution,
ContractError::ProviderDigest => CodexRefusal::ProviderDigestSubstitution,
_ => CodexRefusal::Malformed,
}
}
#[derive(Debug, Error, PartialEq, Eq)]
pub enum ServiceError {
#[error(transparent)]
Contract(#[from] ContractError),
#[error("invalid caller admission")]
InvalidAdmission,
#[error("caller runtime was admitted twice")]
DuplicateCaller,
#[error("callers must not share transport keys")]
SharedCallerKey,
#[error("connector replay store failed: {0}")]
ReplayStore(String),
#[error("connector replay record is malformed")]
InvalidReplayRecord,
#[error("caller key changed while durable replay records still exist")]
ReplayCallerKeyMismatch,
#[error("caller runtime is not admitted")]
CallerNotAdmitted,
#[error("transport payload exceeds the caller bound")]
PayloadTooLarge,
#[error("unexpected transport envelope")]
Envelope,
#[error("transport envelope identity substitution")]
OuterIdentity,
#[error("transport encryption or authentication failed")]
Encryption,
#[error("transport MessagePack encoding failed")]
Encoding,
#[error("completion did not carry a transported provider outcome")]
InvalidCompletion,
#[error("completion has no active request")]
NoActiveRequest,
#[error("completion does not match the active request")]
ActiveRequestMismatch,
}
fn require_id(value: &str, field: &'static str) -> Result<(), ContractError> {
if value.trim().is_empty() || value.trim() != value {
return Err(ContractError::Invalid(field));
}
Ok(())
}
fn require_content(value: &str, field: &'static str) -> Result<(), ContractError> {
if value.is_empty() {
return Err(ContractError::Invalid(field));
}
Ok(())
}
fn require_json_object(value: &str, field: &'static str) -> Result<(), ContractError> {
if !matches!(
serde_json::from_str::<serde_json::Value>(value),
Ok(serde_json::Value::Object(_))
) {
return Err(ContractError::Invalid(field));
}
Ok(())
}
fn require_provider_name(value: &str, field: &'static str) -> Result<(), ContractError> {
if value.is_empty()
|| value.len() > 64
|| !value
.bytes()
.all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'_' | b'-'))
{
return Err(ContractError::Invalid(field));
}
Ok(())
}
fn require_provider_call_id(value: &str, field: &'static str) -> Result<(), ContractError> {
if value.is_empty() || value.len() > 64 || !value.is_ascii() {
return Err(ContractError::Invalid(field));
}
Ok(())
}
#[derive(Debug, Error, PartialEq, Eq)]
pub enum ContractError {
#[error("unexpected schema")]
Schema,
#[error("invalid {0}")]
Invalid(&'static str),
#[error("duplicate tool {0:?}")]
DuplicateTool(String),
#[error("request identity substitution")]
Identity,
#[error("provider request digest substitution")]
ProviderDigest,
#[error("native request digest substitution")]
NativeDigest,
#[error("invocation expiry is outside the admitted horizon")]
Expiry,
#[error("transport event sequence is not contiguous")]
EventSequence,
#[error("canonical MessagePack encoding failed")]
Encoding,
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "daemon")]
use std::sync::atomic::{AtomicUsize, Ordering};
#[cfg(feature = "daemon")]
static TEST_STORE_SEQUENCE: AtomicUsize = AtomicUsize::new(0);
#[cfg(feature = "daemon")]
struct TestStore {
root: std::path::PathBuf,
path: std::path::PathBuf,
}
#[cfg(feature = "daemon")]
impl TestStore {
fn new() -> Self {
let sequence = TEST_STORE_SEQUENCE.fetch_add(1, Ordering::Relaxed);
let root = std::env::temp_dir().join(format!(
"codex-connector-replay-{}-{sequence}",
std::process::id()
));
std::fs::create_dir_all(&root).unwrap();
let path = root.join("replay.cc");
Self { root, path }
}
}
#[cfg(feature = "daemon")]
impl Drop for TestStore {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.root);
}
}
fn request() -> CodexProviderRequest {
let mut request = CodexProviderRequest::new(
"request-1",
"conversation-1",
"gpt-5.4",
"Return the typed result.",
);
request.input.push(CodexInputItem::UserText {
text: "Projected state".to_string(),
});
request.tools.push(CodexToolDefinition {
name: "read_source".to_string(),
description: "Read one admitted source.".to_string(),
parameters_json: r#"{"type":"object"}"#.to_string(),
});
request
}
fn invocation() -> CodexTransportInvocation {
CodexTransportInvocation::new("epiphany-yggdrasil", 2_000, [7; 32], request()).unwrap()
}
fn receipt(invocation: &CodexTransportInvocation) -> CodexTransportReceipt {
CodexTransportReceipt {
schema_id: RECEIPT_SCHEMA_ID.to_string(),
request_id: invocation.request_id().to_string(),
caller_runtime_id: invocation.caller_runtime_id.clone(),
native_request_sha256: invocation.native_request_sha256,
provider_request_sha256: invocation.provider_request_sha256,
model: invocation.request.model.clone(),
transport: "codex-responses-sse".to_string(),
outcome: CodexTransportOutcome::Completed {
provider_response_id: Some("response-1".to_string()),
input_tokens: Some(10),
output_tokens: Some(3),
reasoning_output_tokens: Some(1),
cached_input_tokens: None,
},
}
}
#[test]
fn provider_digest_is_stable_and_content_addressed() {
let original = request();
let same = original.clone();
assert_eq!(
provider_request_sha256(&original).unwrap(),
provider_request_sha256(&same).unwrap()
);
let mut changed = original.clone();
changed.instructions.push_str(" Changed.");
assert_ne!(
provider_request_sha256(&original).unwrap(),
provider_request_sha256(&changed).unwrap()
);
}
#[test]
fn canonical_responses_body_preserves_caller_owned_provider_policy() {
let mut request = request();
request.tool_choice = CodexToolChoice::Required;
request.parallel_tool_calls = false;
request.reasoning_effort = Some("high".to_string());
request.previous_response_id = Some("response-previous".to_string());
request.max_output_tokens = Some(512);
request.output_format_name = Some("epiphany_role_result_v3".to_string());
request.output_schema_json = Some(
r#"{"type":"object","properties":{"summary":{"type":"string"}},"required":["summary"],"additionalProperties":false}"#
.to_string(),
);
let body = canonical_responses_body(&request).unwrap();
assert_eq!(body["tool_choice"], "required");
assert_eq!(body["parallel_tool_calls"], false);
assert_eq!(body["reasoning"], serde_json::json!({"effort": "high"}));
assert_eq!(body["previous_response_id"], "response-previous");
assert_eq!(body["max_output_tokens"], 512);
assert_eq!(body["tools"][0]["name"], "read_source");
assert_eq!(body["text"]["format"]["name"], "epiphany_role_result_v3");
assert_eq!(
canonical_responses_body_bytes(&request).unwrap(),
serde_json::to_vec(&body).unwrap()
);
}
#[test]
fn provider_contract_refuses_transport_side_fixup_pressure() {
let mut request = request();
request.output_format_name = Some("epiphany.role.result".to_string());
request.output_schema_json = Some(r#"{"type":"object"}"#.to_string());
assert_eq!(
request.validate(),
Err(ContractError::Invalid("output_format_name"))
);
request.output_format_name = None;
request.output_schema_json = None;
request.input.push(CodexInputItem::ToolResult {
call_id: "x".repeat(65),
output: "evidence".to_string(),
});
assert_eq!(
request.validate(),
Err(ContractError::Invalid("input.call_id"))
);
}
#[test]
fn invocation_refuses_provider_request_substitution() {
let mut invocation = invocation();
invocation.request.model = "substituted".to_string();
assert_eq!(
invocation.validate(1_000, 2_000),
Err(ContractError::ProviderDigest)
);
}
#[test]
fn invocation_refuses_expired_or_blank_native_provenance() {
let mut invocation = invocation();
assert_eq!(
invocation.validate(2_001, 2_000),
Err(ContractError::Expiry)
);
invocation.expires_at_unix_ms = 2_500;
invocation.native_request_sha256 = [0; 32];
assert_eq!(
invocation.validate(2_001, 2_000),
Err(ContractError::Invalid("native_request_sha256"))
);
}
#[test]
fn typed_tool_round_survives_messagepack() {
let invocation = invocation();
let bytes = rmp_serde::to_vec(&invocation).unwrap();
let decoded: CodexTransportInvocation = rmp_serde::from_slice(&bytes).unwrap();
assert_eq!(decoded, invocation);
assert!(matches!(
decoded.request.tools.as_slice(),
[CodexToolDefinition { name, .. }] if name == "read_source"
));
}
#[test]
fn transported_result_binds_identity_digest_and_event_order() {
let invocation = invocation();
let result = CodexTransportResult::transported(
&invocation,
vec![CodexTransportEvent {
sequence: 0,
payload: CodexTransportEventPayload::ToolCall {
call_id: "call-1".to_string(),
name: "read_source".to_string(),
arguments: "{}".to_string(),
},
}],
receipt(&invocation),
);
assert_eq!(result.validate_against(&invocation), Ok(()));
let mut reordered = result;
let CodexTransportDisposition::Transported { events, .. } = &mut reordered.disposition
else {
unreachable!()
};
events[0].sequence = 1;
assert_eq!(
reordered.validate_against(&invocation),
Err(ContractError::EventSequence)
);
}
#[test]
fn receipt_refuses_caller_substitution() {
let invocation = invocation();
let mut substituted_caller = receipt(&invocation);
substituted_caller.caller_runtime_id = "ghostlight-dungeon-yggdrasil".to_string();
assert_eq!(
substituted_caller.validate_against(&invocation),
Err(ContractError::Identity)
);
let mut substituted_native_basis = receipt(&invocation);
substituted_native_basis.native_request_sha256 = [8; 32];
assert_eq!(
substituted_native_basis.validate_against(&invocation),
Err(ContractError::NativeDigest)
);
}
#[cfg(feature = "daemon")]
fn caller(
caller_runtime_id: &str,
key: &str,
max_concurrent_requests: usize,
) -> CodexCallerAdmission {
CodexCallerAdmission::new(
caller_runtime_id,
key,
1,
["gpt-5.4".to_string()],
max_concurrent_requests,
64 * 1024,
32_768,
)
.unwrap()
}
#[cfg(feature = "daemon")]
fn open_service(store: &TestStore, max_concurrent_requests: usize) -> CodexTransportService {
CodexTransportService::open(
&store.path,
[
caller(
"epiphany-yggdrasil",
"epiphany-distinct-test-key",
max_concurrent_requests,
),
caller(
"ghostlight-yggdrasil",
"ghostlight-distinct-test-key",
max_concurrent_requests,
),
],
5_000,
)
.unwrap()
}
fn security(key: &str) -> CodexTransportKey {
CodexTransportKey::from_connection_secret(key).unwrap()
}
#[cfg(feature = "daemon")]
fn invocation_for(caller_runtime_id: &str, request_id: &str) -> CodexTransportInvocation {
let mut request = request();
request.request_id = request_id.to_string();
CodexTransportInvocation::new(caller_runtime_id, 2_000, [7; 32], request).unwrap()
}
#[test]
fn encrypted_invocation_hides_content_and_binds_outer_identity() {
let invocation = invocation();
let epiphany_key = security("epiphany-distinct-test-key");
let envelope = encrypt_invocation(&invocation, &epiphany_key).unwrap();
assert!(
!envelope
.ciphertext
.windows("Projected state".len())
.any(|window| window == b"Projected state")
);
assert_eq!(
decrypt_invocation(&envelope, &epiphany_key).unwrap(),
invocation
);
assert_eq!(
decrypt_invocation(&envelope, &security("wrong-caller-key")),
Err(ServiceError::Encryption)
);
let mut substituted = envelope;
substituted.request_id = "request-2".to_string();
assert_eq!(
decrypt_invocation(&substituted, &epiphany_key),
Err(ServiceError::Encryption)
);
}
#[test]
fn shared_client_transports_one_exact_encrypted_request_and_result() {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let endpoint = listener.local_addr().unwrap();
let invocation = invocation();
let expected = invocation.clone();
let security = security("epiphany-distinct-test-key");
let server = std::thread::spawn(move || {
let (mut stream, _) = listener.accept().unwrap();
let request = read_transport_frame(&mut stream, 64 * 1024).unwrap();
let envelope: CodexTransportEnvelope = rmp_serde::from_slice(&request).unwrap();
assert_eq!(decrypt_invocation(&envelope, &security).unwrap(), expected);
let response = encrypt_result(
&CodexTransportResult::refused(&expected, CodexRefusal::Policy),
&security,
)
.unwrap();
write_transport_frame(
&mut stream,
&rmp_serde::to_vec(&response).unwrap(),
64 * 1024,
)
.unwrap();
});
let client = CodexConnectorClient::new(
endpoint,
"epiphany-distinct-test-key",
64 * 1024,
Some(Duration::from_secs(1)),
)
.unwrap();
assert_eq!(
client.execute(&invocation).unwrap().disposition,
CodexTransportDisposition::Refused(CodexRefusal::Policy)
);
server.join().unwrap();
}
#[test]
#[cfg(feature = "daemon")]
fn service_refuses_shared_keys_and_isolates_caller_request_identities() {
let store = TestStore::new();
assert!(matches!(
CodexTransportService::open(
&store.path,
[
caller("epiphany-yggdrasil", "shared-key", 1),
caller("ghostlight-yggdrasil", "shared-key", 1),
],
5_000,
),
Err(ServiceError::SharedCallerKey)
));
let epiphany = invocation_for("epiphany-yggdrasil", "shared-request-id");
let ghostlight = invocation_for("ghostlight-yggdrasil", "shared-request-id");
let mut service = open_service(&store, 1);
assert!(matches!(
service
.begin(
&encrypt_invocation(&epiphany, &security("epiphany-distinct-test-key"))
.unwrap(),
1_000,
)
.unwrap(),
CodexTransportAdmission::Execute(_)
));
assert!(matches!(
service
.begin(
&encrypt_invocation(&ghostlight, &security("ghostlight-distinct-test-key"))
.unwrap(),
1_000,
)
.unwrap(),
CodexTransportAdmission::Execute(_)
));
}
#[test]
#[cfg(feature = "daemon")]
fn service_returns_exact_completed_replay_and_refuses_conflicting_replay() {
let store = TestStore::new();
let invocation = invocation();
let security = security("epiphany-distinct-test-key");
let mut service = open_service(&store, 1);
let claim = match service
.begin(&encrypt_invocation(&invocation, &security).unwrap(), 1_000)
.unwrap()
{
CodexTransportAdmission::Execute(claim) => claim,
CodexTransportAdmission::Reply(_) => panic!("first invocation must execute"),
};
let response = service
.complete(
*claim,
CodexTransportResult::transported(
&invocation,
vec![CodexTransportEvent {
sequence: 0,
payload: CodexTransportEventPayload::ToolCall {
call_id: "call-1".to_string(),
name: "read_source".to_string(),
arguments: "{}".to_string(),
},
}],
receipt(&invocation),
),
)
.unwrap();
drop(service);
let mut service = open_service(&store, 1);
let replay = match service
.begin(&encrypt_invocation(&invocation, &security).unwrap(), 1_000)
.unwrap()
{
CodexTransportAdmission::Reply(response) => response,
CodexTransportAdmission::Execute(_) => panic!("completed invocation re-executed"),
};
assert_eq!(replay, response);
let decoded = decrypt_result(&replay, &security, &invocation).unwrap();
assert!(matches!(
decoded.disposition,
CodexTransportDisposition::Transported { .. }
));
let mut changed_request = request();
changed_request.instructions.push_str(" Different cargo.");
let conflicting =
CodexTransportInvocation::new("epiphany-yggdrasil", 2_000, [7; 32], changed_request)
.unwrap();
let refusal = match service
.begin(&encrypt_invocation(&conflicting, &security).unwrap(), 1_000)
.unwrap()
{
CodexTransportAdmission::Reply(response) => response,
CodexTransportAdmission::Execute(_) => panic!("conflicting replay executed"),
};
assert!(matches!(
decrypt_result(&refusal, &security, &conflicting)
.unwrap()
.disposition,
CodexTransportDisposition::Refused(CodexRefusal::ReplayConflict)
));
}
#[test]
#[cfg(feature = "daemon")]
fn service_refuses_duplicate_inflight_and_per_caller_capacity() {
let store = TestStore::new();
let first = invocation_for("epiphany-yggdrasil", "request-1");
let second = invocation_for("epiphany-yggdrasil", "request-2");
let security = security("epiphany-distinct-test-key");
let mut service = open_service(&store, 1);
let first_envelope = encrypt_invocation(&first, &security).unwrap();
assert!(matches!(
service.begin(&first_envelope, 1_000).unwrap(),
CodexTransportAdmission::Execute(_)
));
for (invocation, expected) in [
(&first, CodexRefusal::InFlight),
(&second, CodexRefusal::Capacity),
] {
let response = match service
.begin(&encrypt_invocation(invocation, &security).unwrap(), 1_000)
.unwrap()
{
CodexTransportAdmission::Reply(response) => response,
CodexTransportAdmission::Execute(_) => panic!("refused invocation executed"),
};
assert_eq!(
decrypt_result(&response, &security, invocation)
.unwrap()
.disposition,
CodexTransportDisposition::Refused(expected)
);
}
}
#[test]
#[cfg(feature = "daemon")]
fn restart_refuses_ambiguous_claim_without_consuming_live_capacity() {
let store = TestStore::new();
let first = invocation_for("epiphany-yggdrasil", "request-1");
let second = invocation_for("epiphany-yggdrasil", "request-2");
let security = security("epiphany-distinct-test-key");
let mut service = open_service(&store, 1);
assert!(matches!(
service
.begin(&encrypt_invocation(&first, &security).unwrap(), 1_000)
.unwrap(),
CodexTransportAdmission::Execute(_)
));
drop(service);
let mut restarted = open_service(&store, 1);
let ambiguous = match restarted
.begin(&encrypt_invocation(&first, &security).unwrap(), 1_000)
.unwrap()
{
CodexTransportAdmission::Reply(response) => response,
CodexTransportAdmission::Execute(_) => panic!("ambiguous claim re-executed"),
};
assert_eq!(
decrypt_result(&ambiguous, &security, &first)
.unwrap()
.disposition,
CodexTransportDisposition::Refused(CodexRefusal::Indeterminate)
);
assert!(matches!(
restarted
.begin(&encrypt_invocation(&second, &security).unwrap(), 1_000)
.unwrap(),
CodexTransportAdmission::Execute(_)
));
drop(restarted);
assert!(matches!(
CodexTransportService::open(
&store.path,
[CodexCallerAdmission::new(
"epiphany-yggdrasil",
"rotated-connection-key",
2,
["gpt-5.4".to_string()],
1,
64 * 1024,
32_768,
)
.unwrap()],
5_000,
),
Err(ServiceError::ReplayCallerKeyMismatch)
));
}
}