Skip to content

Move Providers from being tied to Features to being global#1038

Open
dkotter wants to merge 62 commits intodevelopfrom
feature/global-providers
Open

Move Providers from being tied to Features to being global#1038
dkotter wants to merge 62 commits intodevelopfrom
feature/global-providers

Conversation

@dkotter
Copy link
Collaborator

@dkotter dkotter commented Jan 26, 2026

Description of the Change

At the moment, the workflow in ClassifAI is to go into a Feature, choose the Provider you want for that Feature and enter in any Provider credentials from within that Feature. There's nothing wrong with this approach but it does require you to enter your credentials again for each Feature that you want to use the same Provider for (which is likely the majority of use cases).

This has been a common request (to simplify how Providers are setup) and we've also gotten quite a few recent requests around making it easier to programmatically manage credentials (for instance, setting those up as constants in wp-config.php instead of having to enter those in the UI and have those saved to your database).

This PR attempts to address both of these by introducing the concept of global Providers, while still retaining the ability to override credentials at the Feature-level if desired (and to help maintain backwards-compat).

At a high-level, this is what has been done:

  • Introduce a new Providers settings tab that renders out all Providers with their required credential fields
  • Refactor the components that render these credentials so they can be used both on this new global Providers page and within the individual Features
  • Introduce new classes that help manage Provider profiles and configs, as well as a central place to verify credentials
  • Introduce a new CredentialResolver class that will determine where to pull credentials from (either the global scope or the Feature-scope)
  • Add new methods on the Provider class that get all credentials for that Provider or a specific credential field. These all pass through a new filter (classifai_provider_credentials) making it easy for other to hook in and change those credentials
  • At the Feature-level, add a new Override toggle that allows you to use Feature-level Provider credentials. For new installs, this defaults to being off and thus all Features by default will use global credentials. For existing installs, all Features are considered to be overridden and will use the existing Feature-level credentials, though we show prompts in these situations so users can migrate to global credentials if they desire
  • Remove the unneeded Credential Reuse code as we aren't sharing credentials anymore
  • More standardization on how API requests are made, making it easier to ensure all credentials pass through our new filter and setting us up for the future where we will integrate the new WP AI Client for these requests
  • General refactoring / code cleanup to account for this new architecture. I tried to keep this to a minimum as this PR is already quite large but some of this was necessary and some felt like the right thing /right time to do

Screenshots

New Providers setting screen Feature settings screen with new override credentials toggle turned off Feature settings screen with new override credentials toggle turned on

How to test the Change

This is a fairly global change and as such, testing multiple Feature / Provider combinations is the ideal. In addition, testing Features with overridden credentials and Features with global credentials is ideal.

Changelog Entry

Added - Ability to set Providers at a global level, allowing you to easily re-use Provider credentials across all Features that need them
Added - New setting that allows you to override Provider credentials at the Feature-level. For any existing sites that have set up ClassifAI, your Features will be considered to be in an override state but you can migrate credentials to the new global scope as desired
Added - New filter, classifai_provider_credentials, that allows developers the ability to override AI credentials prior to those being used
Changed - For filters that run when API requests are made, the Feature name, not the Feature option name is now passed as an argument. If you have code that relies on that argument, updates will be needed
Removed - Credential re-use code has been removed as it is no longer needed

Credits

Props @dkotter, @fabiankaegy

Checklist:

…undation)

- ProviderProfiles: registry mapping provider IDs to vendor profiles and
  credential fields; supports grouped and ungrouped profiles.
- ProviderConfigStore: persistence for global provider configs in
  classifai_provider_configs option.
- CredentialResolver: resolves effective credentials, preferring
  feature-level overrides over global config.
…onfigs

- ProviderProfiles, ProviderConfigStore, CredentialResolver: registry,
  storage, and resolution for global provider credentials (override-aware).
- GET/POST /classifai/v1/provider-configs: list profiles and configs,
  update config per profile. Plain-string labels in ProviderProfiles to
  avoid static initializer errors.
- Providers tab: fetch provider-configs, list profiles with Configured /
  Not configured / No configuration needed. Redux: providerProfiles,
  providerConfigs, actions, selectors. Route and styles for Providers.
…ices

- Feature: merge CredentialResolver into get_settings; sanitize override.
- CredentialResolver: explicit override (true=Feature, false=global); infer from non-empty creds when unset.
- ClassifAISettings: fetch provider-configs on load.
- ProviderSettings: notices to configure in Providers tab or use Feature-level creds.
- utils: getProfileForProvider, hasFeatureLevelCredentials
- Delete CredentialReuse helper and credential-reuse/(feature_id), credential-reuse/copy REST routes.
- Remove CredentialReuseModal and its usage from ServiceSettings and EnableToggleControl.
- Remove credential-reuse SCSS and Cypress modal commands/tests.
- ProviderProfileForm with inputs per credential_fields, Save wired to POST /provider-configs
- ProviderCredentialsVerifier for OpenAI and Ollama; set authenticated and verification_error
- Status (Verified / Not configured) only when config.authenticated === true
- ProviderSettings: links to Providers tab and isProviderConfigured with global configs
…entials or an individual credential and pass that through a filter so others can change credentials if desired. Minor modifications to our CredentialResolver to only return credentials, not all Feature-Provider settings. Remove unneeded code from the Feature class
…tance and we use that to get the API key, passing through our new credential filtering. Ensure we can pass settings to our credential filtering and use those if passed instead of using the saved credentials. Allows us to filter credentials when settings are being saved.
… the Feature ID to avoid extra code duplication
@jeffpaul jeffpaul moved this from In Progress to Code Review in Open Source Practice Jan 29, 2026
@github-actions github-actions bot added the needs:refresh This requires a refreshed PR to resolve. label Jan 30, 2026
@github-actions github-actions bot removed the needs:refresh This requires a refreshed PR to resolve. label Feb 2, 2026
@peterwilsoncc
Copy link
Contributor

I'm doing some manual testing prior to the code review.

  1. Once the feature is merged, instead of prompting users to add feature level credentials to the providers tab, I think it would be better to either:
  • provide a link "migrate these credentials to global providers"
  • be opinionated and automatically migrate the credentials if the same credentials are been used in all the features
  1. Prior to the provider credentials being configured, it's possible to toggle the "override provider credentials" checkbox off and save. Using the title generation as an example, toggling the checkbox off then results in a "A valid URL was not provided." error in the editor.

override-provider-creds

  1. For feature level settings that match the global settings, I am wondering if the best approach is to remove the feature settings for the migration. We'd need to store an option indicating the migration has taken place so if the same settings are added we don't auto-migrate again.

@dkotter
Copy link
Collaborator Author

dkotter commented Feb 3, 2026

Note pausing on this temporarily and will be pulling out some individual pieces here to get those out quicker (first is done, #1043)

@github-actions github-actions bot added the needs:refresh This requires a refreshed PR to resolve. label Feb 4, 2026
@github-actions github-actions bot removed the needs:refresh This requires a refreshed PR to resolve. label Feb 4, 2026
@dkotter dkotter modified the milestones: 3.8.0, 3.9.0 Feb 4, 2026
@github-actions github-actions bot added the needs:refresh This requires a refreshed PR to resolve. label Feb 9, 2026
@github-actions github-actions bot added needs:refresh This requires a refreshed PR to resolve. and removed needs:refresh This requires a refreshed PR to resolve. labels Feb 9, 2026
@github-actions github-actions bot removed the needs:refresh This requires a refreshed PR to resolve. label Feb 10, 2026
@jeffpaul jeffpaul mentioned this pull request Feb 10, 2026
28 tasks
@dkotter dkotter removed the request for review from peterwilsoncc February 10, 2026 21:40
@github-actions github-actions bot added the needs:refresh This requires a refreshed PR to resolve. label Feb 10, 2026
@github-actions github-actions bot removed the needs:refresh This requires a refreshed PR to resolve. label Feb 10, 2026
@dkotter dkotter modified the milestones: 3.8.0, 3.9.0 Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs:code-review This requires code review.

Projects

Status: Code Review

Development

Successfully merging this pull request may close these issues.

2 participants