From 2967900d810e3f304999e6c51f5a76088759eee1 Mon Sep 17 00:00:00 2001 From: viyatb-oai Date: Thu, 16 Apr 2026 17:37:15 -0700 Subject: [PATCH] fix: deprecate use_legacy_landlock feature flag (#17971) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - mark `features.use_legacy_landlock` as a deprecated feature flag - emit a startup deprecation notice when the flag is configured - add feature- and core-level regression coverage for the notice Screenshot 2026-04-15 at 11 14 00 PM --------- Co-authored-by: Codex --- .../core/tests/suite/deprecation_notice.rs | 42 +++++++++++++++++++ codex-rs/features/src/lib.rs | 21 +++++++++- codex-rs/features/src/tests.rs | 26 +++++++++++- 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/codex-rs/core/tests/suite/deprecation_notice.rs b/codex-rs/core/tests/suite/deprecation_notice.rs index 26a56c86e..dc7280ea3 100644 --- a/codex-rs/core/tests/suite/deprecation_notice.rs +++ b/codex-rs/core/tests/suite/deprecation_notice.rs @@ -161,3 +161,45 @@ async fn emits_deprecation_notice_for_web_search_feature_flag_values() -> anyhow Ok(()) } + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn emits_deprecation_notice_for_use_legacy_landlock() -> anyhow::Result<()> { + skip_if_no_network!(Ok(())); + + let server = start_mock_server().await; + + let mut builder = test_codex().with_config(|config| { + let mut entries = BTreeMap::new(); + entries.insert("use_legacy_landlock".to_string(), true); + let mut features = config.features.get().clone(); + features.apply_map(&entries); + config + .features + .set(features) + .expect("test config should allow managed feature map updates"); + }); + + let TestCodex { codex, .. } = builder.build(&server).await?; + + let notice = wait_for_event_match(&codex, |event| match event { + EventMsg::DeprecationNotice(ev) + if ev.summary.contains("[features].use_legacy_landlock") => + { + Some(ev.clone()) + } + _ => None, + }) + .await; + + let DeprecationNoticeEvent { summary, details } = notice; + assert_eq!( + summary, + "`[features].use_legacy_landlock` is deprecated and will be removed soon.".to_string(), + ); + assert_eq!( + details.as_deref(), + Some("Remove this setting to stop opting into the legacy Linux sandbox behavior."), + ); + + Ok(()) +} diff --git a/codex-rs/features/src/lib.rs b/codex-rs/features/src/lib.rs index a2e656be4..586c36685 100644 --- a/codex-rs/features/src/lib.rs +++ b/codex-rs/features/src/lib.rs @@ -371,6 +371,12 @@ impl Features { "image_detail_original" => { continue; } + "use_legacy_landlock" => { + self.record_legacy_usage_force( + "features.use_legacy_landlock", + Feature::UseLegacyLandlock, + ); + } _ => {} } match feature_for_key(k) { @@ -456,6 +462,19 @@ fn legacy_usage_notice(alias: &str, feature: Feature) -> (String, Option format!("`{label}` is deprecated because web search is enabled by default."); (summary, Some(web_search_details().to_string())) } + Feature::UseLegacyLandlock => { + let label = match alias { + "features.use_legacy_landlock" | "use_legacy_landlock" => { + "[features].use_legacy_landlock" + } + _ => alias, + }; + let summary = format!("`{label}` is deprecated and will be removed soon."); + let details = + "Remove this setting to stop opting into the legacy Linux sandbox behavior." + .to_string(); + (summary, Some(details)) + } _ => { let label = if alias.contains('.') || alias.starts_with('[') { alias.to_string() @@ -728,7 +747,7 @@ pub const FEATURES: &[FeatureSpec] = &[ FeatureSpec { id: Feature::UseLegacyLandlock, key: "use_legacy_landlock", - stage: Stage::Stable, + stage: Stage::Deprecated, default_enabled: false, }, FeatureSpec { diff --git a/codex-rs/features/src/tests.rs b/codex-rs/features/src/tests.rs index d2f73ceda..fc81c7308 100644 --- a/codex-rs/features/src/tests.rs +++ b/codex-rs/features/src/tests.rs @@ -42,8 +42,8 @@ fn default_enabled_features_are_stable() { } #[test] -fn use_legacy_landlock_is_stable_and_disabled_by_default() { - assert_eq!(Feature::UseLegacyLandlock.stage(), Stage::Stable); +fn use_legacy_landlock_is_deprecated_and_disabled_by_default() { + assert_eq!(Feature::UseLegacyLandlock.stage(), Stage::Deprecated); assert_eq!(Feature::UseLegacyLandlock.default_enabled(), false); } @@ -166,6 +166,28 @@ fn image_generation_is_stable_and_enabled_by_default() { assert_eq!(Feature::ImageGeneration.default_enabled(), true); } +#[test] +fn use_legacy_landlock_config_records_deprecation_notice() { + let mut entries = BTreeMap::new(); + entries.insert("use_legacy_landlock".to_string(), true); + + let mut features = Features::with_defaults(); + features.apply_map(&entries); + + let usages = features.legacy_feature_usages().collect::>(); + assert_eq!(usages.len(), 1); + assert_eq!(usages[0].alias, "features.use_legacy_landlock"); + assert_eq!(usages[0].feature, Feature::UseLegacyLandlock); + assert_eq!( + usages[0].summary, + "`[features].use_legacy_landlock` is deprecated and will be removed soon." + ); + assert_eq!( + usages[0].details.as_deref(), + Some("Remove this setting to stop opting into the legacy Linux sandbox behavior.") + ); +} + #[test] fn image_detail_original_is_a_removed_feature_key() { assert_eq!(