Repository navigation
Connector Approvals: stop blaming core's key check on the provider or Gutenberg - #1070
Conversation
…utenberg Core validates a connector key by listing the provider's models, and the guard attributes every request to the outermost plugin on the stack. Two cases blame a plugin for what is really core's key check, so the request is blocked and the Connectors screen reports the key as invalid: - A provider whose own classes send the request (the OpenRouter provider overrides sendListModelsRequest()) is the only plugin on the stack, so it is blamed for using its own connector. The guard now resolves the plugin that registered the connector's AI Client provider and treats its frames as infrastructure; a plugin calling through the provider is still identified. - With Gutenberg 23.9 to 24.0 active, keys are validated by Gutenberg's polyfill of core's connectors.php, so Gutenberg is blamed. That file is now skipped like core's own connectors.php.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #1070 +/- ##
=============================================
+ Coverage 81.47% 81.57% +0.10%
- Complexity 3064 3077 +13
=============================================
Files 129 129
Lines 12236 12267 +31
=============================================
+ Hits 9969 10007 +38
+ Misses 2267 2260 -7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…e vendored a provider plugin and that we can look at mu-plugins and themes, not just normal plugins
What?
Closes #1069
Stops Connector Approvals from blocking core's connector key check by attributing it to the provider plugin or to Gutenberg, which makes Settings → Connectors reject valid keys.
Why?
Core validates a key by listing the provider's models, and
Caller_Identifierattributes each request to the outermost plugin on the stack. Two cases blame a plugin for what is really core's check (details and stack in #1069):sendListModelsRequest()), it is the only plugin on the stack. Providers that inherit the request from core's OpenAI-compatible base class are unaffected.connectors.php, which the skip list does not cover.#595 aimed to let core's credential checks and requests that only pass through a provider go through without approval. These are the two gaps left.
How?
Http_Guardresolves the plugin that registered the connector's AI Client provider (AiClient::defaultRegistry()->getProviderClassName(), then the class file's plugin directory) and passes its slug toCaller_Identifier::identify().Caller_Identifier::identify()/resolve()accept those slugs and skip the matching plugin frames the same way core frames are skipped. If nothing else is on the stack, the caller isnulland the request passes, the guard's existing rule for core-originated requests. A plugin calling through the provider is still identified;test_identifies_consumer_calling_through_an_infrastructure_pluginpins that.I did not use "the connector's owner is always approved": a consumer hooked inside the provider's code would be attributed to the provider and let through that way.
Skip list gains
gutenberg/lib/compat/wordpress-7.0/default-connectors.php, next to core'sconnectors.php. Gutenberg 24.1 RC no longer ships that file, so the entry becomes inert once sites upgrade.The identifier's per-request cache key now includes the slugs.
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: investigating the root cause, writing the fix, the tests and this description, under my direction.
Testing Instructions
Unit tests
The three new tests are
test_skips_infrastructure_plugin_frames_when_core_validates_a_key,test_skips_gutenberg_connectors_polyfillandtest_identifies_consumer_calling_through_an_infrastructure_plugin. Ondevelopthe first two fail; the third passes on both and guards against exempting too much. The wholeConnector_Approvalfolder passes (30 tests), and phpcs and PHPStan are clean.Manual
ai-provider-for-openrouterfrom wordpress.org) and enable Connector Approvals. Keep Gutenberg inactive.develop: "It was not possible to connect to the provider using this key." and a pendingai-provider-for-openrouterrequest. On this branch: the key saves and nothing is pending. (OpenRouter's/modelsdoes not authenticate, so any key string passes the check once the request goes out.)developrecords the pending request forgutenberg/gutenberg.php; this branch saves the key.Saving an OpenRouter key through
POST /wp/v2/settingson a clean site (AI plugin, OpenRouter provider 1.0.0, Connector Approvals on):developai-provider-for-openroutergutenberg/gutenberg.phpThe same check for
ai-provider-for-openaiis allowed on both, since its request comes from core's base class.Changelog Entry