[codex] Centralize plugin auth capability filtering (#27902)

## Summary

This is the first step in making plugin auth routing consistent. The
rule should not live as one-off checks in every place that loads or
displays plugin capabilities.

This PR introduces a small resolver for the auth-level policy: given a
plugin's declared apps, MCP servers, current auth mode, and active
state, return the capabilities that are actually usable in that context.

## Why

Product rule:
- SiWC auth can use app connectors, so app declarations stay available.
- API-key/direct auth cannot use app connectors, so app declarations are
removed.
- When an active plugin has both an app and an MCP server with the same
name, the app route wins for Codex-backed auth and the conflicting MCP
server is hidden.

Putting that rule in `capabilities.rs` gives the rest of the stack one
place to ask instead of duplicating auth checks in loader, manager,
marketplace, and details code.

## Validation

- `cargo fmt`
- `cargo test -p codex-core-plugins`
This commit is contained in:
felixxia-oai
2026-06-16 01:13:27 +01:00
committed by GitHub
Unverified
parent 8aac63f477
commit 7e0dce91df
5 changed files with 151 additions and 26 deletions
+8 -15
View File
@@ -1,5 +1,6 @@
use super::PluginLoadOutcome;
use crate::OPENAI_CURATED_MARKETPLACE_NAME;
use crate::app_mcp_routing::apply_app_mcp_routing_policy;
use crate::installed_marketplaces::installed_marketplace_roots_from_layer_stack;
use crate::loader::PluginHookLoadOutcome;
use crate::loader::configured_curated_plugin_ids_from_codex_home;
@@ -210,23 +211,15 @@ fn project_plugin_load_outcome_for_auth(
outcome: PluginLoadOutcome,
auth_mode: Option<AuthMode>,
) -> PluginLoadOutcome {
let apps_route_available = auth_mode.is_some_and(AuthMode::uses_codex_backend);
let mut plugins = outcome.plugins().to_vec();
for plugin in &mut plugins {
if apps_route_available {
if plugin.is_active() && !plugin.apps.is_empty() {
let app_declaration_names = plugin
.apps
.iter()
.map(|app| app.name.as_str())
.collect::<HashSet<_>>();
plugin
.mcp_servers
.retain(|name, _| !app_declaration_names.contains(name.as_str()));
}
} else {
plugin.apps.clear();
}
let plugin_active = plugin.is_active();
apply_app_mcp_routing_policy(
&mut plugin.apps,
&mut plugin.mcp_servers,
auth_mode,
plugin_active,
);
}
PluginLoadOutcome::from_plugins(plugins)
}