feat: introduce Authentication abstraction for flexible provider auth#73
feat: introduce Authentication abstraction for flexible provider auth#73Kamilbenkirane merged 3 commits intomainfrom
Conversation
- Add auth.py with Authentication base class and APIKey implementation - Replace direct SecretStr api_key with Authentication in Client - Add PROVIDER_AUTH_CONFIG mapping provider-specific headers/prefixes - Add get_auth() method to Credentials returning Authentication objects - Allow create_client() to accept plain strings for api_key - Update tests to use auth=APIKey instead of api_key=SecretStr
PR Review: Authentication Abstraction LayerSummaryThis PR introduces a well-designed authentication abstraction that replaces the hardcoded 🚨 Critical Issue: Breaking Changes Not Fully ImplementedThe ProblemThe PR changes Affected FilesAll provider implementations across all capabilities are broken - 28+ instances found in:
Required FixAll instances of Example fix: # Before (broken):
headers = {
config.AUTH_HEADER_NAME: f"{config.AUTH_HEADER_PREFIX}{self.api_key.get_secret_value()}",
"Content-Type": ApplicationMimeType.JSON,
}
# After (correct):
headers = {
**self.auth.get_headers(),
"Content-Type": ApplicationMimeType.JSON,
}✅ Positive AspectsArchitecture & Design
Implementation Quality
🔍 Code Quality Observationssrc/celeste/auth.pyGood: Clean module, elegant field validator pattern, proper exports Minor: Line 69 imports inside function - consider caching loaded state src/celeste/credentials.pyGood: Consistent ordering, proper error handling, clear precedence Suggestion: Line 162 - 🧪 TestingCoverage: Unit tests updated correctly but integration tests will fail due to the critical bug Missing tests to consider:
🔒 Security ConsiderationsGood practices:
Consider: Adding ⚡ PerformanceNo regression - negligible overhead, connection pooling preserved, lazy loading maintained 🎯 RecommendationsBefore Merging (Required)
Nice to Have
📊 Overall Assessment
Verdict: Strong architectural foundation, but cannot be merged until all provider implementations are updated. Once fixed, this will be an excellent addition to the codebase. |
- Replace self.api_key.get_secret_value() with self.auth.get_headers() - Update all text-generation provider clients (OpenAI, Anthropic, Google, Cohere, Mistral, XAI) - Update all image-generation provider clients (OpenAI, Google, BFL, ByteDance) - Update all speech-generation provider clients (OpenAI, Google, ElevenLabs) - Update all video-generation provider clients (OpenAI, Google, ByteDance) - Update test fixtures to use auth=APIKey() instead of api_key=SecretStr()
- Add packages/providers/* to uv workspace members - Add ANN401 ignore for client.py files in ruff config - Remove noqa comments from src/celeste/client.py (now handled by config) - Update Makefile typecheck to use packages/*/*/src/ glob - Update Makefile test to run only core unit tests - Add capability argument support to make integration-test
Pull Request Review - PR #73Thank you for this well-structured PR introducing the Authentication abstraction! This is a thoughtful architectural improvement that enables flexible authentication methods. Below is my detailed review: ✅ StrengthsArchitecture & Design
Code Quality
🔴 Critical Issues1. Missing Test Coverage for New Auth Module
|
| File | Lines Added | Test Coverage |
|---|---|---|
src/celeste/auth.py |
80 | ❌ 0% |
src/celeste/credentials.py (new methods) |
38 | ❌ 0% |
| Provider clients (17 files) | ~34 | ✅ Indirectly tested |
Overall: Test coverage for new code is insufficient for a production merge.
🔒 Security Review
✅ Secure Practices
- Proper use of
SecretStrthroughout - Authentication headers correctly constructed
- No credential leakage in error messages
⚠️ Considerations
- Plain string API keys accepted for convenience (see feat: add artifacts and mime_types core modules #6 above)
- No validation of header names or prefixes (could pass empty strings)
🚀 Performance Considerations
No performance concerns identified:
- Header generation is a simple dictionary operation
- Lazy imports used appropriately
- No additional HTTP requests or blocking operations
📋 Recommendations Summary
Must-Fix Before Merge
- ✅ Add comprehensive tests for
src/celeste/auth.py - ✅ Add tests for
Credentials.get_auth()method - ✅ Document or remove unused
package_nameinPROVIDER_AUTH_CONFIG
Should Fix
- Add docstring warning about plain string security implications
- Clarify error handling strategy (
UnsupportedProviderErrorvsMissingCredentialsError) - Add comment explaining lazy import in
get_auth_class()(circular dependency prevention)
Nice to Have
- Verify Cohere's lowercase
"bearer "is intentional (add comment if so) - Restore
# noqa: ANN401if needed - Standardize provider ordering in credential fields
📝 Migration Notes for Users
The PR description excellently covers migration. One suggestion:
Add to README/CHANGELOG:
# ⚠️ BREAKING CHANGE in v0.3.0
# client.api_key is now client.auth
# Before
api_key_value = client.api_key.get_secret_value()
# After (for APIKey auth)
api_key_value = client.auth.key.get_secret_value()✨ Conclusion
This is a well-architected PR that significantly improves the flexibility and extensibility of the authentication system. The design is sound, the implementation is clean, and the changes are comprehensive.
Primary blocker: Insufficient test coverage for critical new functionality.
Recommendation: Add tests for auth.py and get_auth(), address the unused package_name issue, then this PR will be ready to merge.
Great work on this foundational improvement! 🎉
Reviewed with 🤖 Claude Code
Pull Request Review: Authentication Abstraction LayerSummaryThis PR introduces a well-architected authentication abstraction that successfully decouples authentication mechanisms from the provider clients. The implementation is clean, follows good design patterns, and maintains backward compatibility while enabling future extensibility. ✅ StrengthsArchitecture & Design
Code Quality
User Experience
🔍 Issues & Recommendations1. Missing Test Coverage for New Auth Module
|
| Area | Risk | Rationale |
|---|---|---|
| Breaking Changes | Low | Well-documented, only affects Client.api_key → Client.auth |
| Regression Risk | Medium | Missing test coverage for new code paths |
| Security | Low | Proper SecretStr usage, no new exposure vectors |
| Performance | None | No performance impact |
| Maintainability | High (Positive) | Significantly improves extensibility |
🎉 Conclusion
This is a well-designed and thoughtfully implemented feature that significantly improves Celeste's architecture. The abstraction is clean, the migration path is clear, and the code quality is high.
Main concern: Test coverage gaps for core new functionality (auth.py and get_auth()). These should be addressed before merge to prevent regressions and ensure the new abstraction works correctly across all edge cases.
Once test coverage is added, this PR will be ready to merge. Great work! 🚀
Summary
This PR introduces a flexible authentication abstraction layer that replaces the direct
api_key: SecretStrpattern with a pluggableAuthenticationprotocol. This foundational change enables support for diverse authentication methods across providers while maintaining backward compatibility.Motivation
Different AI providers require different authentication mechanisms:
Authorization: Bearer,x-api-key,x-goog-api-key, etc.)The previous approach hardcoded
api_key: SecretStrthroughout the codebase, making it impossible to support alternative auth methods without invasive changes.Changes
New:
src/celeste/auth.pyAuthentication— Abstract base class defining the auth protocol withget_headers() -> dict[str, str]APIKey— Concrete implementation supporting configurable header name and prefixregister_auth()/get_auth_class()— Registry system for plugin-based auth extensionsModified:
src/celeste/credentials.pyPROVIDER_AUTH_CONFIG— Maps each provider to its auth configuration(package_name, header, prefix)get_auth()method — Returns configuredAuthenticationobjects for providersget_credentials()now accepts plainstrin addition toSecretStrModified:
src/celeste/client.pyClient.api_key: SecretStr→Client.auth: AuthenticationModified:
src/celeste/__init__.pycreate_client()now accepts:api_key: str | SecretStr | None— Improved ergonomics (plain strings auto-convert)auth: Authentication | None— Direct auth object injection for custom auth flowsAPIKeyandAuthenticationfor public useModified:
tests/unit_tests/test_client.pyauth=APIKey(key=...)patternProvider Auth Configuration
AuthorizationBearerx-api-keyx-goog-api-keyAuthorizationbearerxi-api-keyx-keyX-API-KeyAuthorizationBearerUsage Examples
Before (hardcoded api_key)
After (flexible options)
Breaking Changes
Client.api_keyattribute renamed toClient.authSecretStrtoAuthenticationMigration: Replace
client.api_keywithclient.auth.key(forAPIKeyinstances)Test Plan