fix: harden plugin feature gating (#15104)

Resubmit https://github.com/openai/codex/pull/15020 with correct
content.

1. Use requirement-resolved config.features as the plugin gate.
2. Guard plugin/list, plugin/read, and related flows behind that gate.
3. Skip bad marketplace.json files instead of failing the whole list.
4. Simplify plugin state and caching.
This commit is contained in:
xl-openai
2026-03-18 17:03:37 -07:00
committed by GitHub
parent 56d0c6bf67
commit dcd5e08269
13 changed files with 337 additions and 108 deletions

View File

@@ -148,7 +148,9 @@ impl ConfigLayerStack {
})
}
/// Returns the user config layer, if any.
/// Returns the raw user config layer, if any.
///
/// This does not merge other config layers or apply any requirements.
pub fn get_user_layer(&self) -> Option<&ConfigLayerEntry> {
self.user_layer_index
.and_then(|index| self.layers.get(index))
@@ -209,6 +211,10 @@ impl ConfigLayerStack {
}
}
/// Returns the merged config-layer view.
///
/// This only merges ordinary config layers and does not apply requirements
/// such as cloud requirements.
pub fn effective_config(&self) -> TomlValue {
let mut merged = TomlValue::Table(toml::map::Map::new());
for layer in self.get_layers(
@@ -220,6 +226,9 @@ impl ConfigLayerStack {
merged
}
/// Returns field origins for the merged config-layer view.
///
/// Requirement sources are tracked separately and are not included here.
pub fn origins(&self) -> HashMap<String, ConfigLayerMetadata> {
let mut origins = HashMap::new();
let mut path = Vec::new();
@@ -234,8 +243,9 @@ impl ConfigLayerStack {
origins
}
/// Returns the highest-precedence to lowest-precedence layers, so
/// `ConfigLayerSource::SessionFlags` would be first, if present.
/// Returns config layers from highest precedence to lowest precedence.
///
/// Requirement sources are tracked separately and are not included here.
pub fn layers_high_to_low(&self) -> Vec<&ConfigLayerEntry> {
self.get_layers(
ConfigLayerStackOrdering::HighestPrecedenceFirst,
@@ -243,8 +253,9 @@ impl ConfigLayerStack {
)
}
/// Returns the highest-precedence to lowest-precedence layers, so
/// `ConfigLayerSource::SessionFlags` would be first, if present.
/// Returns config layers in the requested precedence order.
///
/// Requirement sources are tracked separately and are not included here.
pub fn get_layers(
&self,
ordering: ConfigLayerStackOrdering,