Skip to content

chore(onboarding): Introduce type safety checks - #1120

Open
Ayush8923 wants to merge 3 commits into
mainfrom
feat/onboarding-type-safety-check
Open

chore(onboarding): Introduce type safety checks#1120
Ayush8923 wants to merge 3 commits into
mainfrom
feat/onboarding-type-safety-check

Conversation

@Ayush8923

@Ayush8923 Ayush8923 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

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 changed google'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, …). ProviderConfig now holds model + sensitive_fields, and required_fields is derived from the model, so the schema and the validation gate cannot drift. New parse_provider_credentials() is the single validate-and-coerce entry point shared by all three request models. (The models live here, not in app/models/, because models/credentials.py and models/onboarding.py already import from this module — the reverse direction would be a circular import.)

Request models

  • CredsCreate.credential: dict[str, Any]dict[Provider, ProviderCredentials]
  • CredsUpdate: providerProvider; 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.settingsdict[str, JsonValue],

  • and real return annotations replacing -> Any / bare ): across the four route modules.

  • Payloads keep extra="allow" and round-trip via model_dump(exclude_unset=True), so provider passthrough (model, temperature, Vertex's sa_key) is preserved exactly.

  • Wiki pages for platform and tenancy updated per the repo maintenance rule.

Checklist

Before submitting a pull request, please ensure that you mark these task.

  • Ran fastapi run --reload app/main.py or docker compose up in the repository root and test.
  • If you've fixed a bug or added code that is tested and has test cases.

Summary by CodeRabbit

  • New Features

    • Added provider-specific credential validation, including required-field and data-type checks.
    • Credential inputs now support validated provider schemas while preserving additional fields.
    • Improved credential masking and consistent credential payload handling.
  • Bug Fixes

    • Invalid or incomplete credentials now return clear validation errors instead of being accepted.
    • Standardized response formats for credential deletion and user operations.
  • Documentation

    • Added guidance for credential contracts, onboarding validation, provider configuration, and project settings.

@Ayush8923 Ayush8923 self-assigned this Aug 8, 2026
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d101d006-de00-48fd-9c22-1f2b70d1366e

📥 Commits

Reviewing files that changed from the base of the PR and between 8f8e62f and 0da06c2.

📒 Files selected for processing (1)
  • docs/wiki/modules/platform.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/wiki/modules/platform.md

📝 Walkthrough

Walkthrough

The 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.

Changes

Backend type safety

Layer / File(s) Summary
Provider credential schemas and validation
backend/app/core/providers.py, docs/wiki/modules/platform.md
Provider configurations now reference typed Pydantic models. Validation checks required fields and value types. Credential payloads support JSON-compatible values and extra fields.
Typed credential models and persistence
backend/app/models/credentials.py, backend/app/models/onboarding.py, backend/app/crud/credentials.py, backend/app/crud/onboarding.py, backend/app/tests/...
Credential and onboarding inputs are parsed into provider-specific models. CRUD operations persist normalized provider values and explicitly set payload fields. Tests expect model-level validation errors and HTTP 422 responses.
Route response and public model contracts
backend/app/api/routes/*.py, backend/app/models/project.py, docs/wiki/modules/tenancy.md
Routes now declare concrete APIResponse types. Credential responses use typed payloads and Message objects. Project settings use JSON-compatible values.

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
Loading

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: prajna1999, vprashrex

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements type safety for onboarding, credentials, users, and projects, but no organization endpoint changes are shown for issue #1081. Add or document the required type safety changes for the /organizations endpoints, or limit the issue and PR scope accordingly.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the PR's main change: introducing type safety checks for onboarding-related APIs.
Out of Scope Changes check ✅ Passed The code, tests, and documentation changes support the type safety objectives in issue #1081 and do not show unrelated scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/onboarding-type-safety-check

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot changed the title feat(onboarding): Type safety checks feat(onboarding): Introduce type safety checks Aug 8, 2026
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

OpenAPI changes   🔴 48 breaking changes

Caution

Downstream consumers may need an update before merging.

Breaking changes  ·  48
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

main9dd12a08 · generated by oasdiff

@codecov

codecov Bot commented Aug 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.11765% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
backend/app/core/providers.py 92.00% 4 Missing ⚠️
backend/app/models/credentials.py 90.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@Ayush8923 Ayush8923 changed the title feat(onboarding): Introduce type safety checks chore(onboarding): Introduce type safety checks Aug 8, 2026
@Ayush8923

Copy link
Copy Markdown
Collaborator Author

In this comment #1120

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
backend/app/core/providers.py (2)

135-163: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract 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 win

Replace Any in credential validation function signatures.

These signatures weaken the type-safety contract introduced by this PR. Use object for untrusted raw input. Use a specific mapping or provider-model type after validation.

  • backend/app/core/providers.py#L192-L207: Replace dict[str, Any] and Any in credential validation helper parameters with narrow raw-input types.
  • backend/app/models/onboarding.py#L93-L115: Replace _parse_credential_list(cls, value: Any) -> Any with 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 -> Any as 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 win

Extract 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

📥 Commits

Reviewing files that changed from the base of the PR and between efd2155 and 8f8e62f.

📒 Files selected for processing (14)
  • backend/app/api/routes/credentials.py
  • backend/app/api/routes/onboarding.py
  • backend/app/api/routes/project.py
  • backend/app/api/routes/users.py
  • backend/app/core/providers.py
  • backend/app/crud/credentials.py
  • backend/app/crud/onboarding.py
  • backend/app/models/credentials.py
  • backend/app/models/onboarding.py
  • backend/app/models/project.py
  • backend/app/tests/api/routes/test_creds.py
  • backend/app/tests/crud/test_credentials.py
  • docs/wiki/modules/platform.md
  • docs/wiki/modules/tenancy.md

Comment on lines 155 to 158
Provider.GOOGLE: ProviderConfig(
required_fields=[
"api_key",
],
model=GoogleCredentials,
sensitive_fields=["api_key"],
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 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.

Suggested change
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.

Comment on lines +58 to +74
@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()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 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.py

Repository: 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.py

Repository: 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.py

Repository: 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.py

Repository: 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),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Onboarding: Implement type safety checks

1 participant