Honor canonical plugin disables for shared connectors (#45755)

## Why

Disabling a connector's canonical plugin could leave its tools available when another enabled plugin contributed the same connector.

## What changed

Retain `canonical_app_id` in the remote installed-plugin cache and use ownership metadata for the current account when building connector snapshots. A disabled canonical owner now excludes its connector even when another plugin contributes it or the owner's bundle is absent from the host. Match owners by plugin name and marketplace, and ignore ownership metadata when the cache no longer matches the current authentication.

Build these snapshots through `PluginsManager` when the plugins feature is enabled; otherwise use an empty snapshot.

## Testing

Add manager coverage for combined local and canonical exclusions, marketplace matching, and authentication changes. Add an integration test showing that disabling a noncanonical contributor preserves shared calendar tools, disabling the canonical owner hides them, and clearing the exclusion restores them.

GitOrigin-RevId: ee2981d1277825fefb671dd7d1078cd7ea5c0ea5
This commit is contained in:
Matthew Zeng
2026-09-15 18:23:08 +00:00
committed by copyberry
parent 9899091441
commit af1fc2dbff
9 changed files with 275 additions and 13 deletions
+4
View File
@@ -230,6 +230,7 @@ pub struct RemoteInstalledPlugin {
pub id: String,
pub version: Option<String>,
pub name: String,
pub canonical_app_id: Option<String>,
pub installed_at: Option<DateTime<Utc>>,
pub enabled: bool,
pub install_policy: PluginInstallPolicy,
@@ -682,6 +683,8 @@ impl RemotePluginInstallPolicySource {
struct RemotePluginDirectoryItem {
id: String,
name: String,
#[serde(default)]
canonical_app_id: Option<String>,
scope: RemotePluginScope,
#[serde(default)]
discoverability: Option<RemotePluginShareDiscoverability>,
@@ -1879,6 +1882,7 @@ fn remote_installed_plugin_to_cache_entry(
id: plugin.id.clone(),
version: plugin.release.version.clone(),
name: plugin.name.clone(),
canonical_app_id: plugin.canonical_app_id.clone(),
installed_at: installed_plugin.installed_at,
enabled: installed_plugin.enabled,
install_policy: plugin.installation_policy,