Skip to content

feat: add password auth fallback with VITE_MAGICLINK_AUTH#304

Merged
turisanapo merged 8 commits into
mainfrom
claude-issue-299-20260320-0932
Mar 21, 2026
Merged

feat: add password auth fallback with VITE_MAGICLINK_AUTH#304
turisanapo merged 8 commits into
mainfrom
claude-issue-299-20260320-0932

Conversation

@heiwen

@heiwen heiwen commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

Password auth is now the default (no env var needed). Set VITE_MAGICLINK_AUTH=true to switch to email OTP magic link flow.

  • Auth service: emailAndPassword enabled when SMTP is not configured
  • Console: password sign-in/sign-up forms shown by default
  • SST: VITE_MAGICLINK_AUTH derived from SmtpHost secret
  • Removes console-based OTP logger dev workaround

Closes #299

Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Password-based sign-up and two-step sign-in (email → password) added; sign-in method auto-switches based on email service availability.
  • UI Improvements

    • Simplified sign-in page and new overall auth layout with marketing panel and nested auth routes.
    • Acceptance/invitation layout spacing adjusted.
  • Usability

    • Invitation rows include a copy-invitation-link button with visual feedback.
    • Forms show loading/disabled states during submit.
  • Accessibility

    • Error messages in sign-in/magic-link flows now expose role="alert".

Password auth is now the default (no env var needed). Set
VITE_MAGICLINK_AUTH=true to switch to email OTP magic link flow.

Auth service: emailAndPassword enabled when hasSmtpConfig() is false,
credential added to trustedProviders for account linking.

Console: password sign-in/sign-up forms shown by default, magic link
shown when VITE_MAGICLINK_AUTH=true.

SST: VITE_MAGICLINK_AUTH derived from SmtpHost secret — automatically
true when SMTP is configured.

Removes console-based OTP logger dev workaround.

Co-authored-by: Heinrich Wendel <heiwen@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9b480b6b-11e8-40d7-8cd5-885b86d0af95

📥 Commits

Reviewing files that changed from the base of the PR and between e208e07 and 34c1143.

📒 Files selected for processing (2)
  • apps/console/app/routes/_shell.agent.$agentSlug.settings/members.tsx
  • packages/shared-ui/src/components/CopyButton.tsx

📝 Walkthrough

Walkthrough

Enables email+password auth across backend and console: exports SMTP detection, conditionally enables Better Auth's emailAndPassword, adds password sign-in/sign-up UI and service methods, introduces VITE_MAGICLINK_AUTH flag, and small UI/layout/accessibility updates.

Changes

Cohort / File(s) Summary
Auth service config & email helper
apps/auth/src/better-auth.ts, apps/auth/src/lib/email.ts
Added "email-password" to accountLinking.trustedProviders; exported hasSmtpConfig() (returns explicit boolean) and used it to enable emailAndPassword when SMTP is absent; removed production-only SMTP gating/logging and reordered URL construction.
Console auth types & implementations
apps/console/app/lib/auth/types.ts, apps/console/app/lib/auth/better-auth.ts, apps/console/app/lib/auth/dummy-auth.ts
Extended AuthService interface with signInWithPassword and signUpWithPassword; implemented methods in real and dummy auth services (real calls authClient.signIn.email/authClient.signUp.email, errors thrown on failure, redirect on success).
Console routes: sign-in / sign-up / layout / magiclink
apps/console/app/routes/_auth.signin/password.tsx, apps/console/app/routes/_auth.signin/route.tsx, apps/console/app/routes/_auth.signup/route.tsx, apps/console/app/routes/_auth/route.tsx, apps/console/app/routes/_auth.signin/magiclink.tsx, apps/console/app/routes/_auth.accept-invitation/route.tsx
Added password sign-in component and sign-up page; route.tsx renders MagicLink or Password based on magicLinkAuth; removed an aside in signin route, adjusted layout classes, and added role="alert" to error areas.
Env & infra
apps/console/app/lib/env.ts, infra/stacks/console.ts
Added magicLinkAuth export derived from VITE_MAGICLINK_AUTH; stack sets VITE_MAGICLINK_AUTH based on presence of smtpHost.
Members UI
apps/console/app/routes/_shell.agent.$agentSlug.settings/members.tsx, packages/shared-ui/src/components/CopyButton.tsx
Added CopyButton import and invite-link copy control next to revoke button; CopyButton gains optional icon prop and uses it when not in copied state; updated icon imports.

Sequence Diagrams

sequenceDiagram
    actor User
    participant Console as Console UI
    participant AuthService as AuthService
    participant AuthClient as AuthClient
    participant Backend as BetterAuth
    participant DB as Database

    User->>Console: Submit password sign-in form
    Console->>AuthService: signInWithPassword(email, password)
    AuthService->>AuthClient: authClient.signIn.email({ email, password, callbackURL })
    AuthClient->>Backend: POST /sign-in/email
    Backend->>DB: Verify credentials
    alt Success
        DB-->>Backend: user + session
        Backend-->>AuthClient: success
        AuthClient-->>AuthService: success
        AuthService->>Console: location.replace(redirectPath)
        Console->>User: Redirect to app
    else Failure
        DB-->>Backend: invalid credentials
        Backend-->>AuthClient: error
        AuthClient-->>AuthService: error
        AuthService->>Console: throw Error
        Console->>User: Display error
    end
Loading
sequenceDiagram
    actor User
    participant Console as Console UI
    participant AuthService as AuthService
    participant AuthClient as AuthClient
    participant Backend as BetterAuth
    participant DB as Database

    User->>Console: Submit password sign-up form
    Console->>AuthService: signUpWithPassword(name, email, password)
    AuthService->>AuthClient: authClient.signUp.email({ name, email, password, callbackURL })
    AuthClient->>Backend: POST /sign-up/email
    Backend->>DB: Hash password & create user
    alt Created
        DB-->>Backend: new user + session
        Backend-->>AuthClient: success
        AuthClient-->>AuthService: success
        AuthService->>Console: location.replace(redirectPath)
        Console->>User: Redirect to app
    else Failure
        DB-->>Backend: validation/conflict
        Backend-->>AuthClient: error
        AuthClient-->>AuthService: error
        AuthService->>Console: throw Error
        Console->>User: Display error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Possibly related PRs

Suggested reviewers

  • turisanapo

Poem

🐇 I nibbled at config under moonlight,
Password doors opened, cozy and bright.
No SMTP? I’ll scaffold the gate,
Sign up, sign in — your session’s great.
Carrots, links, and tiny hops of delight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately describes the main change: adding password authentication as a fallback option controlled by VITE_MAGICLINK_AUTH environment variable.
Linked Issues check ✅ Passed The PR meets all primary coding objectives from issue #299: emailAndPassword enabled in better-auth with SMTP config check, password sign-in/sign-up forms added to console, account linking preserved with email-password provider, VITE_MAGICLINK_AUTH environment flag implemented, and invitation link regression addressed via CopyButton.
Out of Scope Changes check ✅ Passed All changes align with the PR objectives. Backend config enables emailAndPassword conditionally; console routes add password forms and feature toggle; infrastructure sets VITE_MAGICLINK_AUTH; CopyButton enhancement supports invitation link copying as discussed with author.

✏️ 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 claude-issue-299-20260320-0932
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c46951a57f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread infra/stacks/console.ts
Comment thread apps/auth/src/better-auth.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/console/app/routes/_auth.signup/route.tsx (1)

25-86: Form implementation looks good; consider adding role="alert" for accessibility.

The form correctly handles loading states, disables inputs during submission, and displays errors. The pattern is consistent with the existing password sign-in flow. One optional improvement: the error message on line 78 would benefit from role="alert" so screen readers announce it when it appears.

♿ Optional accessibility enhancement
-          {error && <div className="text-sm text-destructive">{error}</div>}
+          {error && <div role="alert" className="text-sm text-destructive">{error}</div>}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/console/app/routes/_auth.signup/route.tsx` around lines 25 - 86, Add an
accessibility role to the error message element so screen readers announce it:
update the conditional rendering that displays {error} (the div currently
rendered as <div className="text-sm text-destructive">{error}</div>) to include
role="alert" (and optionally aria-live="assertive") so the error is announced
when setError populates the error state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/auth/src/lib/email.ts`:
- Around line 98-100: The URL construction for acceptUrl uses consoleUrl before
validating it, causing new URL(...) to throw if consoleUrl is undefined; reorder
the guards so hasSmtpConfig() and the consoleUrl check run before constructing
acceptUrl. Specifically, in the function that builds the invitation email (where
acceptUrl is created), move the if (!hasSmtpConfig()) return; and if
(!consoleUrl) return console.warn(...) checks above the new
URL("/accept-invitation", consoleUrl) call—mirroring the guard order used in
sendVerificationOtpEmail—to ensure consoleUrl is present before calling new URL.

---

Nitpick comments:
In `@apps/console/app/routes/_auth.signup/route.tsx`:
- Around line 25-86: Add an accessibility role to the error message element so
screen readers announce it: update the conditional rendering that displays
{error} (the div currently rendered as <div className="text-sm
text-destructive">{error}</div>) to include role="alert" (and optionally
aria-live="assertive") so the error is announced when setError populates the
error state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: df51d995-8467-435e-8e35-dc514c7d2931

📥 Commits

Reviewing files that changed from the base of the PR and between e95dcec and c46951a.

📒 Files selected for processing (10)
  • apps/auth/src/better-auth.ts
  • apps/auth/src/lib/email.ts
  • apps/console/app/lib/auth/better-auth.ts
  • apps/console/app/lib/auth/dummy-auth.ts
  • apps/console/app/lib/auth/types.ts
  • apps/console/app/lib/env.ts
  • apps/console/app/routes/_auth.signin/password.tsx
  • apps/console/app/routes/_auth.signin/route.tsx
  • apps/console/app/routes/_auth.signup/route.tsx
  • infra/stacks/console.ts

Comment thread apps/auth/src/lib/email.ts Outdated
@heiwen

heiwen commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

@claude what do you think about the comments?

@hebo-agent

hebo-agent Bot commented Mar 20, 2026

Copy link
Copy Markdown

Claude finished @heiwen's task in 51s —— View job


Review comment analysis

  • Read relevant source files
  • Evaluate each review comment
  • Post analysis

Here's my take on each comment:


1. Codex P1 — SMTP config mismatch (infra/stacks/console.ts:20) — Agree it's a real discrepancy, but low risk

The console sets VITE_MAGICLINK_AUTH=true when just SmtpHost is set, while the auth service (email.ts:20) requires all 5 fields (smtpHost && smtpPort && smtpUser && smtpPass && smtpFrom). During partial SMTP config, the console would show magic-link UI but the backend wouldn't actually send emails. You already noted this is acceptable — agree it's unlikely in practice since secrets are typically deployed together.

2. Codex P2 — "credential" vs "email-password" trusted provider slug (better-auth.ts:24)Likely incorrect suggestion

Better Auth uses "credential" as the provider ID for email/password accounts internally. The Better Auth account linking docs list "credential" as the correct value. The Codex reviewer appears to be mistaken here — "credential" is correct.

3. CodeRabbit — Guard ordering bug (email.ts:98-100)Valid bug, should fix

This is a real issue. Line 98 constructs new URL("/accept-invitation", consoleUrl) before checking if consoleUrl is defined on line 100. If consoleUrl is undefined, this throws a TypeError. Compare with sendVerificationOtpEmail (lines 55-56) where guards come first. The fix is straightforward — move the guards above the URL construction:

-  const acceptUrl = new URL("/accept-invitation", consoleUrl);
   if (!hasSmtpConfig()) return;
   if (!consoleUrl) return console.warn("Missing origin header, cannot send invitation email");
+  const acceptUrl = new URL("/accept-invitation", consoleUrl);

Fix this →

4. CodeRabbit nitpick — role="alert" on error div (signup/route.tsx:78) — Nice-to-have

Adding role="alert" to the error message would improve screen reader accessibility. Minor enhancement, not blocking.


Summary

Only comment #3 (guard ordering in sendOrganizationInvitationEmail) is a real bug that should be fixed before merge. The trusted provider slug ("credential") is correct as-is. The SMTP mismatch is acknowledged and accepted. The accessibility improvement is optional.

Want me to push the fix for the guard ordering?

@heiwen

heiwen commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

@claude fix 3 and 4. for 2, I verified in the source code that "email-password" is correct, which is also in the reference docs here: https://better-auth.com/docs/reference/options

@hebo-agent

hebo-agent Bot commented Mar 20, 2026

Copy link
Copy Markdown

Claude finished @heiwen's task in 54s —— View job


Fixing review comments

All three fixes applied in commit 68c3401:

  1. "credential""email-password" in apps/auth/src/better-auth.ts:24 — corrected the trusted provider slug per the Better Auth reference docs
  2. Guard reordering in apps/auth/src/lib/email.ts:98-100 — moved hasSmtpConfig() and consoleUrl checks before new URL() construction to prevent TypeError when consoleUrl is undefined
  3. role="alert" added to error messages in both password.tsx and signup/route.tsx for screen reader accessibility

github-actions Bot and others added 2 commits March 20, 2026 10:17
- Change trustedProviders slug from "credential" to "email-password"
- Reorder guards before URL construction in sendOrganizationInvitationEmail
- Add role="alert" to error messages for accessibility

Co-authored-by: Heinrich Wendel <heiwen@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 the current code and only fix it if needed.

Inline comments:
In `@apps/console/app/routes/_auth.signin/route.tsx`:
- Around line 27-30: The decorative icon elements (the span with className
"relative" containing Ban and CreditCard) are being read by screen readers; mark
them as presentation-only by adding aria-hidden="true" (and role="presentation"
if your icon library requires) to the decorative container or directly to the
Ban and CreditCard components so they are ignored by assistive tech; update the
span (or the Ban and CreditCard JSX) to include aria-hidden="true" to hide these
decorative icons from screen readers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 634fe850-f99e-4e21-9b46-88d36135ec94

📥 Commits

Reviewing files that changed from the base of the PR and between c46951a and cebfe57.

📒 Files selected for processing (8)
  • apps/auth/src/better-auth.ts
  • apps/auth/src/lib/email.ts
  • apps/console/app/routes/_auth.accept-invitation/route.tsx
  • apps/console/app/routes/_auth.signin/magiclink.tsx
  • apps/console/app/routes/_auth.signin/password.tsx
  • apps/console/app/routes/_auth.signin/route.tsx
  • apps/console/app/routes/_auth.signup/route.tsx
  • apps/console/app/routes/_auth/route.tsx
✅ Files skipped from review due to trivial changes (3)
  • apps/console/app/routes/_auth.signin/magiclink.tsx
  • apps/console/app/routes/_auth.accept-invitation/route.tsx
  • apps/console/app/routes/_auth/route.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/console/app/routes/_auth.signin/password.tsx
  • apps/console/app/routes/_auth.signup/route.tsx
  • apps/auth/src/lib/email.ts
  • apps/auth/src/better-auth.ts

Comment thread apps/console/app/routes/_auth.signin/route.tsx Outdated
heiwen and others added 2 commits March 20, 2026 18:45
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@heiwen heiwen requested a review from turisanapo March 20, 2026 10:47
@heiwen

heiwen commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

@claude we still have a gap here. If no SMTP server is set, the invitation url for organization / team member invites can never be seen. how to address this?

@hebo-agent

hebo-agent Bot commented Mar 20, 2026

Copy link
Copy Markdown

Claude finished @heiwen's task in 50s —— View job


Analyzing invitation flow without SMTP

  • Read current invitation email code
  • Investigate how invitations are created and sent
  • Propose solution

Good catch. Here's the gap:

When hasSmtpConfig() returns false, sendOrganizationInvitationEmail (apps/auth/src/lib/email.ts:98) silently returns. The invitation record is still created in the database (Better Auth creates it before calling sendInvitationEmail), but the accept URL (/accept-invitation?id=...) is never shown to anyone. The invitation is effectively invisible.

Options to address this

Option A: Log the invitation URL to console (simplest)
When SMTP is not configured, log the full accept URL to the server console. This mirrors how dev tools typically handle emails — the admin can copy/paste and share the link manually. Quick to implement, good for self-hosted / dev scenarios.

Option B: Return the invitation URL in the API response
Have sendInvitationEmail signal back that email wasn't sent, and surface the accept URL in the console UI after inviting a member (e.g., a copyable link in a toast/dialog). This is the best UX for self-hosted deployments without SMTP, but requires changes to both the auth hook and the members settings page.

Option C: Show pending invitations with accept links in the members list
The members settings page could display pending invitations with their accept URLs visible to admins, so they can copy and share them. This is complementary to either A or B.

Recommendation

I'd suggest Option A as a quick fix (log the URL when SMTP isn't available — matches the pattern used in dev tools) and potentially Option B as a follow-up for a polished UX. Option A can be done in a few lines in sendOrganizationInvitationEmail.

Want me to implement one of these? If so, which approach do you prefer?


View job

@heiwen

heiwen commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

@claude I like option C, it's like of a copy button for invitation links, right? I prefer it behind a button, instead of a full link visibility that spoils the UX. Maybe combine it into the existing "invited" batch? Is it possible though, or is the invitation link, not accessible anymore after it was created?

@hebo-agent

hebo-agent Bot commented Mar 20, 2026

Copy link
Copy Markdown

Claude finished @heiwen's task in 53s —— View job


Investigating invitation link feasibility

  • Read invitation email code to understand link structure
  • Find how invitations are listed in the members UI
  • Determine if invitation ID is available after creation
  • Provide recommendation

Analysis

Yes, this is fully feasible! Here's why:

  1. The invitation ID persists in the database — Better Auth creates the invitation record before calling sendInvitationEmail. The OrgInvitation type (apps/console/app/lib/auth/types.ts:46-52) already includes the id field.

  2. The accept URL is trivially reconstructable — It's just /accept-invitation?id={invitationId} (see apps/auth/src/lib/email.ts:101-103). No tokens, no signatures — just the invitation ID, which is already available in the members list.

  3. The inv.id is already used in the UI — The members table (apps/console/app/routes/_shell.agent.$agentSlug.settings/members.tsx:117-144) already iterates over invitations and has access to inv.id (used by the "Revoke" button on line 140).

Suggested approach

Add a copy-link button next to the existing "Invited" badge (line 134) or in the actions column next to the "Revoke" button (line 140). Something like:

// Next to the Revoke button, when SMTP is not configured (or always, for convenience)
<CopyInvitationLinkButton invitationId={inv.id} />

The button would construct the URL client-side:

function CopyInvitationLinkButton({ invitationId }: { invitationId: string }) {
  const url = `${window.location.origin}/accept-invitation?id=${invitationId}`;
  // copy to clipboard, show toast/tooltip confirmation
}

However — I'd suggest this as a separate follow-up PR rather than adding it to this one, since this PR is focused on the password auth feature and is already reviewed. The invitation copy link is a distinct UX feature that benefits from its own review cycle. It also applies regardless of SMTP config (it's useful even with SMTP as a "resend" alternative).

Want me to create a new issue for this, or implement it directly in this PR?


View job

@heiwen

heiwen commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

@claude let's do it in this PR, otherwise we have a functional regression

@hebo-agent

hebo-agent Bot commented Mar 20, 2026

Copy link
Copy Markdown

Claude finished @heiwen's task in 1m 26s —— View job


Adding copy invitation link button

  • Read members settings page and understand current UI
  • Implement copy invitation link button
  • Commit and push

Added a copy invitation link button (link icon) next to the Revoke button for pending invitations in apps/console/app/routes/_shell.agent.$agentSlug.settings/members.tsx. When clicked, it copies the /accept-invitation?id=... URL to clipboard and shows a green checkmark for 2 seconds as confirmation.

This ensures admins can share invitation links manually when SMTP is not configured, closing the functional gap where invitations were created but the accept URL was invisible.

Pushed in commit e208e07.

View job

Adds a copy-to-clipboard button next to the Revoke button for pending
invitations, so admins can manually share the accept URL when SMTP
is not configured.

Co-authored-by: Heinrich Wendel <heiwen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@heiwen

heiwen commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

@claude we have an existing CopyButton component, how about you generalize that for this use case instead of creating a new one?

@hebo-agent

hebo-agent Bot commented Mar 20, 2026

Copy link
Copy Markdown

Claude finished @heiwen's task in 1m 31s —— View job


Refactored to use existing CopyButton component

  • Find existing CopyButton component
  • Replace CopyInvitationLinkButton with CopyButton from shared-ui
  • Commit and push

Replaced the custom CopyInvitationLinkButton (18 lines) with the existing CopyButton from @hebo/shared-ui/components/CopyButton, which already provides clipboard copy, check icon feedback, tooltip, and error handling. The invitation URL is constructed inline as the value prop.

Pushed in commit dd5ac8e.

View job

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 the current code and only fix it if needed.

Inline comments:
In `@apps/console/app/routes/_shell.agent`.$agentSlug.settings/members.tsx:
- Around line 233-239: handleCopy currently calls
navigator.clipboard.writeText(...) without handling rejections; update the
handleCopy function to catch failures and provide fallback UI/behavior: wrap the
clipboard write in a try/catch (or add .catch()) around
navigator.clipboard.writeText(url), on success continue to call setCopied(true)
and clear after timeout, on failure set an error state (e.g., setCopyError or
setCopied(false)) and surface a user-visible message or fallback copy mechanism
(like opening a prompt with the URL or selecting text for manual copy). Ensure
you reference and update the handleCopy function and use existing state setters
(setCopied) and add a new state setter (setCopyError or similar) so failures are
handled without unhandled promise rejections.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1fbbaa54-3bc8-4226-b11a-059078d11a57

📥 Commits

Reviewing files that changed from the base of the PR and between cebfe57 and e208e07.

📒 Files selected for processing (3)
  • apps/console/app/routes/_auth.signin/password.tsx
  • apps/console/app/routes/_auth.signin/route.tsx
  • apps/console/app/routes/_shell.agent.$agentSlug.settings/members.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/console/app/routes/_auth.signin/route.tsx
  • apps/console/app/routes/_auth.signin/password.tsx

Comment thread apps/console/app/routes/_shell.agent.$agentSlug.settings/members.tsx Outdated
Replace custom CopyInvitationLinkButton with the existing CopyButton
component from @hebo/shared-ui, which already handles clipboard copy,
check icon feedback, and tooltip.

Co-authored-by: Heinrich Wendel <heiwen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@heiwen

heiwen commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

@turisanapo for final review

@turisanapo turisanapo merged commit 3fb85ab into main Mar 21, 2026
7 checks passed
@turisanapo turisanapo deleted the claude-issue-299-20260320-0932 branch March 21, 2026 02:41
This was referenced Mar 27, 2026
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.

Password-based auth flow for self-hosted distribution

2 participants