From fd4c655f5ae0c2e23a4db697b8489827b49f4144 Mon Sep 17 00:00:00 2001 From: "Builder.io" Date: Tue, 11 Nov 2025 22:09:35 +0000 Subject: [PATCH] Email Linking System Documentation cgen-549a90ed4b7a4a8f877d5c4fd75b2ca7 --- docs/EMAIL_LINKING_SYSTEM.md | 223 +++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 docs/EMAIL_LINKING_SYSTEM.md diff --git a/docs/EMAIL_LINKING_SYSTEM.md b/docs/EMAIL_LINKING_SYSTEM.md new file mode 100644 index 00000000..b3da4d3f --- /dev/null +++ b/docs/EMAIL_LINKING_SYSTEM.md @@ -0,0 +1,223 @@ +# Email Linking System + +## Overview + +The email linking system allows users to authenticate with multiple email addresses that all resolve to the same account. This is particularly useful for developers with both work (`@aethex.dev`) and personal email addresses. + +## Architecture + +### Database Tables + +#### `user_email_links` +Links multiple email addresses to a single user account. + +```sql +- id: UUID (primary key) +- user_id: UUID (FK to user_profiles.user_id) +- email: TEXT (unique) +- is_primary: BOOLEAN (marks the main email) +- verified_at: TIMESTAMP +- linked_at: TIMESTAMP +- created_at: TIMESTAMP +- updated_at: TIMESTAMP +``` + +#### `user_profiles` (additions) +```sql +- primary_email: TEXT (the primary email for the account) +- is_dev_account: BOOLEAN (marks if this is a developer account) +- merged_to_user_id: UUID (if this account was merged, points to the primary account) +``` + +## User Flows + +### Flow 1: Login with Linked Email + +``` +User attempts login with: mrpiglr@gmail.com +↓ +SignIn catches "invalid credentials" error +↓ +Calls /api/user/resolve-linked-email with email +↓ +Check user_email_links table +↓ +Found! Returns primary email: mrpiglr@aethex.dev +↓ +Retry SignIn with primary email +↓ +Success - user logged in +``` + +### Flow 2: Link Additional Email (Settings) + +``` +User clicks "Link Email" in settings +↓ +Enters secondary email: mrpiglr@gmail.com +↓ +Verification sent to that email +↓ +User verifies via link +↓ +Email added to user_email_links with is_primary=false +↓ +UI shows: "Also logged in as mrpiglr@gmail.com" +``` + +## API Endpoints + +### POST `/api/user/resolve-linked-email` + +Resolve a linked email to its primary email address. + +**Request:** +```json +{ + "email": "mrpiglr@gmail.com" +} +``` + +**Response (linked email):** +```json +{ + "primaryEmail": "mrpiglr@aethex.dev", + "linkedFrom": "mrpiglr@gmail.com", + "userId": "uuid-here" +} +``` + +**Response (non-linked email):** +```json +{ + "primaryEmail": "some@email.com" +} +``` + +### POST `/api/user/link-email` + +Link two existing user accounts by merging one into the other. + +**Request:** +```json +{ + "primaryEmail": "mrpiglr@aethex.dev", + "linkedEmail": "mrpiglr@gmail.com" +} +``` + +**Response:** +```json +{ + "success": true, + "message": "Successfully linked mrpiglr@gmail.com to mrpiglr@aethex.dev", + "targetUserId": "primary-user-uuid", + "sourceUserId": "linked-user-uuid" +} +``` + +### POST `/api/user/link-mrpiglr-accounts` (Admin Only) + +Special endpoint to link the mrpiglr accounts. + +**Request:** +```bash +curl -X POST https://aethex.dev/api/user/link-mrpiglr-accounts \ + -H "Authorization: Bearer mrpiglr-admin-token" \ + -H "Content-Type: application/json" +``` + +**Response:** +```json +{ + "success": true, + "message": "Successfully linked mrpiglr@aethex.dev and mrpiglr@gmail.com", + "primaryEmail": "mrpiglr@aethex.dev", + "linkedEmail": "mrpiglr@gmail.com", + "note": "Both emails can now log in and will access the same account." +} +``` + +## Implementation Details + +### Authentication Resolution + +When a user tries to sign in with a linked email: + +1. **First attempt**: Try with provided email (normal auth flow) +2. **If it fails with "invalid credentials"**: + - Check `/api/user/resolve-linked-email` + - If email is linked, get primary email + - **Retry with primary email** + - If successful, user is logged in + +This is transparent to the user - they can log in with any linked email. + +### Data Transfer on Merge + +When two accounts are merged: + +1. **Achievements**: Transferred to primary account +2. **Creator Profile**: Transferred or preserved if not duplicate +3. **Applications**: Transferred to primary account +4. **Discord Links**: Transferred (avoiding duplicates) +5. **Web3 Wallets**: Transferred (avoiding duplicates) +6. **Email Links**: Both emails added to user_email_links table +7. **Profile**: Source profile marked as `merged_to_user_id` + +### For Developers (Dev Accounts) + +Developer accounts with `@aethex.dev` email: +- `is_dev_account = true` +- `primary_email = "@aethex.dev email"` +- Public profile shows work email +- Can link personal email for authentication convenience + +## Usage Examples + +### Link mrpiglr Accounts + +```bash +# Admin endpoint (one-time setup) +curl -X POST https://aethex.dev/api/user/link-mrpiglr-accounts \ + -H "Authorization: Bearer mrpiglr-admin-token" \ + -H "Content-Type: application/json" +``` + +### Link Any Two Accounts + +```bash +# Generic link endpoint +curl -X POST https://aethex.dev/api/user/link-email \ + -H "Content-Type: application/json" \ + -d '{ + "primaryEmail": "user@aethex.dev", + "linkedEmail": "user@gmail.com" + }' +``` + +### Check Email Resolution + +```bash +curl -X POST https://aethex.dev/api/user/resolve-linked-email \ + -H "Content-Type: application/json" \ + -d '{"email": "user@gmail.com"}' +``` + +## Database Migration + +Applied via: `code/supabase/migrations/20250206_add_email_linking.sql` + +Includes: +- `user_email_links` table with RLS policies +- `get_primary_user_by_email()` function +- Columns on `user_profiles` for dev accounts and primary email +- Proper indexes for performance + +## Future Enhancements + +1. **Email Verification**: Add verification flow before linking new emails +2. **Settings UI**: Add "Linked Emails" section in user settings +3. **Email Change Request**: Allow users to change primary email +4. **Admin Dashboard**: View all linked emails for a user +5. **Notification**: Email both addresses when a new email is linked