Skip to content

Conversation

@fabiankaegy
Copy link
Member

@fabiankaegy fabiankaegy commented Dec 9, 2025

Description of the Change

This pull request introduces a centralized credentials management system for all provider integrations, enabling programmatic overrides and easier integration with external secret management solutions. The changes ensure that all provider classes consistently retrieve credentials through a new helper class and apply filtering hooks, improving security and flexibility.

Centralized Credential Management:

  • Introduced a new Credentials helper class in Classifai\Helpers that centralizes credential retrieval and allows credentials to be filtered or overridden via the classifai_provider_credentials filter, supporting integration with external secret managers.

Provider Refactoring to Use Centralized Credentials:

  • Updated AWS (AmazonPolly), Azure (ComputerVision, Embeddings, OpenAI, Speech), and ElevenLabs providers to use the new credentials helper for all credential access, including authentication, API requests, and feature logic. This includes updating methods such as sanitize_settings, API request handlers, and utility methods to fetch and use filtered credentials. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23]

Security and Extensibility Improvements:

  • All credential lookups now support being overridden by external filters, paving the way for secure storage and retrieval from systems like AWS Secrets Manager, Azure Key Vault, or HashiCorp Vault, rather than relying solely on database-stored values.

Consistency and Code Simplification:

  • Refactored repeated credential access patterns across multiple providers to use a single, consistent interface, reducing code duplication and potential for errors. (All provider-related references above)

Backward Compatibility:

  • Where credentials are not filtered or overridden, the system gracefully falls back to existing settings, ensuring backward compatibility. (All provider-related references above)

Closes: #1019

Changelog Entry

Added - New Credentials management class that will filter all credentials through a new filter, classifai_provider_credentials, allowing developers to hook in and modify credentials before they are used.

Credits

Props @fabiankaegy, @dkotter

@fabiankaegy fabiankaegy requested review from a team, dkotter and jeffpaul as code owners December 9, 2025 10:26
@fabiankaegy fabiankaegy requested review from Copilot and removed request for a team, dkotter and jeffpaul December 9, 2025 10:26
@fabiankaegy fabiankaegy requested a review from dkotter December 9, 2025 10:26
@github-actions github-actions bot added this to the 3.8.0 milestone Dec 9, 2025
@github-actions github-actions bot added the needs:feedback This requires reporter feedback to better understand the request. label Dec 9, 2025
@github-actions
Copy link

github-actions bot commented Dec 9, 2025

@fabiankaegy thanks for the PR! Could you please fill out the PR template with description, changelog, and credits information so that we can properly review and merge this?

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces a centralized credential management system that enables programmatic credential overrides for all provider integrations, allowing seamless integration with external secret management services like Azure Key Vault, AWS Secrets Manager, or HashiCorp Vault.

Key Changes:

  • Added a new Credentials helper class that centralizes all credential retrieval through the classifai_provider_credentials filter hook
  • Refactored all provider classes (AWS, Azure, ElevenLabs, OpenAI, GoogleAI, Watson, xAI) to use the centralized credentials system
  • Added comprehensive documentation explaining how to integrate external secret management services

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
includes/Classifai/Helpers/Credentials.php New helper class providing centralized credential management with filtering support
includes/Classifai/Providers/Provider.php Added get_provider_credentials() helper method for provider subclasses
includes/Classifai/Providers/AWS/AmazonPolly.php Updated to use filtered credentials in authentication and API requests
includes/Classifai/Providers/Azure/ComputerVision.php Refactored to retrieve credentials through the new helper in multiple methods
includes/Classifai/Providers/Azure/Embeddings.php Updated prep_api_url() and embedding generation methods to use filtered credentials
includes/Classifai/Providers/Azure/OpenAI.php Modified authentication, API URL preparation, and all feature methods to use credentials helper
includes/Classifai/Providers/Azure/Speech.php Updated authentication and speech synthesis to use filtered credentials
includes/Classifai/Providers/ElevenLabs/ElevenLabs.php Added credential filtering to model and voice retrieval methods
includes/Classifai/Providers/ElevenLabs/TextToSpeech.php Updated speech synthesis to use get_provider_credentials()
includes/Classifai/Providers/ElevenLabs/SpeechToText.php Updated audio transcription to use filtered credentials
includes/Classifai/Providers/GoogleAI/APIRequest.php Added provider_id parameter and credential filtering in get_api_key()
includes/Classifai/Providers/GoogleAI/GeminiAPI.php Updated all API request instantiations to pass provider_id
includes/Classifai/Providers/GoogleAI/GoogleAI.php Added credential filtering to authentication method
includes/Classifai/Providers/GoogleAI/Images.php Updated image generation to pass provider_id to APIRequest
includes/Classifai/Providers/OpenAI/APIRequest.php Added provider_id parameter and credential filtering in get_api_key()
includes/Classifai/Providers/OpenAI/ChatGPT.php Updated all feature methods to pass provider_id to APIRequest
includes/Classifai/Providers/OpenAI/Embeddings.php Updated embedding generation methods to pass provider_id
includes/Classifai/Providers/OpenAI/Images.php Updated image generation to pass provider_id to APIRequest
includes/Classifai/Providers/OpenAI/Moderation.php Updated comment moderation to pass provider_id
includes/Classifai/Providers/OpenAI/OpenAI.php Added credential filtering to authentication method
includes/Classifai/Providers/OpenAI/SpeechToText.php Updated audio transcription to pass provider_id
includes/Classifai/Providers/OpenAI/TextToSpeech.php Updated speech synthesis to pass provider_id
includes/Classifai/Providers/Watson/Helpers.php Updated helper functions to use filtered credentials with fallback patterns
includes/Classifai/Providers/Watson/NLU.php Added credential filtering to authentication check
includes/Classifai/Providers/XAI/APIRequest.php Added provider_id parameter and credential filtering in get_api_key()
includes/Classifai/Providers/XAI/Grok.php Updated authentication and all feature methods to pass provider_id
wp-hooks-docs/docs/03.advanced-docs/index.md Added reference to new programmatic credentials documentation
wp-hooks-docs/docs/03.advanced-docs/09.programmatic-credentials.md Comprehensive guide with examples for integrating external secret management

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 19 to 71
class Credentials {

/**
* Get credentials for a provider.
*
* @param string $provider_id The provider ID (e.g., 'azure_openai', 'openai_chatgpt').
* @param string $feature_id The feature ID (e.g., 'feature_title_generation').
* @param array $settings The provider settings from the database.
* @return array Filtered credentials array.
*/
public static function get_credentials( string $provider_id, string $feature_id, array $settings ): array {
/**
* Filter provider credentials before making an API request.
*
* This is the primary hook for integrating external secret management
* services like Azure Key Vault, AWS Secrets Manager, or HashiCorp Vault.
*
* @since 3.7.0
* @hook classifai_provider_credentials
*
* @param array $credentials The credentials array from settings.
* @param string $provider_id The provider ID (e.g., 'azure_openai', 'openai_chatgpt').
* @param string $feature_id The feature ID making the request.
*
* @return array Filtered credentials array.
*/
return apply_filters(
'classifai_provider_credentials',
$settings,
$provider_id,
$feature_id
);
}

/**
* Get a specific credential value.
*
* @param string $provider_id The provider ID.
* @param string $feature_id The feature ID.
* @param array $settings The provider settings.
* @param string $credential_key The specific credential key (e.g., 'api_key').
* @return mixed The credential value.
*/
public static function get_credential(
string $provider_id,
string $feature_id,
array $settings,
string $credential_key
) {
$credentials = self::get_credentials( $provider_id, $feature_id, $settings );
return $credentials[ $credential_key ] ?? '';
}
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Credentials helper class lacks test coverage. Consider adding unit tests to verify:

  1. The get_credentials() method correctly applies the classifai_provider_credentials filter
  2. The get_credential() method returns the correct individual credential value
  3. Fallback behavior when credentials are not set in the filter
  4. Integration with different provider types (Azure, OpenAI, Watson, etc.)

Copilot uses AI. Check for mistakes.
@jeffpaul
Copy link
Member

jeffpaul commented Dec 9, 2025

One thing we'll want to be mindful of here is how this interacts with the work pending in #994 (and perhaps updated to use the WP AI Client instead) and whether that makes things more complex or if an alternate approach should be planned as we look to migrate to the core WPAI packages?

@fabiankaegy
Copy link
Member Author

@jeffpaul yeah, like I said, I have no idea if this is the right approach if not. This is just the thing that came to mind for me which I then let cursor help me get a scrapy PR up to showcase it :)

No worries at all if we disregard this.

@github-actions github-actions bot added the needs:refresh This requires a refreshed PR to resolve. label Jan 8, 2026
@github-actions github-actions bot added needs:code-review This requires code review. and removed needs:refresh This requires a refreshed PR to resolve. needs:feedback This requires reporter feedback to better understand the request. labels Jan 15, 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

None yet

Development

Successfully merging this pull request may close these issues.

Programmatic Credentials Support for External Secret Management

3 participants