chore(onboarding): Introduce type safety checks - #1120
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe PR adds Pydantic provider credential schemas and centralized validation. Credential and onboarding workflows use normalized typed payloads. API routes declare explicit response types across credentials, onboarding, projects, and users. Tests and documentation reflect the updated contracts. ChangesBackend type safety
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant OnboardingRequest
participant parse_provider_credentials
participant onboarding_crud
participant CredentialStorage
OnboardingRequest->>parse_provider_credentials: provider credential entry
parse_provider_credentials-->>OnboardingRequest: typed provider credentials
OnboardingRequest->>onboarding_crud: normalized credential payload
onboarding_crud->>CredentialStorage: provider.value and exclude_unset payload
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
OpenAPI changes 🔴 48 breaking changesCaution Downstream consumers may need an update before merging. Breaking changes ·
|
| Method | Path | Change | |
|---|---|---|---|
| 🔴 | PATCH |
/api/v1/credentials |
request property provider was restricted to a list of enum values |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
request property provider was restricted to a list of enum values |
| 🔴 | POST |
/api/v1/onboard |
added 'propertyNames' constraint to the request property credentials/anyOf[subschema #1]/items/ |
| 🔴 | GET |
/api/v1/credentials |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
Full changelog · 82
| Method | Path | Change | |
|---|---|---|---|
| 🔴 | PATCH |
/api/v1/credentials |
request property provider was restricted to a list of enum values |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
request property provider was restricted to a list of enum values |
| 🔴 | POST |
/api/v1/onboard |
added 'propertyNames' constraint to the request property credentials/anyOf[subschema #1]/items/ |
| 🔴 | GET |
/api/v1/credentials |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | POST |
/api/v1/credentials |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | GET |
/api/v1/credentials/{org_id}/{project_id} |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new anthropic enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new elevenlabs enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new google enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new google-aistudio enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new langfuse enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new openai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new proxy enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new sarvamai enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🔴 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new webhook_secret enum value to the data/anyOf[subschema #1]/items/provider response property for the response status 200 |
| 🟢 | — |
— |
removed the schema APIResponse_Union_dict__NoneType__ |
| 🟢 | — |
— |
removed the schema Provider |
| 🟢 | — |
— |
a breaking change was detected but the version is still 0.5.0 |
| 🟢 | DELETE |
/api/v1/credentials |
added #/components/schemas/Message to the data response property anyOf list for the response status 200 |
| 🟢 | DELETE |
/api/v1/credentials |
removed subschema #1 from the data response property anyOf list for the response status 200 |
| 🟢 | PATCH |
/api/v1/credentials |
added #/components/schemas/OpenAICredentials, #/components/schemas/LangfuseCredentials, #/components/schemas/GoogleAIStudioCredentials, #/components/schemas/SarvamAICredentials, #/components/schemas/ElevenLabsCredentials, #/components/schemas/AnthropicCredentials, #/components/schemas/GoogleCredentials, #/components/schemas/WebhookSecretCredentials, #/components/schemas/ProxyCredentials to the credential request property anyOf list |
| 🟢 | PATCH |
/api/v1/credentials |
added the new anthropic enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials |
added the new elevenlabs enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials |
added the new google enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials |
added the new google-aistudio enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials |
added the new langfuse enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials |
added the new openai enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials |
added the new proxy enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials |
added the new sarvamai enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials |
added the new webhook_secret enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials |
the credential request property type was widened from object to any |
| 🟢 | POST |
/api/v1/credentials |
request property credential list-of-types was widened by adding types null to media type application/json |
| 🟢 | DELETE |
/api/v1/credentials/provider/{provider} |
added #/components/schemas/Message to the data response property anyOf list for the response status 200 |
| 🟢 | DELETE |
/api/v1/credentials/provider/{provider} |
removed subschema #1 from the data response property anyOf list for the response status 200 |
| 🟢 | DELETE |
/api/v1/credentials/{org_id}/{project_id} |
added #/components/schemas/Message to the data response property anyOf list for the response status 200 |
| 🟢 | DELETE |
/api/v1/credentials/{org_id}/{project_id} |
removed subschema #1 from the data response property anyOf list for the response status 200 |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added #/components/schemas/OpenAICredentials, #/components/schemas/LangfuseCredentials, #/components/schemas/GoogleAIStudioCredentials, #/components/schemas/SarvamAICredentials, #/components/schemas/ElevenLabsCredentials, #/components/schemas/AnthropicCredentials, #/components/schemas/GoogleCredentials, #/components/schemas/WebhookSecretCredentials, #/components/schemas/ProxyCredentials to the credential request property anyOf list |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new anthropic enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new elevenlabs enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new google enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new google-aistudio enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new langfuse enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new openai enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new proxy enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new sarvamai enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
added the new webhook_secret enum value to the request property provider |
| 🟢 | PATCH |
/api/v1/credentials/{org_id}/{project_id} |
the credential request property type was widened from object to any |
| 🟢 | DELETE |
/api/v1/credentials/{org_id}/{project_id}/provider/{provider} |
added #/components/schemas/Message to the data response property anyOf list for the response status 200 |
| 🟢 | DELETE |
/api/v1/credentials/{org_id}/{project_id}/provider/{provider} |
removed subschema #1 from the data response property anyOf list for the response status 200 |
main ↔ 9dd12a08 · generated by oasdiff
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
The breaking changes shown here are mostly due to the addition of new enums. Instead of directly saving whatever value the user sends through the API, we now validate the value against the supported enums first and then save it. @vprashrex @Prajna1999 could you please review this carefully, especially from a backward-compatibility perspective? If there are any third-party dependencies involved that we need to check carefully for compatibility, please let me know as well. If you think any changes are needed, please let me know and i will address them. |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
backend/app/core/providers.py (2)
135-163: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract repeated sensitive-field names into constants.
The
"api_key"literal is repeated across provider configurations. Define a named constant and use it in each configuration.As per coding guidelines: “Do not use magic values; extract repeated literals into constants, enums, or settings.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/app/core/providers.py` around lines 135 - 163, Define a shared constant for the repeated "api_key" sensitive-field name near PROVIDER_CONFIGS, then replace each matching literal in the ProviderConfig entries with that constant. Leave other sensitive-field values, such as "secret_key" and "webhook_secret", unchanged.Source: Coding guidelines
192-207: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReplace
Anyin credential validation function signatures.These signatures weaken the type-safety contract introduced by this PR. Use
objectfor untrusted raw input. Use a specific mapping or provider-model type after validation.
backend/app/core/providers.py#L192-L207: Replacedict[str, Any]andAnyin credential validation helper parameters with narrow raw-input types.backend/app/models/onboarding.py#L93-L115: Replace_parse_credential_list(cls, value: Any) -> Anywith narrow raw-input and return types.As per coding guidelines: “Use Python 3.11+ and provide narrow type hints for every function parameter and return value; do not use
-> Anyas a substitute for a specific annotation.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/app/core/providers.py` around lines 192 - 207, Replace broad Any annotations in validate_provider_credentials and parse_provider_credentials with narrow object or specific mapping/provider-model types appropriate for untrusted input and validated output. In backend/app/core/providers.py lines 192-207, update both credential parameters without changing validation behavior; in backend/app/models/onboarding.py lines 93-115, update _parse_credential_list’s value parameter and return type to specific narrow types, avoiding -> Any.Source: Coding guidelines
backend/app/api/routes/credentials.py (1)
167-189: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract repeated deletion-response messages into constants.
Equivalent user and superuser routes duplicate the same response literals. A future message change can produce different API responses.
backend/app/api/routes/credentials.py#L167-L189: use shared constants for provider and bulk deletion messages.backend/app/api/routes/credentials.py#L309-L333: use the same constants in the superuser routes.As per coding guidelines, extract repeated literals into constants.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/app/api/routes/credentials.py` around lines 167 - 189, Extract shared constants for the provider-credential deletion and bulk-credential deletion response messages, then use them in delete_all_credentials and the corresponding superuser routes at backend/app/api/routes/credentials.py:167-189 and backend/app/api/routes/credentials.py:309-333. Replace each duplicated literal with the appropriate constant so both route groups return identical messages.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/app/core/providers.py`:
- Around line 155-158: Update the Google ProviderConfig entry for
GoogleCredentials to include sa_key in sensitive_fields alongside api_key,
ensuring Credential.to_public and credential read responses mask the
service-account private key.
In `@backend/app/models/credentials.py`:
- Line 186: Update the credential provider migration/read path around
Credential.to_public and Provider(self.provider) so supported legacy persisted
values such as “OpenAI” are normalized to canonical Provider values before enum
validation. Add an explicit handling path for unsupported historical values that
prevents credential read endpoints from failing unexpectedly, and add regression
coverage for the legacy value. Assess and preserve backward compatibility for
the enum validation change.
- Around line 58-74: Update backend/app/models/credentials.py lines 58-74 and
92-116: remove Any from _parse_credential, credential_payloads, and
credential_payload type annotations; use object or the project’s JSON-input
alias for raw validator input, type parse_provider_credentials input as
CredentialPayload, and model credential output as CredentialPayload | None
rather than dict[str, Any].
---
Nitpick comments:
In `@backend/app/api/routes/credentials.py`:
- Around line 167-189: Extract shared constants for the provider-credential
deletion and bulk-credential deletion response messages, then use them in
delete_all_credentials and the corresponding superuser routes at
backend/app/api/routes/credentials.py:167-189 and
backend/app/api/routes/credentials.py:309-333. Replace each duplicated literal
with the appropriate constant so both route groups return identical messages.
In `@backend/app/core/providers.py`:
- Around line 135-163: Define a shared constant for the repeated "api_key"
sensitive-field name near PROVIDER_CONFIGS, then replace each matching literal
in the ProviderConfig entries with that constant. Leave other sensitive-field
values, such as "secret_key" and "webhook_secret", unchanged.
- Around line 192-207: Replace broad Any annotations in
validate_provider_credentials and parse_provider_credentials with narrow object
or specific mapping/provider-model types appropriate for untrusted input and
validated output. In backend/app/core/providers.py lines 192-207, update both
credential parameters without changing validation behavior; in
backend/app/models/onboarding.py lines 93-115, update _parse_credential_list’s
value parameter and return type to specific narrow types, avoiding -> Any.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d3c4ff48-f7b6-4ba8-bdce-c8f3ddb2c44f
📒 Files selected for processing (14)
backend/app/api/routes/credentials.pybackend/app/api/routes/onboarding.pybackend/app/api/routes/project.pybackend/app/api/routes/users.pybackend/app/core/providers.pybackend/app/crud/credentials.pybackend/app/crud/onboarding.pybackend/app/models/credentials.pybackend/app/models/onboarding.pybackend/app/models/project.pybackend/app/tests/api/routes/test_creds.pybackend/app/tests/crud/test_credentials.pydocs/wiki/modules/platform.mddocs/wiki/modules/tenancy.md
| Provider.GOOGLE: ProviderConfig( | ||
| required_fields=[ | ||
| "api_key", | ||
| ], | ||
| model=GoogleCredentials, | ||
| sensitive_fields=["api_key"], | ||
| ), |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Mask GoogleCredentials.sa_key in API responses.
sa_key can contain a service-account private key. mask_credential_fields only masks configured fields. Credential.to_public and credential read routes can therefore return this secret.
Proposed fix
Provider.GOOGLE: ProviderConfig(
model=GoogleCredentials,
- sensitive_fields=["api_key"],
+ sensitive_fields=["api_key", "sa_key"],
),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Provider.GOOGLE: ProviderConfig( | |
| required_fields=[ | |
| "api_key", | |
| ], | |
| model=GoogleCredentials, | |
| sensitive_fields=["api_key"], | |
| ), | |
| Provider.GOOGLE: ProviderConfig( | |
| model=GoogleCredentials, | |
| sensitive_fields=["api_key", "sa_key"], | |
| ), |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@backend/app/core/providers.py` around lines 155 - 158, Update the Google
ProviderConfig entry for GoogleCredentials to include sa_key in sensitive_fields
alongside api_key, ensuring Credential.to_public and credential read responses
mask the service-account private key.
| @field_validator("credential", mode="before") | ||
| @classmethod | ||
| def _parse_credential(cls, value: Any) -> Any: | ||
| if not isinstance(value, dict): | ||
| return value | ||
|
|
||
| return { | ||
| provider: parse_provider_credentials(provider, payload) | ||
| for provider, payload in value.items() | ||
| } | ||
|
|
||
| def credential_payloads(self) -> dict[str, dict[str, Any]]: | ||
| """Provider name -> credential dict, exactly as submitted.""" | ||
| return { | ||
| provider.value: payload.model_dump(exclude_unset=True) | ||
| for provider, payload in (self.credential or {}).items() | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 5 \
'CredentialPayload|ProviderCredentials|def _parse_credential|def credential_payload' \
backend/app/core/providers.py backend/app/models/credentials.pyRepository: ProjectTech4DevAI/kaapi-backend
Length of output: 12912
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- provider credential aliases ---\n'
sed -n '1,130p' backend/app/core/providers.py
printf '\n--- parse/mask implementations (relevant lines) ---\n'
sed -n '180,265p' backend/app/core/providers.py
printf '\n--- credentials model relevant lines ---\n'
sed -n '1,125p' backend/app/models/credentials.py
printf '\n--- imports including Union/TypeAlias/TypedDict availability ---\n'
sed -n '1,20p' backend/app/core/providers.py
sed -n '1,25p' backend/app/models/credentials.pyRepository: ProjectTech4DevAI/kaapi-backend
Length of output: 260
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- provider credential aliases ---'
sed -n '1,130p' backend/app/core/providers.py
printf '%s\n' ''
printf '%s\n' '--- parse/mask implementations (relevant lines) ---'
sed -n '180,265p' backend/app/core/providers.py
printf '%s\n' ''
printf '%s\n' '--- credentials model relevant lines ---'
sed -n '1,125p' backend/app/models/credentials.py
printf '%s\n' ''
printf '%s\n' '--- imports including Union/TypeAlias/TypedDict availability ---'
sed -n '1,20p' backend/app/core/providers.py
sed -n '1,25p' backend/app/models/credentials.pyRepository: ProjectTech4DevAI/kaapi-backend
Length of output: 12368
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- parse_provider_credentials implementation continuation ---'
python3 - <<'PY'
from pathlib import Path
lines = Path('backend/app/core/providers.py').read_text().splitlines()
for i in range(194, 225):
print(f'{i:4}: {lines[i-1]}')
PY
printf '%s\n' ''
printf '%s\n' '--- credential model imports and relevant sections ---'
python3 - <<'PY'
from pathlib import Path
lines = Path('backend/app/models/credentials.py').read_text().splitlines()
for start,end in [(1,20),(44,80),(90,120),(192,206)]:
print(f'--- lines {start}-{end} ---')
for i in range(start,end+1):
print(f'{i:4}: {lines[i-1]}')
PY
printf '%s\n' ''
printf '%s\n' '--- any annotations using raw json input type aliases ---'
rg -n 'JsonInput|Raw.*Json|AnyDict|object\)$|JsonValue' backend/app/core/providers.py backend/app/models/credentials.pyRepository: ProjectTech4DevAI/kaapi-backend
Length of output: 5446
Remove Any from credential validation helpers and modeled outputs.
_parse_credential, credential_payloads, and credential_payload still use Any at request-to-persistence boundaries, so type narrowing is lost. Use object for raw validator input or a JSON-input alias, type parse_provider_credentials input as CredentialPayload, and return the credential output via CredentialPayload | None instead of dict[str, Any].
📍 Affects 1 file
backend/app/models/credentials.py#L58-L74(this comment)backend/app/models/credentials.py#L92-L116
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@backend/app/models/credentials.py` around lines 58 - 74, Update
backend/app/models/credentials.py lines 58-74 and 92-116: remove Any from
_parse_credential, credential_payloads, and credential_payload type annotations;
use object or the project’s JSON-input alias for raw validator input, type
parse_provider_credentials input as CredentialPayload, and model credential
output as CredentialPayload | None rather than dict[str, Any].
Source: Coding guidelines
| project_id=self.project_id, | ||
| is_active=self.is_active, | ||
| provider=self.provider, | ||
| provider=Provider(self.provider), |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Migrate persisted provider values before enforcing Provider.
Historical Credential.provider values were stored as unrestricted strings. Provider(self.provider) raises ValueError for non-canonical or unsupported values. Credential read endpoints call to_public, so affected records return a server error.
Normalize supported legacy values in a migration. Define an explicit handling path for unsupported historical values. Add regression coverage for a legacy value such as "OpenAI".
As per PR objectives, assess backward compatibility for enum validation changes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@backend/app/models/credentials.py` at line 186, Update the credential
provider migration/read path around Credential.to_public and
Provider(self.provider) so supported legacy persisted values such as “OpenAI”
are normalized to canonical Provider values before enum validation. Add an
explicit handling path for unsupported historical values that prevents
credential read endpoints from failing unexpectedly, and add regression coverage
for the legacy value. Assess and preserve backward compatibility for the enum
validation change.
Issue
Closes #1081
Summary
Endpoints covered:
/onboard,/credentials,/users,/organizations,/projects.the breaking-change gate added in API Contract: Automate Schema Updates #892 can only diff what the schema encodes. Wherever a request/response body was typed
dict[str, Any], OpenAPI emitted an opaque object and the gate waved changes through — Model Config: completion_type array + CRUD endpoints + Default Gemini Provider to Vertex + Other enum changes #890 changedgoogle's required credential fields and the diff said nothing, because the field was identical (dict[str, Any]) before and after. Typing the payloads makes that class of change visible.core/providers.py— one Pydantic model per provider (OpenAICredentials,LangfuseCredentials,GoogleCredentials, …).ProviderConfignow holdsmodel+sensitive_fields, andrequired_fieldsis derived from the model, so the schema and the validation gate cannot drift. Newparse_provider_credentials()is the single validate-and-coerce entry point shared by all three request models. (The models live here, not inapp/models/, becausemodels/credentials.pyandmodels/onboarding.pyalready import from this module — the reverse direction would be a circular import.)Request models
CredsCreate.credential:dict[str, Any]→dict[Provider, ProviderCredentials]CredsUpdate:provider→Provider;credential→ the provider union. The nested-vs-flat unwrap moved out of CRUD into the model.OnboardingRequest.credentials:list[dict[str, Any]]→list[dict[Provider, ProviderCredentials]]Responses —
APIResponse[dict]→APIResponse[Message],APIResponse[dict | None]→APIResponse[CredentialPayload | None],ProjectPublic.settings→dict[str, JsonValue],and real return annotations replacing
-> Any/ bare):across the four route modules.Payloads keep
extra="allow"and round-trip viamodel_dump(exclude_unset=True), so provider passthrough (model,temperature, Vertex'ssa_key) is preserved exactly.Wiki pages for
platformandtenancyupdated per the repo maintenance rule.Checklist
Before submitting a pull request, please ensure that you mark these task.
fastapi run --reload app/main.pyordocker compose upin the repository root and test.Summary by CodeRabbit
New Features
Bug Fixes
Documentation