Skip to content

Add Anonymous/Guest User Authentication with Bitcoin-only Payment Restrictions #287

@AnthonyRonning

Description

@AnthonyRonning

Overview

Implement anonymous/guest user authentication flow with strict warnings and Bitcoin-only payment restrictions. Guest users must understand the risks and limitations before creating an account.

Background Research

OpenSecret SDK Guest Authentication

The SDK provides three main methods for guest users:

  • signUpGuest(password, inviteCode) - Returns { id: uuid, access_token, refresh_token }
    • UUID is server-generated
    • Password is user-provided
  • signInGuest(id, password) - Signs in with UUID + password
  • convertGuestToUserAccount(email, password, name?) - Upgrades guest to email account

User Identification

Guest users can be identified by:

  • os.auth.user.user.login_method === "Guest"
  • os.auth.user.user.email === null

Existing Patterns

  • VerificationModal - Template for modal dialogs that block usage
  • AccountDialog - Already checks login_method === "email" for conditional features
  • Billing system works the same for guest users

Requirements

1. Guest Signup Flow

Route: @frontend/src/routes/signup.tsx

Flow:

  1. Add "Sign up as Guest" button to signup method selection
  2. When clicked, show comprehensive warning dialog with:
    • ⚠️ MUST pay for a full year in Bitcoin only (no Stripe, no monthly)
    • ⚠️ Absolutely no support available
    • ⚠️ MUST backup their account UUID - will never be shown again
    • ⚠️ No password recovery - we cannot help if they lose credentials
    • Clear "I understand" checkbox(es) required before proceeding
  3. After accepting warnings, collect password (standard password field)
  4. Call os.signUpGuest(password, inviteCode)
  5. Show credentials dialog with:
    • Their generated UUID (with copy button)
    • Hidden password field (eyeball to reveal, copy button)
    • Final warning to save both securely
    • Emphatic message: "This is your ONLY chance to see your account UUID"

2. Guest Login Flow

Route: @frontend/src/routes/login.tsx

Flow:

  1. Add "Log in as Guest" button to login method selection
  2. When clicked, show login form with:
    • Account UUID field (instead of email)
    • Password field
  3. Call os.signInGuest(uuid, password)

3. Guest Payment Warning Dialog

Location: Homepage (@frontend/src/routes/index.tsx)

Trigger: Show when user is on main chat page AND:

  • os.auth.user.user.login_method === "Guest"
  • billingStatus.product_name === "Free" (or product_name.toLowerCase().includes("free"))

Behavior:

  • Similar to VerificationModal - blocks chat usage until paid
  • Clear message: "Guest accounts must subscribe to a paid plan"
  • Button to go to pricing page
  • Log out option

Exception: Do NOT show this dialog on the pricing page itself (they're trying to pay)

4. Pricing Page Restrictions

Route: @frontend/src/routes/pricing.tsx

Enforce for Guest Users:

  • Auto-enable Bitcoin toggle (disable ability to turn it off)
  • Only show yearly pricing with 10% discount
  • Disable/hide monthly payment options completely
  • Clear badge/indicator showing "Guest Account - Bitcoin Only"
  • Team plan should be disabled (not available for guests)

5. Account Dialog Restrictions

Component: @frontend/src/components/AccountDialog.tsx

Current behavior: Already hides "Change Password" for non-email users

Required:

  • Keep Change Password available for guests (same as email users)
  • Password reset is handled through SDK's standard flow
  • Display "Guest Account" badge/indicator in account info

6. Password Reset/Recovery

Routes: /password-reset, /password-reset/confirm

Behavior:

  • Password changes are ALLOWED (with current password verification)
  • These work through the SDK's standard password change flow
  • No special handling needed - SDK manages this

Technical Implementation Details

Components to Create

1. GuestSignupWarningDialog.tsx

  • Comprehensive warning modal
  • Multiple checkboxes for each warning point
  • "I Understand and Accept" button (disabled until all boxes checked)
  • Clear, emphatic warning text styling

2. GuestCredentialsDialog.tsx

  • Shows UUID prominently with copy button
  • Optional: Shows password with eyeball toggle + copy button
  • Large warning banner about saving credentials
  • "I have saved my credentials" checkbox before allowing to proceed
  • On close, navigates to pricing or main page

3. GuestPaymentWarningDialog.tsx

  • Similar structure to VerificationModal
  • Shown on main chat page for unpaid guests
  • Cannot be dismissed (except by paying or logging out)
  • Link to pricing page
  • Log out button

Files to Modify

  1. @frontend/src/routes/signup.tsx

    • Add "Sign up as Guest" button to method selection
    • Integrate warning dialog flow
    • Handle signUpGuest call
    • Show credentials dialog after signup
  2. @frontend/src/routes/login.tsx

    • Add "Log in as Guest" button to method selection
    • Create guest login form (UUID + password fields)
    • Handle signInGuest call
  3. @frontend/src/routes/index.tsx

    • Add guest payment warning dialog
    • Check conditions: login_method === "Guest" AND on free plan
    • Don't show on pricing page
  4. @frontend/src/routes/pricing.tsx

    • Detect guest users via login_method
    • Force Bitcoin toggle ON for guests (disable Stripe)
    • Disable toggle switch for guests
    • Show "Guest Account - Bitcoin Only" badge
    • Disable team plan for guests
    • Only show yearly pricing
  5. @frontend/src/components/AccountDialog.tsx

    • Add guest account indicator
    • Keep password change enabled for guests
    • No special restrictions needed (already handled)

State Management

Use existing patterns:

  • useOpenSecret() hook for auth state
  • Check os.auth.user.user.login_method === "Guest"
  • Use useLocalState() for billingStatus
  • React useState for dialog states

Testing Checklist

  • Guest signup shows all warning dialogs in correct order
  • UUID is displayed correctly after signup with copy functionality
  • Guest login works with UUID + password
  • Guest payment warning shows on homepage (free plan only)
  • Guest payment warning does NOT show on pricing page
  • Pricing page forces Bitcoin-only for guests
  • Team plan is disabled for guests
  • Account dialog shows guest indicator
  • Password change works for guests
  • Guest can upgrade to paid plan via Bitcoin
  • After payment, guest can use chat normally
  • Guest cannot enable Stripe payments
  • All warnings are clear and emphatic
  • Copy buttons work for UUID
  • Run bun run format and bun run lint - all pass

Security Considerations

  1. No password recovery - Guest accounts cannot reset password without their UUID
  2. UUID is sensitive - Treated as account identifier, must be kept secure
  3. No support - Clearly communicated, no exception
  4. Bitcoin-only enforcement - Prevents App Store payment issues, maintains anonymity
  5. One-time credential display - UUID shown only once after signup

Design Notes

  • Use existing component patterns (VerificationModal, AlertDestructive)
  • Warning dialogs should be visually distinct (warning colors, icons)
  • Multiple confirmation checkboxes for critical warnings
  • Clear, non-technical language in warnings
  • Mobile-responsive design

Related Files

  • /Users/tony/Dev/OpenSecret/OpenSecret-SDK/src/lib/main.tsx (SDK methods)
  • @frontend/src/components/VerificationModal.tsx (pattern reference)
  • @frontend/src/components/AccountDialog.tsx (restrictions)
  • @frontend/src/routes/signup.tsx
  • @frontend/src/routes/login.tsx
  • @frontend/src/routes/pricing.tsx
  • @frontend/src/routes/index.tsx

Implementation Order

  1. Create dialog components (warnings, credentials display)
  2. Modify signup flow
  3. Modify login flow
  4. Add pricing page restrictions
  5. Add homepage payment warning
  6. Update account dialog
  7. Testing and verification
  8. Run format and lint

Priority: High
Estimated Effort: 6-8 hours
Dependencies: OpenSecret SDK (existing)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions