[claude] shared dev credentials in instant-cli + auth client update#2623
[claude] shared dev credentials in instant-cli + auth client update#2623stopachka wants to merge 1 commit into
Conversation
Mirrors the dashboard's shared dev credentials feature (#2553) in instant-cli, plus a new `auth client update` command that works across providers. ## auth client add (Google web) - New `--use-shared-credentials` flag. With it, `--client-id` / `--client-secret` / `--custom-redirect-uri` may be omitted; the server fills creds in at runtime and auto-allows localhost / Expo redirects. - Interactive: after picking app-type=web, prompt "How do you want to set up credentials?" with shared as the default. - `--yes` with neither shared nor custom flags auto-defaults to shared with a clear `Using Instant's shared dev credentials.` log line. Native app types still require `--client-id`. - Mutually-exclusive validation: shared rejects --client-id / --client-secret / --custom-redirect-uri; native rejects shared. ## auth client update (new) Identifies a client by `--id` or `--name`, dispatches per-provider: - Google: rotate creds, switch shared <-> custom, update redirect. - GitHub / LinkedIn: rotate creds, update redirect. - Apple: rotate services-id / private-key-file, update team-id / key-id meta, update redirect. - Clerk: rotate publishable-key (re-derives discovery_endpoint). - Firebase: rotate project-id (re-derives discovery_endpoint). Interactive picker when --id/--name omitted (non-yes). Strict "nothing to update" error in --yes without flags. ## auth client list Shows `Mode: shared dev credentials` when applicable. JSON output passes through via the new schema field. ## Server `update-oauth-client` (dash/routes.clj) now accepts `discovery_endpoint` so Clerk / Firebase clients can be updated in place. `redirect_to` is added to the response select-keys (it was missing). `app_oauth_client` model's `update!` plumbs the new field through with the same discovery validation as create!. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR introduces shared developer credentials support for Google OAuth clients, enables switching between credential modes (shared vs. custom) in the add command, and implements a new Changes
Sequence Diagram(s)sequenceDiagram
participant User as CLI User
participant CLI as Auth Add Command
participant Server as API Server
participant DB as Database
User->>CLI: Run add with --yes (Google web)
CLI->>CLI: Detect minimal flags, app-type=web
CLI->>CLI: Auto-select shared credentials mode
CLI->>Server: POST /oauth-clients with useSharedCredentials:true
Server->>DB: Create client with use_shared_credentials=true
DB-->>Server: Client created
Server-->>CLI: Return client record
CLI->>User: Log "shared dev credentials" summary
sequenceDiagram
participant User as CLI User
participant CLI as Auth Update Command
participant UI as Interactive Picker
participant Server as API Server
participant DB as Database
User->>CLI: Run update (no --id/--name)
CLI->>UI: Prompt for client selection
UI-->>CLI: Return selected client
CLI->>CLI: Gather provider-specific inputs via prompts
alt Credential Mode Toggle
CLI->>Server: POST /oauth-clients/{id} with use_shared_credentials flag
else Custom Credentials Update
CLI->>Server: POST /oauth-clients/{id} with client_id/secret
else Discovery Endpoint Update
CLI->>Server: POST /oauth-clients/{id} with discovery_endpoint
end
Server->>Server: Validate discovery endpoint (fetch provider doc)
Server->>DB: Update client record
DB-->>Server: Success
Server-->>CLI: Return updated client
CLI->>User: Display boxed provider-labeled summary
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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. Review rate limit: 6/8 reviews remaining, refill in 14 minutes and 13 seconds.Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
server/src/instant/dash/routes.clj (1)
655-656:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse the admin-token-capable app lookup here.
auth client updateis wired withallowAdminToken: true, but this handler still goes throughreq->app-and-user!, which only accepts a user refresh token. As a result, updates authenticated with an app admin token will fail even though the neighboring OAuth client routes work with that auth mode.Suggested fix
-(defn update-oauth-client [req] - (let [{{app-id :id} :app} (req->app-and-user! :collaborator req) +(defn update-oauth-client [req] + (let [{{app-id :id} :app} (req->app-accepting-superadmin-or-ref-token! + :collaborator + :apps/write + req) id (ex/get-param! req [:params :id] uuid-util/coerce)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@server/src/instant/dash/routes.clj` around lines 655 - 656, The handler currently uses req->app-and-user! which only accepts a user refresh token; replace that call with the admin-token-capable app lookup used by neighboring OAuth client routes (e.g. req->app-and-user-or-admin! or the project’s req->app-or-admin! helper) so the route honors allowAdminToken: true for auth client update; keep the same destructuring ({ {app-id :id} :app } ...) and id parsing (ex/get-param! ...) but obtain the app via the admin-capable lookup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@client/packages/cli/src/commands/auth/client/update.ts`:
- Around line 176-183: The code drops the prompted redirect URI when rotating an
existing custom Google client because the intent created for rotation ({ kind:
'rotate', clientId, clientSecret }) omits redirect; update the intent creation
so the redirect is preserved for custom clients: when isShared is true and we
are rotating (i.e., clientId/clientSecret provided), include the redirect field
on the intent object (e.g., { kind: 'rotate', clientId, clientSecret, redirect
}) or otherwise ensure both branches produced by intent (set-custom and rotate)
carry the redirect from promptCustomRedirectUri/redirectFlag.
---
Outside diff comments:
In `@server/src/instant/dash/routes.clj`:
- Around line 655-656: The handler currently uses req->app-and-user! which only
accepts a user refresh token; replace that call with the admin-token-capable app
lookup used by neighboring OAuth client routes (e.g. req->app-and-user-or-admin!
or the project’s req->app-or-admin! helper) so the route honors allowAdminToken:
true for auth client update; keep the same destructuring ({ {app-id :id} :app }
...) and id parsing (ex/get-param! ...) but obtain the app via the admin-capable
lookup.
🪄 Autofix (Beta)
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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 68dccee3-5436-4752-8dda-a493ebfdc8ee
📒 Files selected for processing (9)
client/packages/cli/__tests__/authClientAddGoogle.test.tsclient/packages/cli/__tests__/authClientUpdate.test.tsclient/packages/cli/src/commands/auth/client/add.tsclient/packages/cli/src/commands/auth/client/list.tsclient/packages/cli/src/commands/auth/client/update.tsclient/packages/cli/src/index.tsclient/packages/cli/src/lib/oauth.tsserver/src/instant/dash/routes.cljserver/src/instant/model/app_oauth_client.clj
| const redirect = redirectFlag | ||
| ? (((yield* promptCustomRedirectUri(opts)) || undefined) as | ||
| | string | ||
| | undefined) | ||
| : undefined; | ||
| intent = isShared | ||
| ? { kind: 'set-custom', clientId, clientSecret, redirect } | ||
| : { kind: 'rotate', clientId, clientSecret }; |
There was a problem hiding this comment.
Preserve --custom-redirect-uri when rotating custom Google credentials.
For an existing custom Google client, this branch prompts for a redirect URI but then throws it away by emitting kind: 'rotate', so --custom-redirect-uri is silently ignored whenever --client-id/--client-secret are also passed.
Suggested fix
type Intent =
| {
kind: 'set-custom';
clientId: string;
clientSecret: string;
redirect?: string;
}
| { kind: 'switch-to-shared' }
- | { kind: 'rotate'; clientId: string; clientSecret: string }
+ | {
+ kind: 'rotate';
+ clientId: string;
+ clientSecret: string;
+ redirect?: string;
+ }
| { kind: 'update-redirect'; redirect: string };
@@
const redirect = redirectFlag
? (((yield* promptCustomRedirectUri(opts)) || undefined) as
| string
| undefined)
: undefined;
intent = isShared
? { kind: 'set-custom', clientId, clientSecret, redirect }
- : { kind: 'rotate', clientId, clientSecret };
+ : { kind: 'rotate', clientId, clientSecret, redirect };
@@
case 'rotate':
body.client_id = intent.clientId;
body.client_secret = intent.clientSecret;
+ if (intent.redirect) body.redirect_to = intent.redirect;
summaryLines.push(`Google Client ID: ${intent.clientId}`);
+ if (intent.redirect) {
+ summaryLines.push(`Redirect URI: ${intent.redirect}`);
+ }
break;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@client/packages/cli/src/commands/auth/client/update.ts` around lines 176 -
183, The code drops the prompted redirect URI when rotating an existing custom
Google client because the intent created for rotation ({ kind: 'rotate',
clientId, clientSecret }) omits redirect; update the intent creation so the
redirect is preserved for custom clients: when isShared is true and we are
rotating (i.e., clientId/clientSecret provided), include the redirect field on
the intent object (e.g., { kind: 'rotate', clientId, clientSecret, redirect })
or otherwise ensure both branches produced by intent (set-custom and rotate)
carry the redirect from promptCustomRedirectUri/redirectFlag.
|
View Vercel preview at instant-www-js-claude-cli-shared-dev-credentials-jsv.vercel.app. |
Mirrors the dashboard's shared dev credentials feature (#2553) in
instant-cli, plus a generalizedauth client updatethat works across providers.What's new
auth client add— Google web--use-shared-credentialsflag. With it,--client-id/--client-secret/--custom-redirect-urimay be omitted; the server fills credentials in at runtime and auto-allowslocalhost/ Expo redirects.app-type=web, prompt "How do you want to set up credentials?" withUse Instant's shared dev credentialsas the default.--yes(agent /create-instant-appUX): with no creds and no flag, auto-defaults to shared and printsUsing Instant's shared dev credentials.Native app types still require--client-id.--client-id/--client-secret/--custom-redirect-uri; native app types reject--use-shared-credentials.Boxen output (shared mode):
```
Google OAuth client created: google-web
App type: web Mode: shared dev credentials
ID:
Redirect origins enabled: http://localhost, https://localhost, exp://
Capped at 100 sign-ups. Run `instant-cli auth client update` with --client-id and --client-secret before going to production.
```
auth client update(new) — works across providersIdentifies a client by `--id` or `--name` (mirrors `auth client delete`). Per-provider dispatch:
Interactive picker when no `--id` / `--name` is given (non-`--yes`). `--yes` is strict — pass at least one update flag or get "Nothing to update".
`auth client list`
Adds `Mode: shared dev credentials` under `Client id:` when applicable. JSON output passes the field through via the schema.
Server changes
To make `update` work for Clerk / Firebase, `update-oauth-client` now accepts `discovery_endpoint`. `redirect_to` is also added to the response `select-keys` (was missing). The `app_oauth_client` model's `update!` plumbs the new field through with the same discovery validation as `create!`.
Testing
Manual smoke matrix (against a local dev server)
🤖 Generated with Claude Code