From 9b2efe0c3a7fc17dab872b6d4121bdfe5d9acafe Mon Sep 17 00:00:00 2001 From: Abhinav Vedmala Date: Mon, 15 Jun 2026 05:30:26 +0000 Subject: [PATCH] rename Desktop distribution crate to installation --- codex-rs/Cargo.lock | 4 +- codex-rs/Cargo.toml | 4 +- codex-rs/cli/Cargo.toml | 2 +- codex-rs/cli/src/desktop_app/mac.rs | 16 +++---- codex-rs/cli/src/desktop_app/windows.rs | 4 +- codex-rs/desktop-distribution/BUILD.bazel | 6 --- .../desktop-distribution/src/unsupported.rs | 6 --- codex-rs/desktop-installation/BUILD.bazel | 6 +++ .../Cargo.toml | 4 +- .../src/lib.rs | 46 +++++++++---------- .../src/lib_tests.rs | 14 +++--- .../src/macos.rs | 17 +++---- .../desktop-installation/src/unsupported.rs | 6 +++ .../src/windows.rs | 10 ++-- 14 files changed, 73 insertions(+), 72 deletions(-) delete mode 100644 codex-rs/desktop-distribution/BUILD.bazel delete mode 100644 codex-rs/desktop-distribution/src/unsupported.rs create mode 100644 codex-rs/desktop-installation/BUILD.bazel rename codex-rs/{desktop-distribution => desktop-installation}/Cargo.toml (82%) rename codex-rs/{desktop-distribution => desktop-installation}/src/lib.rs (82%) rename codex-rs/{desktop-distribution => desktop-installation}/src/lib_tests.rs (87%) rename codex-rs/{desktop-distribution => desktop-installation}/src/macos.rs (72%) create mode 100644 codex-rs/desktop-installation/src/unsupported.rs rename codex-rs/{desktop-distribution => desktop-installation}/src/windows.rs (75%) diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index ee27df0537..3a1bec2a27 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -2291,7 +2291,7 @@ dependencies = [ "codex-config", "codex-core", "codex-core-plugins", - "codex-desktop-distribution", + "codex-desktop-installation", "codex-exec", "codex-exec-server", "codex-execpolicy", @@ -2784,7 +2784,7 @@ dependencies = [ ] [[package]] -name = "codex-desktop-distribution" +name = "codex-desktop-installation" version = "0.0.0" dependencies = [ "codex-utils-absolute-path", diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 5f389f609c..9df5bbeb21 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -33,7 +33,7 @@ members = [ "connectors", "config", "context-fragments", - "desktop-distribution", + "desktop-installation", "shell-command", "shell-escalation", "skills", @@ -166,7 +166,7 @@ codex-home = { path = "codex-home" } codex-config = { path = "config" } codex-connectors = { path = "connectors" } codex-context-fragments = { path = "context-fragments" } -codex-desktop-distribution = { path = "desktop-distribution" } +codex-desktop-installation = { path = "desktop-installation" } codex-core = { path = "core" } codex-core-api = { path = "core-api" } codex-core-plugins = { path = "core-plugins" } diff --git a/codex-rs/cli/Cargo.toml b/codex-rs/cli/Cargo.toml index c63c8b020b..9f434161fb 100644 --- a/codex-rs/cli/Cargo.toml +++ b/codex-rs/cli/Cargo.toml @@ -31,7 +31,7 @@ codex-chatgpt = { workspace = true } codex-cloud-tasks = { path = "../cloud-tasks" } codex-utils-cli = { workspace = true } codex-config = { workspace = true } -codex-desktop-distribution = { workspace = true } +codex-desktop-installation = { workspace = true } codex-core = { workspace = true } codex-core-plugins = { workspace = true } codex-home = { workspace = true } diff --git a/codex-rs/cli/src/desktop_app/mac.rs b/codex-rs/cli/src/desktop_app/mac.rs index c5437ee854..ea5fd4ee75 100644 --- a/codex-rs/cli/src/desktop_app/mac.rs +++ b/codex-rs/cli/src/desktop_app/mac.rs @@ -1,6 +1,6 @@ use anyhow::Context as _; -use codex_desktop_distribution::discover_installed_distribution; -use codex_desktop_distribution::validate_installed_distribution_at; +use codex_desktop_installation::discover_desktop_installation; +use codex_desktop_installation::validate_desktop_installation_at; use std::ffi::CString; use std::path::Path; use std::path::PathBuf; @@ -66,10 +66,10 @@ fn is_apple_silicon_mac() -> bool { } async fn find_existing_codex_app_path() -> anyhow::Result> { - let distribution = tokio::task::spawn_blocking(discover_installed_distribution) + let installation = tokio::task::spawn_blocking(discover_desktop_installation) .await .context("Desktop discovery task failed")??; - Ok(distribution.map(|distribution| distribution.app_root().to_path_buf())) + Ok(installation.map(|installation| installation.app_root().to_path_buf())) } async fn open_codex_app(app_path: &Path, workspace: &Path) -> anyhow::Result<()> { @@ -174,15 +174,15 @@ async fn install_codex_app_bundle(app_in_volume: &Path) -> anyhow::Result anyhow::Result { let candidate = app_path.clone(); - let distribution = - tokio::task::spawn_blocking(move || validate_installed_distribution_at(candidate)) + let installation = + tokio::task::spawn_blocking(move || validate_desktop_installation_at(candidate)) .await .context("Desktop validation task failed")??; let app_path_display = app_path.display(); - let distribution = distribution.with_context(|| { + let installation = installation.with_context(|| { format!("refusing to launch unverified Codex Desktop at {app_path_display}") })?; - Ok(distribution.app_root().to_path_buf()) + Ok(installation.app_root().to_path_buf()) } fn candidate_applications_dirs() -> anyhow::Result> { diff --git a/codex-rs/cli/src/desktop_app/windows.rs b/codex-rs/cli/src/desktop_app/windows.rs index c2505ebc83..05442448b8 100644 --- a/codex-rs/cli/src/desktop_app/windows.rs +++ b/codex-rs/cli/src/desktop_app/windows.rs @@ -1,5 +1,5 @@ use anyhow::Context as _; -use codex_desktop_distribution::discover_installed_distribution; +use codex_desktop_installation::discover_desktop_installation; use std::path::Path; use std::path::PathBuf; use tokio::process::Command; @@ -32,7 +32,7 @@ pub async fn run_windows_app_open_or_install( } async fn codex_app_is_installed() -> anyhow::Result { - Ok(tokio::task::spawn_blocking(discover_installed_distribution) + Ok(tokio::task::spawn_blocking(discover_desktop_installation) .await .context("Desktop discovery task failed")?? .is_some()) diff --git a/codex-rs/desktop-distribution/BUILD.bazel b/codex-rs/desktop-distribution/BUILD.bazel deleted file mode 100644 index a19bddd76a..0000000000 --- a/codex-rs/desktop-distribution/BUILD.bazel +++ /dev/null @@ -1,6 +0,0 @@ -load("//:defs.bzl", "codex_rust_crate") - -codex_rust_crate( - name = "desktop-distribution", - crate_name = "codex_desktop_distribution", -) diff --git a/codex-rs/desktop-distribution/src/unsupported.rs b/codex-rs/desktop-distribution/src/unsupported.rs deleted file mode 100644 index 42a0272138..0000000000 --- a/codex-rs/desktop-distribution/src/unsupported.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::DesktopDistributionError; -use crate::InstalledDesktop; - -pub(crate) fn discover() -> Result, DesktopDistributionError> { - Ok(None) -} diff --git a/codex-rs/desktop-installation/BUILD.bazel b/codex-rs/desktop-installation/BUILD.bazel new file mode 100644 index 0000000000..1ec2183826 --- /dev/null +++ b/codex-rs/desktop-installation/BUILD.bazel @@ -0,0 +1,6 @@ +load("//:defs.bzl", "codex_rust_crate") + +codex_rust_crate( + name = "desktop-installation", + crate_name = "codex_desktop_installation", +) diff --git a/codex-rs/desktop-distribution/Cargo.toml b/codex-rs/desktop-installation/Cargo.toml similarity index 82% rename from codex-rs/desktop-distribution/Cargo.toml rename to codex-rs/desktop-installation/Cargo.toml index 9040720cdd..a8a131d347 100644 --- a/codex-rs/desktop-distribution/Cargo.toml +++ b/codex-rs/desktop-installation/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "codex-desktop-distribution" +name = "codex-desktop-installation" version.workspace = true edition.workspace = true license.workspace = true [lib] -name = "codex_desktop_distribution" +name = "codex_desktop_installation" path = "src/lib.rs" doctest = false diff --git a/codex-rs/desktop-distribution/src/lib.rs b/codex-rs/desktop-installation/src/lib.rs similarity index 82% rename from codex-rs/desktop-distribution/src/lib.rs rename to codex-rs/desktop-installation/src/lib.rs index 87adceaa3c..98e3d0fe6a 100644 --- a/codex-rs/desktop-distribution/src/lib.rs +++ b/codex-rs/desktop-installation/src/lib.rs @@ -22,10 +22,10 @@ mod platform; const DESKTOP_RESOURCES_PATH_ENV_VAR: &str = "CODEX_DESKTOP_RESOURCES_PATH"; #[derive(Debug, thiserror::Error)] -pub enum DesktopDistributionError { +pub enum DesktopInstallationError { /// No launcher hint was provided and no installed Codex Desktop app was found. This can /// happen, for example, when Desktop was uninstalled after installing a bundled plugin. - #[error("no installed Codex Desktop distribution was found")] + #[error("no Codex Desktop installation was found")] NotFound, /// The platform app-discovery mechanism could not be queried successfully. #[error("Codex Desktop discovery failed: {0}")] @@ -52,19 +52,19 @@ impl DesktopResources { pub fn contained_file( &self, relative_path: impl AsRef, - ) -> Result { + ) -> Result { contained_path(&self.root, relative_path.as_ref(), ResourceKind::File) } pub fn contained_directory( &self, relative_path: impl AsRef, - ) -> Result { + ) -> Result { contained_path(&self.root, relative_path.as_ref(), ResourceKind::Directory) } /// Uses a resources directory supplied by the trusted Desktop launcher. - pub fn from_trusted_path(root: PathBuf) -> Result { + pub fn from_trusted_path(root: PathBuf) -> Result { let root = canonical(&root, "resources root")?; if !root.as_path().is_dir() { return Err(containment("expected the resources root to be a directory")); @@ -74,12 +74,12 @@ impl DesktopResources { } #[derive(Debug)] -pub struct InstalledDesktop { +pub struct VerifiedDesktopInstallation { app_root: AbsolutePathBuf, resources: DesktopResources, } -impl InstalledDesktop { +impl VerifiedDesktopInstallation { pub fn app_root(&self) -> &Path { self.app_root.as_path() } @@ -88,7 +88,7 @@ impl InstalledDesktop { fn from_paths( app_root: PathBuf, resources_root: PathBuf, - ) -> Result { + ) -> Result { let app_root = canonical(&app_root, "application root")?; let resources = DesktopResources::from_trusted_path(resources_root)?; if resources.root == app_root || !resources.root.as_path().starts_with(app_root.as_path()) { @@ -104,29 +104,29 @@ impl InstalledDesktop { } /// Uses resources supplied by Desktop, otherwise discovers the installed stable app. -pub fn locate_current_or_installed_resources() -> Result +pub fn locate_current_or_installed_resources() -> Result { if let Some(resources_root) = std::env::var_os(DESKTOP_RESOURCES_PATH_ENV_VAR) { return DesktopResources::from_trusted_path(PathBuf::from(resources_root)); } - discover_installed_distribution()? - .map(|distribution| distribution.resources) - .ok_or(DesktopDistributionError::NotFound) + discover_desktop_installation()? + .map(|installation| installation.resources) + .ok_or(DesktopInstallationError::NotFound) } /// Discovers an installed Desktop app without consulting the launcher resources hint. -pub fn discover_installed_distribution() --> Result, DesktopDistributionError> { +pub fn discover_desktop_installation() +-> Result, DesktopInstallationError> { platform::discover() } /// Validates a macOS Codex app bundle at a known path using the same identity and containment /// checks as installed-app discovery. Returns `Ok(None)` when the path is not a trusted Codex -/// Desktop distribution. +/// Desktop installation. #[cfg(target_os = "macos")] -pub fn validate_installed_distribution_at( +pub fn validate_desktop_installation_at( app_root: impl AsRef, -) -> Result, DesktopDistributionError> { +) -> Result, DesktopInstallationError> { platform::validate_candidate(app_root.as_ref()) } @@ -145,7 +145,7 @@ fn contained_path( root: &AbsolutePathBuf, relative_path: &Path, kind: ResourceKind, -) -> Result { +) -> Result { if relative_path.as_os_str().is_empty() || relative_path .components() @@ -162,7 +162,7 @@ fn contained_path( )); } let metadata = - fs::metadata(path.as_path()).map_err(|source| DesktopDistributionError::Filesystem { + fs::metadata(path.as_path()).map_err(|source| DesktopInstallationError::Filesystem { stage: "resource metadata", source, })?; @@ -182,14 +182,14 @@ fn contained_path( fn canonical( path: &Path, stage: &'static str, -) -> Result { +) -> Result { AbsolutePathBuf::from_absolute_path_checked(path) .and_then(|path| path.canonicalize()) - .map_err(|source| DesktopDistributionError::Filesystem { stage, source }) + .map_err(|source| DesktopInstallationError::Filesystem { stage, source }) } -fn containment(message: impl Into) -> DesktopDistributionError { - DesktopDistributionError::Containment(message.into()) +fn containment(message: impl Into) -> DesktopInstallationError { + DesktopInstallationError::Containment(message.into()) } #[cfg(test)] diff --git a/codex-rs/desktop-distribution/src/lib_tests.rs b/codex-rs/desktop-installation/src/lib_tests.rs similarity index 87% rename from codex-rs/desktop-distribution/src/lib_tests.rs rename to codex-rs/desktop-installation/src/lib_tests.rs index aa88a40415..3865fcd5b0 100644 --- a/codex-rs/desktop-distribution/src/lib_tests.rs +++ b/codex-rs/desktop-installation/src/lib_tests.rs @@ -1,10 +1,10 @@ use pretty_assertions::assert_eq; use std::fs; -use super::DesktopDistributionError; +use super::DesktopInstallationError; use super::DesktopResources; #[cfg(unix)] -use super::InstalledDesktop; +use super::VerifiedDesktopInstallation; use super::canonical; #[test] @@ -41,12 +41,12 @@ fn rejects_non_normal_and_wrong_kind_paths() { for path in ["", ".", "../resources/plugins", "/tmp"] { assert!(matches!( resources.contained_directory(path), - Err(DesktopDistributionError::Containment(_)) + Err(DesktopInstallationError::Containment(_)) )); } assert!(matches!( resources.contained_file("plugins"), - Err(DesktopDistributionError::Containment(_)) + Err(DesktopInstallationError::Containment(_)) )); } @@ -66,7 +66,7 @@ fn rejects_symlink_traversal() { assert!(matches!( resources.contained_file("plugins/hook.json"), - Err(DesktopDistributionError::Containment(_)) + Err(DesktopInstallationError::Containment(_)) )); let app_root = temp.path().join("Codex.app"); @@ -75,7 +75,7 @@ fn rejects_symlink_traversal() { .expect("create app contents"); symlink(&outside, &resources_link).expect("create resources symlink"); assert!(matches!( - InstalledDesktop::from_paths(app_root, resources_link), - Err(DesktopDistributionError::Containment(_)) + VerifiedDesktopInstallation::from_paths(app_root, resources_link), + Err(DesktopInstallationError::Containment(_)) )); } diff --git a/codex-rs/desktop-distribution/src/macos.rs b/codex-rs/desktop-installation/src/macos.rs similarity index 72% rename from codex-rs/desktop-distribution/src/macos.rs rename to codex-rs/desktop-installation/src/macos.rs index a47b35899b..f00feadb60 100644 --- a/codex-rs/desktop-distribution/src/macos.rs +++ b/codex-rs/desktop-installation/src/macos.rs @@ -2,19 +2,19 @@ use std::path::Path; use std::path::PathBuf; use std::process::Command; -use crate::DesktopDistributionError; -use crate::InstalledDesktop; +use crate::DesktopInstallationError; +use crate::VerifiedDesktopInstallation; const BUNDLE_IDENTIFIER: &str = "com.openai.codex"; const TEAM_IDENTIFIER: &str = "2DC432GLL2"; /// Asks LaunchServices for the signed stable Codex app, independent of name or location. -pub(crate) fn discover() -> Result, DesktopDistributionError> { +pub(crate) fn discover() -> Result, DesktopInstallationError> { let script = format!(r#"POSIX path of (path to application id "{BUNDLE_IDENTIFIER}")"#); let output = Command::new("/usr/bin/osascript") .args(["-e", &script]) .output() - .map_err(|error| DesktopDistributionError::Discovery(error.to_string()))?; + .map_err(|error| DesktopInstallationError::Discovery(error.to_string()))?; if !output.status.success() { return Ok(None); } @@ -24,18 +24,19 @@ pub(crate) fn discover() -> Result, DesktopDistribution pub(crate) fn validate_candidate( app_root: &Path, -) -> Result, DesktopDistributionError> { +) -> Result, DesktopInstallationError> { let resources_root = app_root.join("Contents/Resources"); if app_root.extension().is_some_and(|value| value == "app") && resources_root.is_dir() && has_openai_signature(app_root)? { - return InstalledDesktop::from_paths(app_root.to_path_buf(), resources_root).map(Some); + return VerifiedDesktopInstallation::from_paths(app_root.to_path_buf(), resources_root) + .map(Some); } Ok(None) } -fn has_openai_signature(app_root: &std::path::Path) -> Result { +fn has_openai_signature(app_root: &std::path::Path) -> Result { let requirement = format!( r#"=identifier "{BUNDLE_IDENTIFIER}" and anchor apple generic and certificate leaf[subject.OU] = "{TEAM_IDENTIFIER}""# ); @@ -43,6 +44,6 @@ fn has_openai_signature(app_root: &std::path::Path) -> Result Result, DesktopInstallationError> { + Ok(None) +} diff --git a/codex-rs/desktop-distribution/src/windows.rs b/codex-rs/desktop-installation/src/windows.rs similarity index 75% rename from codex-rs/desktop-distribution/src/windows.rs rename to codex-rs/desktop-installation/src/windows.rs index e6149aa18b..c9130c4d61 100644 --- a/codex-rs/desktop-distribution/src/windows.rs +++ b/codex-rs/desktop-installation/src/windows.rs @@ -1,13 +1,13 @@ use std::path::PathBuf; use std::process::Command; -use crate::DesktopDistributionError; -use crate::InstalledDesktop; +use crate::DesktopInstallationError; +use crate::VerifiedDesktopInstallation; const STORE_PUBLISHER_ID: &str = "2p2nqsd0c76g0"; /// Queries the signed stable MSIX identity and uses the package location as the app root. -pub(crate) fn discover() -> Result, DesktopDistributionError> { +pub(crate) fn discover() -> Result, DesktopInstallationError> { let script = format!( r#" $location = Get-AppxPackage -Name 'OpenAI.Codex' -ErrorAction SilentlyContinue | @@ -22,7 +22,7 @@ if ($location) {{ $location }} .arg("-Command") .arg(script) .output() - .map_err(|error| DesktopDistributionError::Discovery(error.to_string()))?; + .map_err(|error| DesktopInstallationError::Discovery(error.to_string()))?; if !output.status.success() { return Ok(None); } @@ -32,5 +32,5 @@ if ($location) {{ $location }} } let app_root = PathBuf::from(install_location); let resources_root = app_root.join("app/resources"); - InstalledDesktop::from_paths(app_root, resources_root).map(Some) + VerifiedDesktopInstallation::from_paths(app_root, resources_root).map(Some) }