Skip to content

stack-cli: support self-hosted URLs and tighten CLI auth polling#1419

Merged
mantrakp04 merged 5 commits intodevfrom
cli/self-host-urls-and-poll-hardening
May 8, 2026
Merged

stack-cli: support self-hosted URLs and tighten CLI auth polling#1419
mantrakp04 merged 5 commits intodevfrom
cli/self-host-urls-and-poll-hardening

Conversation

@mantrakp04
Copy link
Copy Markdown
Collaborator

@mantrakp04 mantrakp04 commented May 6, 2026

Summary

  • Self-hosted CLI: read STACK_API_URL / STACK_DASHBOARD_URL from env in stack-cli so the published CLI can talk to self-hosted Stack Auth installs without a custom build. The existing STACK_CLI_PUBLISHABLE_CLIENT_KEY override is kept as-is.
  • Docker example: surface the three CLI-relevant vars in docker/server/.env.example so self-host operators see them.
  • Tighter polling-code TTL: default 2h -> 2min, max 24h -> 15min for the CLI auth polling code. The code is only valid while a user is actively waiting in stack login, so a tight window limits the blast radius of a leaked code.
  • Raw-SQL poll handler: convert apps/backend/src/app/api/latest/auth/cli/poll/route.tsx from prisma.cliAuthAttempt.* to raw SQL targeted at the tenancy source-of-truth schema, matching the pattern already used by the initiate handler in apps/backend/src/app/api/latest/auth/cli/route.tsx.

Test plan

  • pnpm typecheck
  • pnpm lint
  • pnpm test run (focus on CLI-auth tests if any)
  • Manual: stack login against a local backend
    • polling code now expires after ~2 minutes by default
    • waiting / success / used / expired branches still return correct status codes and bodies
  • Manual: published stack-cli against a self-hosted backend with STACK_API_URL / STACK_DASHBOARD_URL set, end-to-end login

Made with Cursor

Summary by CodeRabbit

  • Improvements

    • More robust CLI authentication polling with atomic database updates to prevent races; returns explicit statuses (waiting/expired/used/success) and provides the refresh token on success.
  • Changes

    • Default CLI auth token TTL reduced to 2 minutes and capped at 15 minutes.
    • Anonymous refresh token is considered present only when not null; null expiry is treated as not-expired.

- Read STACK_API_URL / STACK_DASHBOARD_URL from env in stack-cli so
  the published CLI can talk to self-hosted Stack Auth installs
  without a custom build. Surface the vars (and the existing
  STACK_CLI_PUBLISHABLE_CLIENT_KEY) in docker/server/.env.example.
- Reduce the CLI auth polling-code TTL: default 2h -> 2min, max 24h
  -> 15min. The code is only used while a user is actively waiting
  in `stack login`, so a tight window limits the value of a leak.
- Convert the CLI auth poll handler to raw SQL against the tenancy
  source-of-truth schema, matching the pattern already used by the
  initiate handler.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI review requested due to automatic review settings May 6, 2026 21:34
@vercel
Copy link
Copy Markdown

vercel Bot commented May 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stack-auth-hosted-components Ready Ready Preview, Comment May 8, 2026 5:34pm
stack-auth-mcp Error Error May 8, 2026 5:34pm
stack-backend Ready Ready Preview, Comment May 8, 2026 5:34pm
stack-dashboard Ready Ready Preview, Comment May 8, 2026 5:34pm
stack-demo Ready Ready Preview, Comment May 8, 2026 5:34pm
stack-docs Ready Ready Preview, Comment May 8, 2026 5:34pm
stack-preview-backend Ready Ready Preview, Comment May 8, 2026 5:34pm
stack-preview-dashboard Ready Ready Preview, Comment May 8, 2026 5:34pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Moves CLI auth polling from Prisma model methods to schema-qualified raw SQL, changes CLI request timing defaults to 2 minutes (max 15 minutes), refines anon refresh token presence and expiry checks, and replaces the ORM update with an atomic SQL UPDATE that returns the refresh token.

Changes

CLI Auth Endpoints Refactor

Layer / File(s) Summary
Request Schema
apps/backend/src/app/api/latest/auth/cli/route.tsx
expires_in_millis default changed to 2 minutes and capped at 15 minutes.
Token Presence & Expiry
apps/backend/src/app/api/latest/auth/cli/route.tsx
anon_refresh_token presence now checked with != null; expiresAt comparisons guarded by expiresAt != null.
SQL Type & Utilities
apps/backend/src/app/api/latest/auth/cli/poll/route.tsx
Adds getPrismaSchemaForTenancy, sqlQuoteIdent, and local CliAuthAttemptRow type for $queryRaw.
Polling Lookup & State Validation
apps/backend/src/app/api/latest/auth/cli/poll/route.tsx
Replaces findFirst with schema-qualified raw SELECT; throws InvalidPollingCodeError if not found; checks expiresAt, usedAt, and refreshToken to determine expired/used/waiting.
Atomic Claim Update
apps/backend/src/app/api/latest/auth/cli/poll/route.tsx
Replaces Prisma update() with atomic UPDATE ... WHERE ... AND "usedAt" IS NULL RETURNING "refreshToken"; sets usedAt and updatedAt to NOW(); returns used if no rows, otherwise success with token.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • N2D4

Poem

🐰 I hopped through schemas, small and neat,
Replaced the ORM with SQL sweet,
I guarded tokens, checked their time,
And claimed the refresh with one small chime,
Now polling dances, swift and fleet.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the two main changes: adding self-hosted URL support to the CLI and tightening the polling-code TTL window.
Description check ✅ Passed The description covers all major changes with clear sections (Summary and Test plan), includes specific technical details, and explains the rationale for each change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cli/self-host-urls-and-poll-hardening

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 and usage tips.

@mantrakp04 mantrakp04 requested a review from BilalG1 May 6, 2026 21:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds self-hosting support for the published stack-cli by allowing API/Dashboard URL overrides via environment variables, updates the Docker env example to surface those knobs, and tightens CLI-auth polling code lifetimes while aligning the poll handler with the tenancy source-of-truth schema via raw SQL.

Changes:

  • Allow stack-cli to read STACK_API_URL / STACK_DASHBOARD_URL from environment variables.
  • Document CLI-specific env vars in docker/server/.env.example.
  • Reduce CLI auth polling code TTL defaults/max and switch the poll handler to tenancy-schema raw SQL access.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
packages/stack-cli/src/lib/auth.ts Uses env overrides for default API/Dashboard URLs to support self-hosted backends.
docker/server/.env.example Documents CLI-relevant env vars for self-hosted/docker operators.
apps/backend/src/app/api/latest/auth/cli/route.tsx Tightens expires_in_millis default/max for CLI auth initiation.
apps/backend/src/app/api/latest/auth/cli/poll/route.tsx Uses raw SQL against tenancy schema for polling and marks attempts as used.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/backend/src/app/api/latest/auth/cli/poll/route.tsx Outdated
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR adds anonymous refresh token support to the CLI auth initiation endpoint, converts the poll handler from Prisma ORM to raw SQL (matching the initiate handler's pattern), and tightens CLI auth polling-code TTL defaults. The poll handler also addresses a previous TOCTOU concern by using an atomic UPDATE … WHERE "usedAt" IS NULL RETURNING "refreshToken" as the sole authoritative claim step.

  • poll/route.tsx: Migrated to raw SQL with an atomic UPDATE claim that prevents two concurrent polls from both receiving the same refresh token; null-check semantics are also made explicit.
  • route.tsx: Adds anon_refresh_token handling (validates token ownership, anonymity, and expiry before storing it on the CliAuthAttempt); tightens null checks (!= null over truthiness); changes the default expires_in_millis from 2 h to 10 min — but the advertised max reduction (24 h → 15 min) is absent from the code.

Confidence Score: 4/5

Safe to merge with the max-TTL caveat resolved — the atomic claim fix and anon-token handling are correct, but the 24-hour max expiry contradicts the stated security hardening.

The poll handler's atomic UPDATE correctly closes the concurrent-claim window, and the anon refresh token validation in the initiate handler is well-structured. However, the initiate handler's yupNumber().max() constraint was not reduced from 24 hours to the 15 minutes stated in the PR — a client can still request a day-long polling code, leaving the blast-radius argument incomplete.

apps/backend/src/app/api/latest/auth/cli/route.tsx — the max TTL guard needs to be updated to match the stated intent.

Important Files Changed

Filename Overview
apps/backend/src/app/api/latest/auth/cli/poll/route.tsx Converted from Prisma ORM to raw SQL with an atomic UPDATE…WHERE usedAt IS NULL RETURNING to prevent the TOCTOU token-claim race; logic and structure are correct.
apps/backend/src/app/api/latest/auth/cli/route.tsx Adds anon_refresh_token support and tightens null checks, but the advertised max-TTL reduction (24h → 15min) is missing from code — the max guard stays at 24 hours.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI Client
    participant Init as POST /auth/cli (initiate)
    participant Poll as POST /auth/cli/poll
    participant DB as Tenancy DB

    CLI->>Init: "POST {expires_in_millis, anon_refresh_token?}"
    Init->>DB: Validate anon_refresh_token (global DB)
    Init->>DB: INSERT CliAuthAttempt (pollingCode, loginCode, expiresAt)
    Init-->>CLI: "{polling_code, login_code, expires_at}"

    loop Poll until success/expired/used
        CLI->>Poll: "POST {polling_code}"
        Poll->>DB: SELECT id, refreshToken, expiresAt, usedAt
        alt expired
            Poll-->>CLI: "{status: expired}"
        else "usedAt != null"
            Poll-->>CLI: "{status: used}"
        else "refreshToken == null"
            Poll-->>CLI: "{status: waiting}"
        else refreshToken set
            Poll->>DB: "UPDATE SET usedAt=NOW() WHERE usedAt IS NULL RETURNING refreshToken"
            alt claimed atomic
                Poll-->>CLI: "201 {status: success, refresh_token}"
            else already claimed by concurrent request
                Poll-->>CLI: "{status: used}"
            end
        end
    end
Loading

Fix All in Claude Code Fix All in Cursor Fix All in Codex

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/backend/src/app/api/latest/auth/cli/route.tsx:28
**Max TTL not reduced — contradicts PR's security claim**

The PR description says the max expiry is being tightened from 24 h to 15 min, but the `yupNumber().max(...)` guard is unchanged at `1000 * 60 * 60 * 24` (24 hours). A client can still explicitly pass `expires_in_millis=86400000` and obtain a polling code valid for a full day, which negates the "limit the blast radius of a leaked code" argument in the PR. The default is also 10 minutes here, not 2 minutes as stated in the PR description. Both the max and the default need to match the stated security intent if the hardening is the rationale for the change.

Reviews (2): Last reviewed commit: "Update default expiration time for CLI a..." | Re-trigger Greptile

Comment thread apps/backend/src/app/api/latest/auth/cli/poll/route.tsx
Comment thread packages/stack-cli/src/lib/auth.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
apps/backend/src/app/api/latest/auth/cli/poll/route.tsx (2)

66-88: ⚡ Quick win

Make "mark as used" atomic to close a TOCTOU window on the polling code.

The SELECT at L51 and the UPDATE at L81 are independent statements with no row lock and no usedAt IS NULL guard. Two concurrent successful polls of the same polling_code (e.g., the legitimate CLI plus a leaked/mirrored request) can both pass the usedAt/refreshToken checks and both receive the refresh token, with the second update simply re-stamping usedAt. Since the file is now raw SQL, an atomic UPDATE … WHERE "usedAt" IS NULL RETURNING … plus a row-count check is a minimal, defense-in-depth fix and also lets you drop the in-memory cliAuth.usedAt branch.

🔒 Proposed atomic claim of the polling code
-    if (cliAuth.usedAt) {
-      return createResponse('used');
-    }
-
-    if (!cliAuth.refreshToken) {
+    if (cliAuth.refreshToken == null) {
       return createResponse('waiting');
     }
 
     // Mark as used
-    await prisma.$executeRaw(Prisma.sql`
-      UPDATE ${sqlQuoteIdent(schema)}."CliAuthAttempt"
-      SET
-        "usedAt" = NOW(),
-        "updatedAt" = NOW()
-      WHERE "tenancyId" = ${tenancy.id}::UUID
-        AND "id" = ${cliAuth.id}::UUID
-    `);
-
-    return createResponse('success', cliAuth.refreshToken);
+    const claimed = await prisma.$queryRaw<{ refreshToken: string }[]>(Prisma.sql`
+      UPDATE ${sqlQuoteIdent(schema)}."CliAuthAttempt"
+      SET
+        "usedAt" = NOW(),
+        "updatedAt" = NOW()
+      WHERE "tenancyId" = ${tenancy.id}::UUID
+        AND "id" = ${cliAuth.id}::UUID
+        AND "usedAt" IS NULL
+      RETURNING "refreshToken"
+    `);
+    if (claimed.length === 0) {
+      return createResponse('used');
+    }
+    return createResponse('success', claimed[0].refreshToken);
🤖 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 `@apps/backend/src/app/api/latest/auth/cli/poll/route.tsx` around lines 66 -
88, The polling code has a TOCTOU gap between selecting cliAuth and later
marking it used; change the raw UPDATE executed in prisma.$executeRaw (the one
that updates "CliAuthAttempt") to atomically set "usedAt" = NOW() only when
"usedAt" IS NULL and RETURNING the refreshToken (i.e. add WHERE "usedAt" IS NULL
and a RETURNING clause), then check the returned row count/result to decide
whether to return the refresh token or a 'used' response; remove the separate
in-memory cliAuth.usedAt branch and rely on the UPDATE RETURNING result (use
schema, tenancy.id, cliAuth.id and sqlQuoteIdent as in the current query to
locate the statement).

72-78: 💤 Low value

Use explicit null checks for usedAt / refreshToken.

usedAt is Date | null and refreshToken is string | null per CliAuthAttemptRow; prefer explicit null comparisons over truthiness so that, e.g., empty-string refreshToken would still be treated as not-yet-set rather than as an invalid token. (If you adopt the atomic-claim refactor above, the usedAt branch can be removed and only the refreshToken == null check remains.)

♻️ Proposed change
-    if (cliAuth.usedAt) {
+    if (cliAuth.usedAt != null) {
       return createResponse('used');
     }
 
-    if (!cliAuth.refreshToken) {
+    if (cliAuth.refreshToken == null) {
       return createResponse('waiting');
     }

As per coding guidelines: "Unless very clearly equivalent from types, prefer explicit null/undefinedness checks over boolean checks (e.g., foo == null instead of !foo)".

🤖 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 `@apps/backend/src/app/api/latest/auth/cli/poll/route.tsx` around lines 72 -
78, The truthy checks on cliAuth.usedAt and cliAuth.refreshToken should be
replaced with explicit null checks: change the first branch to test if
cliAuth.usedAt != null (or === null depending on desired behavior) and change
the second branch to test cliAuth.refreshToken == null so an empty-string
refreshToken is treated as "waiting"; update the branches that call
createResponse('used') and createResponse('waiting') accordingly (or remove the
usedAt branch if you adopt the atomic-claim refactor and only check refreshToken
== null).
apps/backend/src/app/api/latest/auth/cli/route.tsx (1)

44-62: 💤 Low value

Use explicit null/undefined checks instead of truthiness.

Per the coding guidelines, prefer foo == null (or != null) over boolean checks when the value isn't a boolean. Here anon_refresh_token is string | undefined and refreshTokenObj.expiresAt is Date | null, so the truthiness checks would also branch on the empty string / a future epoch-zero date even though those should not be treated specially.

♻️ Proposed change
-    if (anon_refresh_token) {
+    if (anon_refresh_token != null) {
       const refreshTokenRows = await globalPrismaClient.$queryRaw<RefreshTokenRow[]>(Prisma.sql`
@@
-      if (refreshTokenObj.expiresAt && refreshTokenObj.expiresAt < new Date()) {
+      if (refreshTokenObj.expiresAt != null && refreshTokenObj.expiresAt < new Date()) {
         throw new StatusError(400, "The provided anon refresh token has expired");
       }

As per coding guidelines: "Unless very clearly equivalent from types, prefer explicit null/undefinedness checks over boolean checks (e.g., foo == null instead of !foo)".

🤖 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 `@apps/backend/src/app/api/latest/auth/cli/route.tsx` around lines 44 - 62,
Replace truthiness checks with explicit null/undefined checks: change the
anon_refresh_token branch to test anon_refresh_token != null (since its type is
string | undefined) and change the expiry check to test
refreshTokenObj.expiresAt != null && refreshTokenObj.expiresAt < new Date()
(since expiresAt is Date | null) so empty string or epoch-like dates are not
misinterpreted; update the conditions around anon_refresh_token and
refreshTokenObj.expiresAt in the route handler accordingly.
🤖 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.

Nitpick comments:
In `@apps/backend/src/app/api/latest/auth/cli/poll/route.tsx`:
- Around line 66-88: The polling code has a TOCTOU gap between selecting cliAuth
and later marking it used; change the raw UPDATE executed in prisma.$executeRaw
(the one that updates "CliAuthAttempt") to atomically set "usedAt" = NOW() only
when "usedAt" IS NULL and RETURNING the refreshToken (i.e. add WHERE "usedAt" IS
NULL and a RETURNING clause), then check the returned row count/result to decide
whether to return the refresh token or a 'used' response; remove the separate
in-memory cliAuth.usedAt branch and rely on the UPDATE RETURNING result (use
schema, tenancy.id, cliAuth.id and sqlQuoteIdent as in the current query to
locate the statement).
- Around line 72-78: The truthy checks on cliAuth.usedAt and
cliAuth.refreshToken should be replaced with explicit null checks: change the
first branch to test if cliAuth.usedAt != null (or === null depending on desired
behavior) and change the second branch to test cliAuth.refreshToken == null so
an empty-string refreshToken is treated as "waiting"; update the branches that
call createResponse('used') and createResponse('waiting') accordingly (or remove
the usedAt branch if you adopt the atomic-claim refactor and only check
refreshToken == null).

In `@apps/backend/src/app/api/latest/auth/cli/route.tsx`:
- Around line 44-62: Replace truthiness checks with explicit null/undefined
checks: change the anon_refresh_token branch to test anon_refresh_token != null
(since its type is string | undefined) and change the expiry check to test
refreshTokenObj.expiresAt != null && refreshTokenObj.expiresAt < new Date()
(since expiresAt is Date | null) so empty string or epoch-like dates are not
misinterpreted; update the conditions around anon_refresh_token and
refreshTokenObj.expiresAt in the route handler accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8bd27d59-5cc0-4402-bef9-1432804d4f42

📥 Commits

Reviewing files that changed from the base of the PR and between bd8c448 and 38a64ff.

📒 Files selected for processing (4)
  • apps/backend/src/app/api/latest/auth/cli/poll/route.tsx
  • apps/backend/src/app/api/latest/auth/cli/route.tsx
  • docker/server/.env.example
  • packages/stack-cli/src/lib/auth.ts

Comment thread docker/server/.env.example Outdated
Comment thread apps/backend/src/app/api/latest/auth/cli/route.tsx Outdated
…tes and improve null checks in route handlers
@mantrakp04
Copy link
Copy Markdown
Collaborator Author

@greptile-ai I've addressed all the review feedback:

  • TOCTOU race in cli/poll/route.tsx (P1, also flagged by Copilot): replaced the SELECT-then-UPDATE with a single atomic UPDATE ... WHERE "usedAt" IS NULL RETURNING "refreshToken", so concurrent polls can't both claim the same refresh token.
  • DEFAULT_API_URL / DEFAULT_DASHBOARD_URL double-lookup (P2): reverted the constants to plain string literals; env-var resolution stays in resolveApiUrl() / resolveDashboardUrl() as the single source of truth.
  • Bilal's notes: removed the new lines from docker/server/.env.example (self-hosters pass these to the CLI), and bumped the default expires_in_millis from 2 min to 10 min.
  • CodeRabbit nits: switched the truthy checks on anon_refresh_token, refreshTokenObj.expiresAt, cliAuth.usedAt, and cliAuth.refreshToken to explicit != null / === null.

Please take another look.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@apps/backend/src/app/api/latest/auth/cli/route.tsx`:
- Line 28: The expires_in_millis schema currently allows up to 24 hours; tighten
the TTL by changing the yupNumber().max(...) cap from 1000 * 60 * 60 * 24 to a
short ceiling (e.g., 1000 * 60 * 15 for 15 minutes) while keeping the default at
1000 * 60 * 10 (10 minutes) so the expires_in_millis field enforces the intended
short polling window.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: edad35e1-8dd4-45f2-8ac8-60353e408c4f

📥 Commits

Reviewing files that changed from the base of the PR and between 38a64ff and 94637a2.

📒 Files selected for processing (2)
  • apps/backend/src/app/api/latest/auth/cli/poll/route.tsx
  • apps/backend/src/app/api/latest/auth/cli/route.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/backend/src/app/api/latest/auth/cli/poll/route.tsx

Comment thread apps/backend/src/app/api/latest/auth/cli/route.tsx Outdated
Comment thread apps/backend/src/app/api/latest/auth/cli/route.tsx Outdated
Comment thread apps/backend/src/app/api/latest/auth/cli/route.tsx Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
apps/backend/src/app/api/latest/auth/cli/route.tsx (1)

28-28: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restore the intended default polling TTL to 10 minutes.

Line 28 currently defaults to 2 minutes, but this PR’s agreed behavior is 10 minutes (with 15-minute max). Keep the tighter max, but update the default to avoid premature CLI auth expiry.

Suggested patch
-      expires_in_millis: yupNumber().max(1000 * 60 * 15).default(1000 * 60 * 2), // Default: 2 minutes, max: 15 minutes
+      expires_in_millis: yupNumber().max(1000 * 60 * 15).default(1000 * 60 * 10), // Default: 10 minutes, max: 15 minutes
🤖 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 `@apps/backend/src/app/api/latest/auth/cli/route.tsx` at line 28, The default
polling TTL for CLI auth is set incorrectly; update the default value in the
expires_in_millis schema (where expires_in_millis uses yupNumber().max(1000 * 60
* 15).default(...)) to 10 minutes by changing the default from 1000 * 60 * 2 to
1000 * 60 * 10 while keeping the existing max at 1000 * 60 * 15.
🤖 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.

Duplicate comments:
In `@apps/backend/src/app/api/latest/auth/cli/route.tsx`:
- Line 28: The default polling TTL for CLI auth is set incorrectly; update the
default value in the expires_in_millis schema (where expires_in_millis uses
yupNumber().max(1000 * 60 * 15).default(...)) to 10 minutes by changing the
default from 1000 * 60 * 2 to 1000 * 60 * 10 while keeping the existing max at
1000 * 60 * 15.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 939ac83e-d289-4e52-a37e-8ca4b9241f74

📥 Commits

Reviewing files that changed from the base of the PR and between 94637a2 and 27ed2eb.

📒 Files selected for processing (1)
  • apps/backend/src/app/api/latest/auth/cli/route.tsx

@mantrakp04 mantrakp04 merged commit 261d892 into dev May 8, 2026
29 of 35 checks passed
@mantrakp04 mantrakp04 deleted the cli/self-host-urls-and-poll-hardening branch May 8, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants