Skip to content

Conversation

@madster456
Copy link
Collaborator

@madster456 madster456 commented Dec 10, 2025

Updates the Auth panel on API pages to allow for authenticated users to select a project from project drop downs.

This enables easy access for the user to select their project, and test endpoints against it.

image

Summary by CodeRabbit

  • New Features

    • Project selection UI for configuring admin-scoped API access
    • Automatic admin-token refresh and auto-population of admin headers from the signed-in user
  • Improvements

    • Enhanced header management (supports functional updates and clearer handling)
    • Automatic token refresh before requests and improved base URL resolution across environments
    • Default project fallback when no project is configured
  • UX

    • clearer admin-related indicators, read-only styling, and contextual messaging for auto-populated headers

✏️ Tip: You can customize this high-level summary in your review settings.

@cmux-agent
Copy link

cmux-agent bot commented Dec 10, 2025

Older cmux preview screenshots (latest comment is below)

Preview Screenshots

Open Workspace (1 hr expiry) · Open Dev Browser (1 hr expiry) · Open Diff Heatmap

Captured 4 screenshots for commit 2b09ba4 (2025-12-10 18:02:35.647 UTC).

EnhancedAPIPage component showing POST /auth/password/sign-in endpoint with Request Body fields (email/password), Response section with Expected/Live Response tabs, and Code Examples section

api-page-with-auth-panel.png

AuthPanel component showing API Authentication header with 'logged in' badge, Quick Select Project dropdown, and all header input fields (Access Type, Project ID, Client Key, Server Key, Access Token, Admin Access Token) with '0 configured' status

auth-panel-open.png

AuthPanel with project dropdown expanded showing available projects (Dummy Project, Stack Dashboard) for quick selection

auth-panel-project-dropdown.png

AuthPanel after project selection showing auto-populated headers (Access Type: admin, Project ID: internal, Admin Access Token with JWT), success message, and 'Ready for API requests' status indicator

auth-panel-project-selected.png


Generated by cmux preview system

@vercel
Copy link

vercel bot commented Dec 10, 2025

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

Project Deployment Review Updated (UTC)
stack-backend Ready Ready Preview, Comment Dec 16, 2025 6:10pm
stack-dashboard Ready Ready Preview, Comment Dec 16, 2025 6:10pm
stack-demo Ready Ready Preview, Comment Dec 16, 2025 6:10pm
stack-docs Error Error Dec 16, 2025 6:10pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds admin-scoped authentication to the docs API UI: project selection in the auth panel, client-side admin token refresh and propagation into shared headers before requests, updateSharedHeaders API/type changes and behavior tweaks, Content-Type handling notes, and a default "internal" fallback for StackServerApp.projectId.

Changes

Cohort / File(s) Summary
Header configuration & context
docs/src/components/api/api-page-wrapper.tsx
Imported useCallback; added UpdateSharedHeadersInput type; changed APIPageContextType.updateSharedHeaders to accept object or functional updater; updateSharedHeaders now uses useCallback, applies functional state updates, and always clears highlightMissingHeaders; removed explicit Content-Type from STACK_AUTH_HEADERS, added X-Stack-Admin-Access-Token, and updated X-Stack-Access-Type description.
Admin auth UI & project selection
docs/src/components/api/auth-panel.tsx
Added project picker, owned-projects derivation, admin-token refresh when a project is selected (using session/user), auto-population and read-only behavior for admin headers, new header metadata (StackAuthHeaderKey/StackAuthHeaderField), UI messaging and mobile/desktop selectors, and logic to update shared headers with admin token and project ID.
Request flow & token refresh propagation
docs/src/components/api/enhanced-api-page.tsx
Integrated useUser and per-request admin token refresh when headers indicate admin access; updated flows to call updateSharedHeaders with refreshed X-Stack-Admin-Access-Token; ensure Content-Type: application/json is present for JSON bodies; base URL resolution uses env var in dev or OpenAPI spec in prod; effects/callbacks updated to include user and updateSharedHeaders.
Stack server config default
docs/src/stack.ts
StackServerApp initialization now falls back to "internal" for projectId when NEXT_PUBLIC_STACK_PROJECT_ID is not defined.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer (UI)
    participant AuthPanel as Auth Panel
    participant User as useUser/session
    participant APIPage as Enhanced API Page
    participant API as Stack API

    Dev->>AuthPanel: open auth panel / select project
    AuthPanel->>User: request session / user data
    User-->>AuthPanel: return session
    AuthPanel->>User: call user.getAuthJson() (get admin token)
    User-->>AuthPanel: return auth JSON (admin token)
    AuthPanel->>AuthPanel: merge admin headers (X-Stack-Admin-Access-Token, access-type, project-id)
    AuthPanel->>APIPage: call updateSharedHeaders(newHeaders)
    Dev->>APIPage: trigger API request
    APIPage->>APIPage: detect admin access in shared headers
    APIPage->>User: call user.getAuthJson() to refresh token
    User-->>APIPage: return refreshed token
    APIPage->>APIPage: update request headers with refreshed token and Content-Type if JSON
    APIPage->>API: send request with admin headers
    API-->>APIPage: return response
    APIPage-->>Dev: render response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Pay special attention to:
    • Correct typing and behavioral semantics of UpdateSharedHeadersInput and updateSharedHeaders (functional vs object updates).
    • That updateSharedHeaders always clears highlightMissingHeaders as intended and doesn't introduce UI regressions.
    • Token refresh timing/race conditions and error handling in auth-panel.tsx and enhanced-api-page.tsx.
    • Base URL selection logic (dev env var vs. OpenAPI spec) and implications for codegen examples.
    • The projectId fallback to "internal" and any downstream assumptions.

Possibly related PRs

Suggested reviewers

  • N2D4

Poem

🐇 I nibble headers with delight,
I pick a project and fetch a key tonight,
Admin token snug and new,
Shared headers hop into view,
Hooray — docs auth hops just right!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: enabling project selection on API documentation pages for authenticated users.
Description check ✅ Passed The description provides a clear, concise explanation of the changes with visual support, though it lacks detailed technical context and follows the minimal template.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch docs/util/apiauth

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.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Dec 10, 2025

Greptile Overview

Greptile Summary

Added project selection dropdown to API docs authentication panel, enabling authenticated users to quickly select and test endpoints against their owned projects using admin authentication.

Key Changes

  • Project selector UI in auth panel with automatic header population for admin access
  • Admin authentication flow with automatic refresh before API requests
  • Support for local API URL via NEXT_PUBLIC_STACK_API_URL environment variable
  • Fallback to "internal" project when environment variable is not set

Issues Found

  • Missing dependencies in useEffect hook causes stale closure over headers and updateSharedHeaders
  • Direct state mutation in executeRequest function may cause race conditions with stale data

Confidence Score: 3/5

  • Safe to merge with minor fixes for React hooks dependencies and state mutation
  • Two syntax/logic issues need attention: missing useEffect dependencies and direct state mutation. These will cause stale closures and potential race conditions in production
  • Pay close attention to docs/src/components/api/auth-panel.tsx and docs/src/components/api/enhanced-api-page.tsx for the React hooks and state management issues

Important Files Changed

File Analysis

Filename Score Overview
docs/src/components/api/auth-panel.tsx 3/5 Added project selector UI with admin token refresh logic; has missing useEffect dependencies
docs/src/components/api/enhanced-api-page.tsx 3/5 Added admin token refresh before API requests and local URL support; direct state mutation issue

Sequence Diagram

sequenceDiagram
    participant User
    participant AuthPanel
    participant EnhancedAPIPage
    participant StackAuth
    participant API

    User->>AuthPanel: Select project from dropdown
    AuthPanel->>AuthPanel: handleProjectSelect(projectId)
    AuthPanel->>AuthPanel: Update headers with projectId
    AuthPanel->>StackAuth: Request user authentication data
    StackAuth-->>AuthPanel: Return authentication info
    AuthPanel->>AuthPanel: Populate admin authentication header
    
    User->>EnhancedAPIPage: Click Try it out button
    EnhancedAPIPage->>EnhancedAPIPage: executeRequest()
    
    alt Admin access type
        EnhancedAPIPage->>StackAuth: Request fresh user authentication
        StackAuth-->>EnhancedAPIPage: Return fresh authentication info
        EnhancedAPIPage->>EnhancedAPIPage: Update admin authentication header
    end
    
    EnhancedAPIPage->>EnhancedAPIPage: Build request URL with parameters
    EnhancedAPIPage->>EnhancedAPIPage: Prepare headers and body
    EnhancedAPIPage->>API: fetch(url, requestOptions)
    API-->>EnhancedAPIPage: Response (status, data, headers)
    
    alt Error response (400/401/403)
        EnhancedAPIPage->>AuthPanel: reportError(status, error)
        AuthPanel->>AuthPanel: Highlight missing headers
        AuthPanel->>User: Show error in auth panel
    end
    
    EnhancedAPIPage->>User: Display response in UI
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Copy link
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: 5

🧹 Nitpick comments (3)
docs/src/components/api/auth-panel.tsx (1)

117-124: Strengthen type definitions for header configuration.

The stackAuthHeaders array uses properties (hideWhenProjectSelected, isSensitive) that aren't in the implicit type, requiring (header as any) casts later. Define an explicit type to improve safety.

+type StackAuthHeader = {
+  key: string;
+  label: string;
+  placeholder: string;
+  required: boolean;
+  hideWhenProjectSelected?: boolean;
+  isSensitive?: boolean;
+};

-  const stackAuthHeaders = [
+  const stackAuthHeaders: StackAuthHeader[] = [
     { key: 'X-Stack-Access-Type', label: 'Access Type', placeholder: 'client, server, or admin', required: true },
     ...
   ];

This eliminates the need for (header as any) casts on lines 256, 262, 422, and 428.

docs/src/components/api/enhanced-api-page.tsx (2)

423-428: Consider extracting duplicated base URL logic.

The base URL resolution logic is duplicated in generateCurlCommand, generateJavaScriptCode, and generatePythonCode. Consider extracting to a shared memoized value.

+  const computedBaseUrl = useMemo(() => {
+    const defaultBaseUrl = spec?.servers?.[0]?.url || '';
+    return process.env.NEXT_PUBLIC_STACK_API_URL 
+      ? process.env.NEXT_PUBLIC_STACK_API_URL + '/api/v1'
+      : defaultBaseUrl;
+  }, [spec]);

   const generateCurlCommand = useCallback(() => {
-    // Use local API URL in development, production URL otherwise
-    const defaultBaseUrl = spec.servers?.[0]?.url || '';
-    const baseUrl = process.env.NEXT_PUBLIC_STACK_API_URL 
-      ? process.env.NEXT_PUBLIC_STACK_API_URL + '/api/v1'
-      : defaultBaseUrl;
-    let url = baseUrl + path;
+    let url = computedBaseUrl + path;

371-375: Avoid .catch(console.error) pattern.

Per coding guidelines, avoid .catch(console.error). The executeRequest function already handles errors internally, so the outer catch is redundant.

             onExecute={() => {
-              // eslint-disable-next-line no-restricted-syntax
-              executeRequest(operation, path, method)
-                .catch(error => console.error('Failed to execute request:', error));
+              runAsynchronouslyWithAlert(() => executeRequest(operation, path, method));
             }}

Or if executeRequest already handles all errors gracefully, the catch can be removed entirely.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8827c0c and 49ea9bc.

📒 Files selected for processing (4)
  • docs/src/components/api/api-page-wrapper.tsx (1 hunks)
  • docs/src/components/api/auth-panel.tsx (10 hunks)
  • docs/src/components/api/enhanced-api-page.tsx (8 hunks)
  • docs/src/stack.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Always add new E2E tests when changing the API or SDK interface
For blocking alerts and errors, never use toast; use alerts instead as they are less easily missed by the user
NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error); use loading indicators and async callbacks instead, or use runAsynchronously/runAsynchronouslyWithAlert for error handling
Use ES6 maps instead of records wherever you can

Files:

  • docs/src/stack.ts
  • docs/src/components/api/api-page-wrapper.tsx
  • docs/src/components/api/enhanced-api-page.tsx
  • docs/src/components/api/auth-panel.tsx
**/*.{ts,tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,css}: Keep hover/click transitions snappy and fast; avoid fade-in delays on hover. Apply transitions after action completion instead, like smooth fade-out when hover ends
Use hover-exit transitions instead of hover-enter transitions; for example, use 'transition-colors hover:transition-none' instead of fade-in on hover

Files:

  • docs/src/stack.ts
  • docs/src/components/api/api-page-wrapper.tsx
  • docs/src/components/api/enhanced-api-page.tsx
  • docs/src/components/api/auth-panel.tsx
{.env*,**/*.{ts,tsx,js}}

📄 CodeRabbit inference engine (AGENTS.md)

Prefix environment variables with STACK_ (or NEXT_PUBLIC_STACK_ if public) so changes are picked up by Turborepo and improves readability

Files:

  • docs/src/stack.ts
  • docs/src/components/api/api-page-wrapper.tsx
  • docs/src/components/api/enhanced-api-page.tsx
  • docs/src/components/api/auth-panel.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-04T18:03:49.961Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-04T18:03:49.961Z
Learning: Applies to {.env*,**/*.{ts,tsx,js}} : Prefix environment variables with STACK_ (or NEXT_PUBLIC_STACK_ if public) so changes are picked up by Turborepo and improves readability

Applied to files:

  • docs/src/stack.ts
📚 Learning: 2025-10-11T04:13:19.308Z
Learnt from: N2D4
Repo: stack-auth/stack-auth PR: 943
File: examples/convex/app/action/page.tsx:23-28
Timestamp: 2025-10-11T04:13:19.308Z
Learning: In the stack-auth codebase, use `runAsynchronouslyWithAlert` from `stackframe/stack-shared/dist/utils/promises` for async button click handlers and form submissions instead of manual try/catch blocks. This utility automatically handles errors and shows alerts to users.

Applied to files:

  • docs/src/components/api/enhanced-api-page.tsx
  • docs/src/components/api/auth-panel.tsx
🧬 Code graph analysis (1)
docs/src/components/api/auth-panel.tsx (1)
docs/src/components/icons.tsx (1)
  • ChevronDown (67-69)
🪛 Biome (2.1.2)
docs/src/components/api/auth-panel.tsx

[error] 21-21: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: all-good
  • GitHub Check: Vercel Agent Review
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: setup-tests
  • GitHub Check: build (22.x)
  • GitHub Check: restart-dev-and-test
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: build (22.x)
  • GitHub Check: docker
  • GitHub Check: build (22.x)
🔇 Additional comments (2)
docs/src/components/api/api-page-wrapper.tsx (1)

7-15: LGTM!

The header configuration changes are well-documented. The comment clarifying Content-Type handling and the addition of X-Stack-Admin-Access-Token for admin authentication are appropriate for the new project selection feature.

docs/src/stack.ts (1)

7-7: LGTM!

The fallback to "internal" ensures the docs app initializes correctly when the environment variable is not set, supporting the shared authentication model between docs and dashboard.

@cmux-agent
Copy link

cmux-agent bot commented Dec 15, 2025

Older cmux preview screenshots (latest comment is below)

Preview Screenshots

Open Diff Heatmap

Preview screenshots are being captured...

Workspace and dev browser links will appear here once the preview environment is ready.


Generated by cmux preview system

Copy link
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

♻️ Duplicate comments (1)
docs/src/components/api/auth-panel.tsx (1)

53-57: Conditional hook call still violates Rules of Hooks.

Line 55 conditionally calls useOwnedProjects() using optional chaining (internalUser?.useOwnedProjects()), which still violates React's Rules of Hooks. Hooks must be called unconditionally at the top level.

Consider checking if useOwnedProjects can be imported as a separate hook and called unconditionally, or ensure it's called at the top level without conditional access.

🧹 Nitpick comments (2)
docs/src/components/api/auth-panel.tsx (1)

328-330: Consider consistent wording across desktop and mobile.

Line 330 shows "via project selection" for desktop, while line 497 shows "via project" for mobile. Consider using the same text for consistency, though this is a minor UX detail.

Apply this diff if you prefer consistency:

-                {selectedProjectId && ' (via project)'}
+                {selectedProjectId && ' (via project selection)'}

Also applies to: 496-498

docs/src/components/api/enhanced-api-page.tsx (1)

227-230: Consider extracting base URL resolution logic.

The base URL resolution logic is duplicated across four locations (lines 227-230, 416-421, 467-471, 521-525). Extracting this into a helper function would improve maintainability.

Add a helper function:

const getBaseUrl = useCallback(() => {
  const defaultBaseUrl = spec?.servers?.[0]?.url || '';
  const localApiUrl = process.env.NEXT_PUBLIC_STACK_API_URL;
  return localApiUrl ? localApiUrl + '/api/v1' : defaultBaseUrl;
}, [spec]);

Then replace all four occurrences with const baseUrl = getBaseUrl();

Also applies to: 416-421, 467-471, 521-525

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49ea9bc and 8bfc175.

📒 Files selected for processing (2)
  • docs/src/components/api/auth-panel.tsx (9 hunks)
  • docs/src/components/api/enhanced-api-page.tsx (9 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Always add new E2E tests when changing the API or SDK interface
For blocking alerts and errors, never use toast; use alerts instead as they are less easily missed by the user
NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error); use loading indicators and async callbacks instead, or use runAsynchronously/runAsynchronouslyWithAlert for error handling
Use ES6 maps instead of records wherever you can

Files:

  • docs/src/components/api/auth-panel.tsx
  • docs/src/components/api/enhanced-api-page.tsx
**/*.{ts,tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,css}: Keep hover/click transitions snappy and fast; avoid fade-in delays on hover. Apply transitions after action completion instead, like smooth fade-out when hover ends
Use hover-exit transitions instead of hover-enter transitions; for example, use 'transition-colors hover:transition-none' instead of fade-in on hover

Files:

  • docs/src/components/api/auth-panel.tsx
  • docs/src/components/api/enhanced-api-page.tsx
{.env*,**/*.{ts,tsx,js}}

📄 CodeRabbit inference engine (AGENTS.md)

Prefix environment variables with STACK_ (or NEXT_PUBLIC_STACK_ if public) so changes are picked up by Turborepo and improves readability

Files:

  • docs/src/components/api/auth-panel.tsx
  • docs/src/components/api/enhanced-api-page.tsx
🧠 Learnings (2)
📚 Learning: 2025-10-11T04:13:19.308Z
Learnt from: N2D4
Repo: stack-auth/stack-auth PR: 943
File: examples/convex/app/action/page.tsx:23-28
Timestamp: 2025-10-11T04:13:19.308Z
Learning: In the stack-auth codebase, use `runAsynchronouslyWithAlert` from `stackframe/stack-shared/dist/utils/promises` for async button click handlers and form submissions instead of manual try/catch blocks. This utility automatically handles errors and shows alerts to users.

Applied to files:

  • docs/src/components/api/auth-panel.tsx
  • docs/src/components/api/enhanced-api-page.tsx
📚 Learning: 2025-12-04T18:03:49.984Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-04T18:03:49.984Z
Learning: Applies to **/*.{ts,tsx} : NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error); use loading indicators and async callbacks instead, or use runAsynchronously/runAsynchronouslyWithAlert for error handling

Applied to files:

  • docs/src/components/api/auth-panel.tsx
🧬 Code graph analysis (2)
docs/src/components/api/auth-panel.tsx (5)
docs/src/components/layouts/sidebar-context.tsx (1)
  • useSidebar (46-49)
docs/src/components/api/api-page-wrapper.tsx (1)
  • useAPIPageContext (38-43)
packages/stack-shared/src/utils/promises.tsx (1)
  • runAsynchronously (343-366)
packages/stack-shared/src/utils/strings.tsx (1)
  • stringCompare (61-65)
docs/src/components/icons.tsx (1)
  • ChevronDown (67-69)
docs/src/components/api/enhanced-api-page.tsx (1)
packages/template/src/lib/stack-app/apps/implementations/common.ts (1)
  • defaultBaseUrl (145-145)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Vercel Agent Review
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: docker
  • GitHub Check: E2E Tests (Node 22.x, Freestyle mock)
  • GitHub Check: build (22.x)
  • GitHub Check: all-good
  • GitHub Check: setup-tests
  • GitHub Check: build (22.x)
  • GitHub Check: E2E Tests (Node 22.x, Freestyle prod)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: setup-tests-with-custom-base-port
  • GitHub Check: restart-dev-and-test
🔇 Additional comments (6)
docs/src/components/api/auth-panel.tsx (3)

149-174: LGTM! Clean project selection logic.

The project selection handler properly validates the selected project and sets up admin headers. The use of useMemo for sorting projects is good for performance optimization.


238-268: LGTM! Well-designed project selector UI.

The project selector provides good UX with clear labels, success feedback, and proper accessibility. The conditional rendering and sorted project list enhance usability.


271-317: LGTM! Clean auto-population logic.

The conditional field visibility and auto-population logic provide a smooth user experience. Making auto-populated fields read-only with clear feedback is a good UX pattern.

docs/src/components/api/enhanced-api-page.tsx (3)

211-225: Admin token refresh logic improved, but silent failure possible.

The code no longer directly mutates state (previous issue resolved). However, if user.getAuthJson() fails, the request proceeds with potentially stale headers. This might be intentional behavior.

If token refresh failure should block the request, consider wrapping this logic differently or surfacing the error to the user. Otherwise, the current implementation is acceptable for graceful degradation.


272-277: LGTM! Proper Content-Type header handling.

Explicitly adding the Content-Type header when sending JSON ensures proper request formatting. The spread operation correctly preserves existing headers including the refreshed admin token.


316-316: LGTM! Complete dependency array.

All dependencies used within the executeRequest callback are properly included in the dependency array, including the newly added user and updateSharedHeaders.

@cmux-agent
Copy link

cmux-agent bot commented Dec 15, 2025

Preview Screenshots

Open Diff Heatmap

Preview screenshots are being captured...

Workspace and dev browser links will appear here once the preview environment is ready.


Generated by cmux preview system

…ate support. Updated auth panel admin-token refresh effect to rely on the new functional updater and trimmed its dependency list, preventing the previous infinite loop that caused maximum update depth exceeded
Copy link
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: 0

♻️ Duplicate comments (1)
docs/src/components/api/auth-panel.tsx (1)

53-57: Conditional hook call violates Rules of Hooks.

Line 55 calls useOwnedProjects() conditionally via optional chaining (internalUser?.useOwnedProjects()). If internalUser is null on one render and non-null on the next, the hook call order changes, violating React's Rules of Hooks.

Refactor to call the hook unconditionally:

-  const user = useUser();
-  const internalUser = isInternalUser(user) ? user : null;
-  const ownedProjectsResult = internalUser?.useOwnedProjects();
-  const projects = useMemo<AdminOwnedProject[]>(() => ownedProjectsResult ?? [], [ownedProjectsResult]);
-  const hasOwnedProjects = Boolean(internalUser);
+  const user = useUser();
+  const internalUser = isInternalUser(user) ? user : null;
+  // Always call the hook unconditionally - pass internalUser to satisfy hook rules
+  const ownedProjectsResult = internalUser ? internalUser.useOwnedProjects() : null;
+  const projects = useMemo<AdminOwnedProject[]>(() => ownedProjectsResult ?? [], [ownedProjectsResult]);
+  const hasOwnedProjects = Boolean(internalUser);

Actually, the issue persists with ternary too. The hook must be called at the top level unconditionally. Consider restructuring by either:

  1. Always calling useOwnedProjects from a stable source (if it's a standalone hook)
  2. Creating a child component that only renders when internalUser exists, which can safely call the hook
🧹 Nitpick comments (3)
docs/src/components/api/auth-panel.tsx (3)

142-143: Dead code: ternary always returns the same value.

The topPosition calculation always evaluates to 'top-0' regardless of the condition.

-  const topPosition = isHomePage && isScrolled ? 'top-0' : 'top-0';
+  const topPosition = 'top-0';

149-169: Consider using functional update for consistency.

The handleProjectSelect spreads headers directly while the useEffect uses functional updates. For consistency and to avoid potential stale closure issues if this function is ever used in callbacks:

-    const newHeaders = {
-      ...headers,
-      'X-Stack-Access-Type': 'admin',
-      'X-Stack-Project-Id': projectId,
-      'X-Stack-Admin-Access-Token': '', // Will be populated by refresh effect
-      'X-Stack-Access-Token': '', // Not used for admin access
-      'X-Stack-Publishable-Client-Key': '', // Not needed for admin auth
-      'X-Stack-Secret-Server-Key': '', // Not needed for admin auth
-    };
-
-    updateSharedHeaders(newHeaders);
+    updateSharedHeaders(prevHeaders => ({
+      ...prevHeaders,
+      'X-Stack-Access-Type': 'admin',
+      'X-Stack-Project-Id': projectId,
+      'X-Stack-Admin-Access-Token': '', // Will be populated by refresh effect
+      'X-Stack-Access-Token': '', // Not used for admin access
+      'X-Stack-Publishable-Client-Key': '', // Not needed for admin auth
+      'X-Stack-Secret-Server-Key': '', // Not needed for admin auth
+    }));

304-304: Consider functional update for input onChange handlers.

For consistency with the useEffect pattern and to ensure the latest headers are used:

-                    onChange={(e) => updateSharedHeaders({ ...headers, [header.key]: e.target.value })}
+                    onChange={(e) => updateSharedHeaders(prev => ({ ...prev, [header.key]: e.target.value }))}

Same applies to line 470 (mobile input).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8bfc175 and 15b7cf8.

📒 Files selected for processing (2)
  • docs/src/components/api/api-page-wrapper.tsx (3 hunks)
  • docs/src/components/api/auth-panel.tsx (9 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Always add new E2E tests when changing the API or SDK interface
For blocking alerts and errors, never use toast; use alerts instead as they are less easily missed by the user
NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error); use loading indicators and async callbacks instead, or use runAsynchronously/runAsynchronouslyWithAlert for error handling
Use ES6 maps instead of records wherever you can

Files:

  • docs/src/components/api/auth-panel.tsx
  • docs/src/components/api/api-page-wrapper.tsx
**/*.{ts,tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,css}: Keep hover/click transitions snappy and fast; avoid fade-in delays on hover. Apply transitions after action completion instead, like smooth fade-out when hover ends
Use hover-exit transitions instead of hover-enter transitions; for example, use 'transition-colors hover:transition-none' instead of fade-in on hover

Files:

  • docs/src/components/api/auth-panel.tsx
  • docs/src/components/api/api-page-wrapper.tsx
{.env*,**/*.{ts,tsx,js}}

📄 CodeRabbit inference engine (AGENTS.md)

Prefix environment variables with STACK_ (or NEXT_PUBLIC_STACK_ if public) so changes are picked up by Turborepo and improves readability

Files:

  • docs/src/components/api/auth-panel.tsx
  • docs/src/components/api/api-page-wrapper.tsx
🧠 Learnings (2)
📚 Learning: 2025-10-11T04:13:19.308Z
Learnt from: N2D4
Repo: stack-auth/stack-auth PR: 943
File: examples/convex/app/action/page.tsx:23-28
Timestamp: 2025-10-11T04:13:19.308Z
Learning: In the stack-auth codebase, use `runAsynchronouslyWithAlert` from `stackframe/stack-shared/dist/utils/promises` for async button click handlers and form submissions instead of manual try/catch blocks. This utility automatically handles errors and shows alerts to users.

Applied to files:

  • docs/src/components/api/auth-panel.tsx
📚 Learning: 2025-12-04T18:03:49.984Z
Learnt from: CR
Repo: stack-auth/stack-auth PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-04T18:03:49.984Z
Learning: Applies to **/*.{ts,tsx} : NEVER try-catch-all, NEVER void a promise, and NEVER .catch(console.error); use loading indicators and async callbacks instead, or use runAsynchronously/runAsynchronouslyWithAlert for error handling

Applied to files:

  • docs/src/components/api/auth-panel.tsx
🧬 Code graph analysis (1)
docs/src/components/api/auth-panel.tsx (5)
docs/src/components/layouts/sidebar-context.tsx (1)
  • useSidebar (46-49)
docs/src/components/api/api-page-wrapper.tsx (1)
  • useAPIPageContext (40-45)
packages/stack-shared/src/utils/promises.tsx (1)
  • runAsynchronously (343-366)
packages/stack-shared/src/utils/strings.tsx (1)
  • stringCompare (61-65)
docs/src/components/icons.tsx (1)
  • ChevronDown (67-69)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Vercel Agent Review
  • GitHub Check: build (22.x)
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: setup-tests
  • GitHub Check: restart-dev-and-test
  • GitHub Check: E2E Tests (Node 22.x, Freestyle prod)
  • GitHub Check: E2E Tests (Node 22.x, Freestyle mock)
  • GitHub Check: setup-tests-with-custom-base-port
  • GitHub Check: all-good
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: docker
  • GitHub Check: build (22.x)
🔇 Additional comments (4)
docs/src/components/api/api-page-wrapper.tsx (2)

63-71: Well-implemented functional update pattern for shared headers.

The useCallback wrapper with empty dependencies is correct since React state setters are stable. The functional update support nicely prevents stale closure issues when consumers need to update headers based on current state.


27-31: Clean type extension for functional updates.

The UpdateSharedHeadersInput union type properly supports both direct object replacement and functional updates, aligning well with React's setState patterns.

docs/src/components/api/auth-panel.tsx (2)

89-106: Good fix for the token refresh effect.

The refactored implementation correctly:

  • Uses runAsynchronously for error handling (per coding guidelines)
  • Uses functional update pattern to avoid stale headers closure
  • Only includes stable dependencies (updateSharedHeaders is now memoized)

This properly addresses the previous review feedback about infinite loops and error handling.


238-268: Good UX for project selection with clear visual feedback.

The project selector provides clear indication of logged-in state, sorted projects, and confirmation when headers are auto-populated. The readOnly state with visual styling for auto-populated fields is well-handled.

Comment on lines +151 to +156
setSelectedProjectId(projectId);

if (!projects.some((projectItem) => projectItem.id === projectId)) {
return;
}

Copy link

Choose a reason for hiding this comment

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

Suggested change
setSelectedProjectId(projectId);
if (!projects.some((projectItem) => projectItem.id === projectId)) {
return;
}
// Validate project exists before modifying state
if (!projects.some((projectItem) => projectItem.id === projectId)) {
return;
}
setSelectedProjectId(projectId);

In handleProjectSelect, the component sets selectedProjectId state before validating if the project exists. If validation fails, the function returns early without updating headers, leaving the component in an inconsistent state.

View Details

Analysis

Race condition in AuthPanel.handleProjectSelect() leaves component in inconsistent state

What fails: When a project list update occurs between dropdown render and user selection, handleProjectSelect() sets selectedProjectId state before validating if the project exists, causing the component to enter an inconsistent state where headers lack the required access-type and project-id fields even though the admin access token is fetched.

How to reproduce:

  1. User views projects [A, B, C] in the Quick Select Project dropdown
  2. User clicks to select project A
  3. Before the onChange handler fires, the projects list updates to [B, C, D] (e.g., from a network fetch completing)
  4. handleProjectSelect fires with projectId="A" but "A" is no longer in the current projects array
  5. Validation fails and function returns early
  6. Result: selectedProjectId is set to "A", useEffect fetches admin token, but X-Stack-Access-Type and X-Stack-Project-Id headers were never set

Expected behavior: Validation should occur before state is modified. Invalid project selections should not update state, preventing the component from entering an inconsistent state.

Root cause: In docs/src/components/api/auth-panel.tsx, the handleProjectSelect function calls setSelectedProjectId(projectId) before validating whether the project exists in the projects array. If validation fails and the function returns early, the state remains modified while headers are not updated, leading to incomplete authentication headers.

Fix: Move the validation check to occur before state modification, ensuring that setSelectedProjectId() is only called when the project ID is confirmed to be valid.

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