Files
codex/codex-rs/runtime-agent-instance/src/bootstrap.rs
T
cooper-oai 9cce575134 Share runtime authentication with model providers and catalogs (#57607)
## Why

Model catalog refreshes need to use the same registered actor and credential owner as model requests when runtime authentication is enabled.

## What changed

- Add `ProviderAuthContext` to carry credentials and optional runtime authentication into model providers and catalog clients.
- Select runtime authentication independently for inference and catalog destinations. Reject unsupported OpenAI origins while preserving provider authentication for other destinations.
- Include API organization and project selectors in runtime registration. Reuse registered runtimes across projects within an organization and replace them when the organization changes.
- Preserve transport restrictions and account bindings, and strip sensitive headers on cross-origin redirects.
- Apply the catalog timeout to authentication and fetching while allowing credential refresh and registration to finish safely.

## Testing

Add coverage for runtime-authenticated catalogs, provider isolation, resource selection, gateway authentication, cross-origin redirects, and timeout recovery that preserves registration and refreshed tokens.

GitOrigin-RevId: c14f1a02159031ea0af1f9b26ea890f8dca7d6ad
2026-10-28 00:51:29 +00:00

89 lines
2.5 KiB
Rust

//! Wire types for one-call runtime registration. Credentials are inputs, not identity claims.
use codex_utils_redacted_string::RedactedString;
use serde::Deserialize;
use serde::Serialize;
use uuid::Uuid;
#[derive(Clone, Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum AuthenticatedActorAuthorization {
Oauth {
credential: RedactedString,
},
PersonalAccessToken {
credential: RedactedString,
},
PlatformApiKey {
credential: RedactedString,
#[serde(flatten)]
selection: PlatformResourceSelection,
},
}
/// API resource selectors to authenticate, not claims about the resulting actor.
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize)]
pub struct PlatformResourceSelection {
#[serde(skip_serializing_if = "Option::is_none")]
pub organization_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub project_id: Option<String>,
}
#[derive(Clone, Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum AgentHostAuthorization {
// An installation ID is tracking metadata, not proof of device ownership.
InstallationId { installation_id: Uuid },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RuntimeRole {
Orchestrator,
Executor,
OrchestratorAndExecutor,
}
#[derive(Clone, Debug, Serialize)]
pub struct RuntimeRegistrationMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub harness: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub harness_version: Option<String>,
pub role: RuntimeRole,
}
#[derive(Clone, Debug, Serialize)]
pub struct RuntimeRegistrationRequest {
pub actor_auth: AuthenticatedActorAuthorization,
pub agent_host_auth: AgentHostAuthorization,
pub public_key: String,
pub metadata: RuntimeRegistrationMetadata,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
pub struct RuntimeRegistrationResponse {
pub runtime_agent_instance_id: String,
pub agent_host_id: String,
pub actor: ActorInfo,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ActorInfo {
Chatgpt {
user_id: String,
account_id: String,
},
Platform {
user_id: String,
organization_id: String,
project_id: Option<String>,
},
}
#[cfg(test)]
#[path = "bootstrap_tests.rs"]
mod tests;