feat(credentials): add v2 credential lifecycle APIs - #6664
feat(credentials): add v2 credential lifecycle APIs#6664TheodoreSpeaks wants to merge 23 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryHigh Risk Overview OAuth browser flows no longer rely on mutable query targets alone. Connection intents are created through A minor docs fix removes a stray blank line in the LogRocket integration output table. Reviewed by Cursor Bugbot for commit 7b74299. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThe PR adds the complete v2 credential lifecycle, including provider discovery, service-account creation, OAuth connection drafts, reconnection, listing, and deletion. The latest follow-up correctly allows renamed reconnect targets to retry, but the retained draft presentation can make the resulting audit event identify the credential by its old name.
Confidence Score: 4/5The PR should not merge until reconnect audit events use the credential’s current display name after an active draft survives a rename. Credential-ID-only reconnect retries preserve the original draft display name, and reconnect completion writes that stale value into the audit resource name and description. Files Needing Attention: apps/sim/lib/credentials/connect-draft.ts and apps/sim/lib/credentials/draft-hooks.ts
|
| Filename | Overview |
|---|---|
| apps/sim/lib/credentials/connect-draft.ts | Makes OAuth draft conflict refreshes immutable by target, but reconnect refreshes retain a stale display name that later appears in audit data. |
| apps/sim/lib/credentials/application/save-credential-draft.ts | Correctly treats credential ID alone as reconnect intent while retaining display-name identity for new connections. |
| apps/sim/lib/credentials/draft-hooks.ts | Reconnects update only account binding, but their audit event consumes the potentially stale draft display name. |
| apps/sim/lib/credentials/draft-processor.ts | Processes exact drafts with authenticated user and provider constraints, preventing foreign-user draft completion. |
| apps/sim/app/api/auth/instagram/authorize/route.ts | Carries supplied draft IDs into OAuth completion; downstream exact-draft processing enforces session-user and provider ownership. |
| apps/sim/app/api/v2/credentials/connections/route.ts | Exposes authenticated OAuth connection and reconnection draft creation through the v2 response contract. |
Reviews (15): Last reviewed commit: "fix(credentials): allow renamed reconnec..." | Re-trigger Greptile
|
@cursor review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit e4b09dc. Configure here.
|
@cursor review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 7fcf26f. Configure here.
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 036bfa0. Configure here.
…-api # Conflicts: # scripts/check-api-validation-contracts.ts
|
@cursor review |
|
@cursor review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2cb08cd. Configure here.
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 147b161. Configure here.
|
@cursor review |

Problem:
The V2 API could list stored credentials, but clients could not discover the complete set of credential methods, create service-account credentials, start or reconnect OAuth credentials safely, or disconnect credentials. OAuth still has to cross into an authenticated browser session, and the old browser entrypoint accepted mutable target parameters instead of an API-created connection intent.
Solution:
/api/v2/credentials./oauth/credential-connected.{ data }/{ data, nextCursor }/{ error }envelopes.API shapes:
GET /api/v2/credentials?workspaceId={workspaceId}{ "data": [ { "id": "credential-id", "type": "oauth", "displayName": "Work Gmail", "description": null, "providerId": "google-email", "accountId": "provider-account-id", "hasServiceAccountKey": false, "role": "admin", "createdAt": "2026-08-13T18:00:00.000Z", "updatedAt": "2026-08-13T18:00:00.000Z" } ], "nextCursor": null }GET /api/v2/credentials/providers?workspaceId={workspaceId}OAuth entry:
{ "type": "oauth", "serviceId": "salesforce", "name": "Salesforce", "description": "Connect to Salesforce CRM data and operations.", "providerFamily": "salesforce", "available": true, "supportsReconnect": true, "authorizationOptions": [ { "providerId": "salesforce", "label": "Production" }, { "providerId": "salesforce-sandbox", "label": "Sandbox" } ] }Service-account entry:
{ "type": "service_account", "serviceId": "zoom-service-account", "providerId": "zoom-service-account", "name": "Zoom server-to-server app", "description": "Connect Zoom with a server-to-server app.", "providerFamily": "zoom", "available": true, "docsUrl": "https://docs.sim.ai/integrations/zoom-service-account", "requiresClientGeneratedCredentialId": false, "fields": [ { "id": "clientId", "label": "Client ID", "placeholder": "Paste the client ID", "required": true, "secret": false, "multiline": false }, { "id": "clientSecret", "label": "Client secret", "placeholder": "Paste the client secret", "required": true, "secret": true, "multiline": false }, { "id": "orgId", "label": "Account ID", "placeholder": "Paste the account ID", "required": true, "secret": false, "multiline": false } ] }The endpoint returns
{ "data": [oauthEntry, serviceAccountEntry], "nextCursor": null }.POST /api/v2/credentialsCreates a service-account credential.
displayNameis optional because providers may derive it from the verified account identity.{ "workspaceId": "workspace-id", "type": "service_account", "providerId": "zoom-service-account", "displayName": "Zoom automation", "clientId": "YOUR_CLIENT_ID", "clientSecret": "YOUR_CLIENT_SECRET", "orgId": "YOUR_ACCOUNT_ID" }Returns
201 { "data": credential }for a new credential or200 { "data": credential }for an accepted replay. Secret fields are write-only and never returned.POST /api/v2/credentials/connectionsNew OAuth credential:
{ "workspaceId": "workspace-id", "providerId": "google-email", "displayName": "Work Gmail" }Reconnect an existing OAuth credential:
{ "workspaceId": "workspace-id", "credentialId": "credential-id" }{ "data": { "authorizationUrl": "https://www.sim.ai/api/auth/oauth2/authorize?draftId=draft-id", "expiresAt": "2026-08-13T18:30:00.000Z" } }This write requires a personal API key because the draft is bound to the human who must sign in in the browser. Workspace API keys can still list credentials and providers.
DELETE /api/v2/credentials/{credentialId}?workspaceId={workspaceId}{ "data": { "id": "credential-id", "deleted": true } }Validation:
bun run lintbunx turbo run type-check --filter=sim --filter=@sim/authbun run check:audits: 26 passedbun run check:api-validation:strictbun run check:openapi