Use server app auth requirements for remote plugin install (#27085)

## Summary
- request `includeAppsNeedingAuth=true` when installing remote plugins
- return backend-provided `app_ids_needing_auth` from the remote install
client
- use those app IDs to populate `appsNeedingAuth` without refetching
accessible apps, with fallback for older responses

## Testing
- `just fmt`
- `just test -p codex-app-server`
- `just test -p codex-core-plugins`
- real app-server install/uninstall check with Notion remote plugin
- subagent review found no blocking issues
This commit is contained in:
xl-openai authored and GitHub committed 2026-06-08 21:39:35 -07:00
1 parent dffc4bf75d
commit 14660c22d1
3 files changed
+156 -14

No files matched your search

@@ -1519,7 +1519,7 @@ impl PluginRequestProcessor {
// Cache first so a backend install cannot succeed when local materialization fails.
// If this backend call fails, the cache entry is harmless because remote installed state
// is still backend-gated.
codex_core_plugins::remote::install_remote_plugin(
let install_result = codex_core_plugins::remote::install_remote_plugin(
&remote_plugin_service_config,
auth.as_ref(),
&actual_remote_marketplace_name,
@@ -1538,7 +1538,7 @@ impl PluginRequestProcessor {
let mut plugin_metadata =
plugin_telemetry_metadata_from_root(&result.plugin_id, &result.installed_path).await;
plugin_metadata.remote_plugin_id = Some(remote_plugin_id);
plugin_metadata.remote_plugin_id = Some(remote_plugin_id.clone());
self.analytics_events_client
.track_plugin_installed(plugin_metadata);
@@ -1548,15 +1548,42 @@ impl PluginRequestProcessor {
.await;
}
let plugin_apps = load_plugin_apps(result.installed_path.as_path()).await;
let apps_needing_auth = self
.plugin_apps_needing_auth_for_install(
&config,
auth.as_ref().is_some_and(CodexAuth::is_chatgpt_auth),
&result.plugin_id.as_key(),
&plugin_apps,
)
.await;
let is_chatgpt_auth = auth.as_ref().is_some_and(CodexAuth::is_chatgpt_auth);
let apps_needing_auth =
if let Some(app_ids_needing_auth) = install_result.app_ids_needing_auth {
if app_ids_needing_auth.is_empty()
|| !config.features.apps_enabled_for_auth(is_chatgpt_auth)
{
Vec::new()
} else {
let plugin_apps = app_ids_needing_auth
.into_iter()
.map(codex_plugin::AppConnectorId)
.collect::<Vec<_>>();
let all_connectors = connectors::list_cached_all_connectors(&config)
.await
.unwrap_or_default();
connectors::connectors_for_plugin_apps(all_connectors, &plugin_apps)
.into_iter()
.map(|connector| AppSummary {
id: connector.id,
name: connector.name,
description: connector.description,
install_url: connector.install_url,
needs_auth: true,
})
.collect()
}
} else {
let plugin_apps = load_plugin_apps(result.installed_path.as_path()).await;
self.plugin_apps_needing_auth_for_install(
&config,
is_chatgpt_auth,
&result.plugin_id.as_key(),
&plugin_apps,
)
.await
};
Ok(PluginInstallResponse {
auth_policy: remote_detail.summary.auth_policy,