Complete Discord Flow Documentation - All 5 Flows
cgen-e654a0d40a06493387754bb68f0e21c9
This commit is contained in:
parent
0575151ffe
commit
32a8bf47a3
1 changed files with 543 additions and 0 deletions
543
docs/DISCORD-COMPLETE-FLOWS.md
Normal file
543
docs/DISCORD-COMPLETE-FLOWS.md
Normal file
|
|
@ -0,0 +1,543 @@
|
|||
# AeThex Discord System - Complete Flow Documentation
|
||||
|
||||
## Overview
|
||||
There are 5 completely separate Discord flows in AeThex. Each one is independent but some share infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## FLOW 1: Discord OAuth Login
|
||||
**When**: User clicks "Continue with Discord" on `/login` page
|
||||
**Goal**: Create new account OR link Discord to existing email
|
||||
**Files Involved**: Login.tsx → oauth/start.ts → oauth/callback.ts
|
||||
|
||||
### Step-by-Step
|
||||
|
||||
```
|
||||
┌─ User on /login page
|
||||
│
|
||||
├─ Clicks "Continue with Discord" button
|
||||
│ └─ code/client/pages/Login.tsx line ~180-185
|
||||
│
|
||||
├─ Browser → /api/discord/oauth/start (GET)
|
||||
│ └─ code/api/discord/oauth/start.ts
|
||||
│ • Builds Discord OAuth URL
|
||||
│ • No state needed for login flow
|
||||
│ • Redirects to: https://discord.com/api/oauth2/authorize?client_id=...
|
||||
│
|
||||
├─ User authorizes on Discord
|
||||
│ └─ Discord redirects to: /api/discord/oauth/callback?code=XXX&state=...
|
||||
│
|
||||
├─ Backend processes callback (GET)
|
||||
│ └─ code/api/discord/oauth/callback.ts
|
||||
│
|
||||
│ A) Parse state (action will be undefined or "login")
|
||||
│ B) Exchange code for Discord access token
|
||||
│ C) Fetch Discord user profile (id, username, email, avatar)
|
||||
│ D) Check if email already in Supabase auth
|
||||
│ └─ If YES: Just link to existing user (don't create)
|
||||
│ └─ If NO: Create new auth user with email
|
||||
│ E) Create/update user_profiles record (upsert)
|
||||
│ F) Create discord_links record (links discord_id → user_id)
|
||||
│ G) Create session (login user automatically)
|
||||
<EFBFBD><EFBFBD> H) Redirect to /dashboard or /onboarding based on profile_complete
|
||||
│
|
||||
└─ ✅ User logged in with Discord account linked
|
||||
```
|
||||
|
||||
### Database Operations (Login Flow)
|
||||
```
|
||||
discord_links table:
|
||||
INSERT: { discord_id: "123", user_id: "uuid", linked_at: now() }
|
||||
|
||||
user_profiles table:
|
||||
UPSERT: { id: user_id, full_name: discord_username, email, avatar_url }
|
||||
|
||||
auth.users table:
|
||||
INSERT: { email, user_metadata: { full_name, avatar_url } }
|
||||
(only if email doesn't already exist)
|
||||
```
|
||||
|
||||
### Success Path
|
||||
✅ User sees dashboard or onboarding screen
|
||||
✅ User is fully logged in
|
||||
✅ Discord account is linked
|
||||
|
||||
### Failure Paths
|
||||
❌ Email already exists → Redirect to `/login?error=account_exists&message=...`
|
||||
- User must sign in with email first, then link from Dashboard
|
||||
❌ Auth user creation fails → Redirect to `/login?error=auth_create`
|
||||
❌ Profile creation fails → Redirect to `/login?error=profile_create`
|
||||
❌ Discord link creation fails → Redirect to `/login?error=link_create`
|
||||
|
||||
---
|
||||
|
||||
## FLOW 2: Discord Account Linking (from Dashboard)
|
||||
**When**: User clicks "Link Discord" button in `/dashboard?tab=connections`
|
||||
**Goal**: Add Discord account to existing AeThex account (user already logged in)
|
||||
**Files Involved**: Dashboard.tsx → AuthContext.linkProvider() → oauth/start.ts → oauth/callback.ts
|
||||
|
||||
### Step-by-Step
|
||||
|
||||
```
|
||||
┌─ User on /dashboard?tab=connections (ALREADY LOGGED IN)
|
||||
│
|
||||
├─ Clicks "Link Discord" button
|
||||
│ └─ code/client/pages/Dashboard.tsx line ~283-290
|
||||
│ Calls: AuthContext.linkProvider("discord")
|
||||
│
|
||||
├─ AuthContext.linkProvider("discord")
|
||||
│ └─ code/client/contexts/AuthContext.tsx line ~700-770
|
||||
│
|
||||
│ A) Get current user's auth token
|
||||
│ └─ const session = await supabase.auth.getSession()
|
||||
│
|
||||
│ B) POST to /api/discord/create-linking-session
|
||||
│ └─ code/server/index.ts line ~871-911
|
||||
│ • Validates auth token
|
||||
│ • Creates temporary session in discord_linking_sessions table
|
||||
│ • Returns: { token: sessionToken } (5 min expiry)
|
||||
│
|
||||
│ C) Build Discord OAuth URL with state containing:
|
||||
│ {
|
||||
│ action: "link",
|
||||
│ sessionToken: sessionToken,
|
||||
│ redirectTo: "/dashboard?tab=connections"
|
||||
│ }
|
||||
│
|
||||
│ D) Browser → https://discord.com/api/oauth2/authorize?...
|
||||
│
|
||||
├─ User authorizes on Discord
|
||||
│ └─ Discord redirects to: /api/discord/oauth/callback?code=XXX&state=...
|
||||
│
|
||||
├─ Backend processes callback (GET)
|
||||
│ └─ code/api/discord/oauth/callback.ts line ~38-100
|
||||
│
|
||||
│ A) Parse state
|
||||
│ └─ stateData.action === "link" <20><><EFBFBD> (this is linking flow)
|
||||
│ └─ stateData.sessionToken: "hex string"
|
||||
│
|
||||
│ B) Look up session in discord_linking_sessions table
|
||||
│ └─ if expired or not found → Redirect to login with error
|
||||
│
|
||||
│ C) Extract authenticatedUserId from session
|
||||
│
|
||||
│ D) Exchange code for Discord access token
|
||||
│
|
||||
│ E) Fetch Discord user profile (id, username, email)
|
||||
│
|
||||
│ F) Check if Discord ID already linked to different user
|
||||
│ └─ if YES: Show error (Discord can only be linked once)
|
||||
│ └─ if NO: Continue
|
||||
│
|
||||
│ G) Create discord_links record with authenticatedUserId
|
||||
│
|
||||
│ H) Delete the temporary session (cleanup)
|
||||
│
|
||||
│ I) Redirect back to /dashboard?tab=connections
|
||||
│ └─ User sees page refresh, Discord is now linked
|
||||
│
|
||||
└─ ✅ Discord account linked to existing AeThex account
|
||||
```
|
||||
|
||||
### Database Operations (Linking Flow)
|
||||
```
|
||||
discord_linking_sessions table:
|
||||
INSERT: { user_id: uuid, session_token: "hex", expires_at: now+5min }
|
||||
DELETE: WHERE session_token = sessionToken (cleanup)
|
||||
|
||||
discord_links table:
|
||||
UPSERT: { discord_id: "123", user_id: uuid, linked_at: now() }
|
||||
```
|
||||
|
||||
### Success Path
|
||||
✅ Browser redirects to `/dashboard?tab=connections`
|
||||
✅ Discord appears as "linked" in connections section
|
||||
✅ User can now use /verify command in Discord to link roles
|
||||
|
||||
### Failure Paths
|
||||
❌ Auth token missing/invalid → User sees "Auth failed" toast
|
||||
❌ Session creation fails → User sees "Link failed" toast
|
||||
❌ Session expired during OAuth redirect → Redirect to login
|
||||
❌ Discord ID already linked to different account → Redirect to login with error
|
||||
|
||||
### Critical: Session Persistence
|
||||
⚠️ **KEY ISSUE THAT WAS FIXED**:
|
||||
- During Discord OAuth redirect (step 2D above), browser leaves aethex.dev
|
||||
- Session cookies might not be sent to Discord redirect back
|
||||
- **SOLUTION**: We store user_id in temporary database session (discord_linking_sessions)
|
||||
- On callback, we extract user_id from database, not from cookies
|
||||
- This guarantees linking works even if cookies get lost
|
||||
|
||||
---
|
||||
|
||||
## FLOW 3: Discord Verification Code (Bot /verify Command)
|
||||
**When**: User types `/verify` in Discord, bot sends code, user clicks link
|
||||
**Goal**: Link Discord account without OAuth flow (alternative to Flow 2)
|
||||
**Files Involved**: bot.js /verify command → DiscordVerify.tsx → api/discord/verify-code.ts
|
||||
|
||||
### Step-by-Step
|
||||
|
||||
```
|
||||
┌─ User in Discord
|
||||
│
|
||||
├─ Types /verify command
|
||||
│ └─ code/discord-bot/commands/verify.js
|
||||
│
|
||||
│ A) Bot generates 6-digit code
|
||||
│ B) Stores in discord_verifications table:
|
||||
│ { discord_id, verification_code, expires_at: now+15min }
|
||||
│ C) Sends message with link:
|
||||
│ "https://aethex.dev/discord-verify?code=123456"
|
||||
│
|
||||
├─ User clicks link
|
||||
│ └─ Browser goes to /discord-verify?code=123456
|
||||
│ code/client/pages/DiscordVerify.tsx
|
||||
│
|
||||
│ A) Check if user is logged in
|
||||
│ └─ if NO: Redirect to /login?next=/discord-verify?code=123456
|
||||
│ (code is preserved in URL)
|
||||
│
|
||||
│ B) If NOT logged in:
|
||||
│ • User logs in with email/password or OAuth
|
||||
│ • Browser returns to /discord-verify?code=123456
|
||||
│
|
||||
│ C) Show form with verification code (pre-filled if from URL)
|
||||
│
|
||||
│ D) User clicks "Verify" button
|
||||
│
|
||||
│ E) Frontend calls POST /api/discord/verify-code
|
||||
│ └─ code/api/discord/verify-code.ts
|
||||
│
|
||||
│ A) Get current user ID from session
|
||||
│ B) Query discord_verifications table for matching code
|
||||
│ C) Check if code is not expired
|
||||
│ D) Check if Discord ID already linked to different user
|
||||
│ E) Create discord_links record
|
||||
│ F) Delete the used verification code
|
||||
│ G) Return success
|
||||
│
|
||||
│ F) Frontend shows success message
|
||||
│
|
||||
│ G) Browser redirects to /dashboard?tab=connections
|
||||
│
|
||||
└─ ✅ Discord linked via verification code
|
||||
```
|
||||
|
||||
### Database Operations (Verification Flow)
|
||||
```
|
||||
discord_verifications table:
|
||||
INSERT: { discord_id: "123", verification_code: "456789", expires_at: now+15min }
|
||||
(done by bot.js)
|
||||
DELETE: WHERE verification_code = code (cleanup after verification)
|
||||
|
||||
discord_links table:
|
||||
INSERT: { discord_id: "123", user_id: uuid, linked_at: now() }
|
||||
```
|
||||
|
||||
### Success Path
|
||||
✅ Page shows "Discord linked successfully!"
|
||||
✅ Browser redirects to connections tab
|
||||
✅ Discord appears as linked
|
||||
|
||||
### Failure Paths
|
||||
❌ Code expired → Show error "Code expired, ask bot to run /verify again"
|
||||
❌ Code not found → Show error "Invalid code"
|
||||
❌ Discord ID already linked to different user → Show error "This Discord is already linked to another account"
|
||||
❌ User not logged in when clicking link → Redirect to login (code preserved)
|
||||
|
||||
### Why This Flow Exists
|
||||
- Simpler than OAuth (no redirect to discord.com)
|
||||
- Works if user's Discord is not verified with email
|
||||
- Manual process but more user-friendly for some
|
||||
|
||||
---
|
||||
|
||||
## FLOW 4: Discord Activity (Standalone SPA in Discord)
|
||||
**When**: User opens Activity in Discord desktop app
|
||||
**Goal**: Show AeThex dashboard inside Discord as an Activity
|
||||
**Files Involved**: Activity.tsx → DiscordActivityContext.tsx → api/discord/activity-auth.ts
|
||||
|
||||
### Step-by-Step
|
||||
|
||||
```
|
||||
┌─ User opens Discord Activity from context menu in Discord app
|
||||
│
|
||||
├─ Discord loads iframe with Activity URL
|
||||
│ └─ https://aethex.dev/activity (or deep link)
|
||||
│ code/client/pages/Activity.tsx
|
||||
│
|
||||
├─ Activity page initializes
|
||||
│ └─ code/client/contexts/DiscordActivityContext.tsx
|
||||
│
|
||||
│ A) Detect if running inside Discord iframe
|
||||
│ B) Initialize Discord SDK
|
||||
│ C) Get Discord access token from SDK
|
||||
│ D) POST to /api/discord/activity-auth with access token
|
||||
│ └─ code/api/discord/activity-auth.ts
|
||||
│
|
||||
├─ Backend validates and creates/updates user
|
||||
│ └─ code/api/discord/activity-auth.ts
|
||||
│
|
||||
│ A) Validate access token (from Discord SDK, not OAuth)
|
||||
│ B) Get current user ID from token (or create if new)
|
||||
│ C) Query user_profiles for that user
|
||||
│ D) If user doesn't exist:
|
||||
│ • Create with defaults: primary_arm="labs", user_type="community_member"
|
||||
│ E) Return user profile data
|
||||
│
|
||||
├─ Activity page displays
|
||||
│ └─ Shows user profile (name, avatar, discord_id)
|
||||
│ └─ Shows current realm/arm
|
||||
│ └─ Shows quick action buttons (browse, opportunities, settings)
|
||||
│
|
||||
├─ User can click buttons
|
||||
│ └─ Each button opens new tab: window.open(url, "_blank")
|
||||
│ └─ Keeps Activity in Discord while main app opens in browser tab
|
||||
│
|
||||
└─ ✅ Activity displayed successfully
|
||||
```
|
||||
|
||||
### Database Operations (Activity Flow)
|
||||
```
|
||||
user_profiles table:
|
||||
SELECT: WHERE id = user_id (from token)
|
||||
INSERT: IF NOT EXISTS with defaults
|
||||
```
|
||||
|
||||
### Success Path
|
||||
✅ Activity loads in Discord
|
||||
✅ Shows user profile
|
||||
✅ Buttons open links in new tabs
|
||||
✅ Activity stays in Discord
|
||||
|
||||
### Failure Paths
|
||||
❌ Not in Discord iframe → Show message "Open this in Discord Activity"
|
||||
❌ Token invalid → Show error "Authentication failed"
|
||||
❌ SDK failed to load → Show error "Discord SDK unavailable"
|
||||
|
||||
### Key Difference from Other Flows
|
||||
- This uses Discord SDK (embedded in iframe)
|
||||
- NOT OAuth (no redirect to discord.com)
|
||||
- NOT a regular login (Activity is ephemeral)
|
||||
- User is verified by Discord SDK internally
|
||||
|
||||
---
|
||||
|
||||
## FLOW 5: Discord Bot Commands
|
||||
**When**: User types slash commands in Discord
|
||||
**Goal**: Manage Discord account, set realm, view profile, etc.
|
||||
**Files Involved**: bot.js → /api/discord/interactions.ts
|
||||
|
||||
### Available Commands
|
||||
|
||||
#### /verify
|
||||
```
|
||||
User: /verify
|
||||
Bot: "Click to link: https://aethex.dev/discord-verify?code=123456"
|
||||
User: (clicks link, links Discord account)
|
||||
Bot: Role assignment happens (if set in discord_role_mappings)
|
||||
```
|
||||
Uses: Flow 3 (Verification Code)
|
||||
|
||||
#### /set-realm [arm]
|
||||
```
|
||||
User: /set-realm
|
||||
Bot: Shows dropdown with 5 arms (labs, gameforge, corp, foundation, devlink)
|
||||
User: Clicks one
|
||||
Bot: Updates discord_links.primary_arm
|
||||
Bot: Assigns Discord role based on arm + user_type mapping
|
||||
```
|
||||
|
||||
#### /profile
|
||||
```
|
||||
User: /profile
|
||||
Bot: Embeds card with user's AeThex profile
|
||||
(name, bio, avatar, primary_arm, avatar)
|
||||
```
|
||||
|
||||
#### /unlink
|
||||
```
|
||||
User: /unlink
|
||||
Bot: Removes discord_links record
|
||||
Bot: Removes all Discord roles assigned by AeThex
|
||||
User: Discord account no longer linked
|
||||
```
|
||||
|
||||
#### /verify-role
|
||||
```
|
||||
User: /verify-role
|
||||
Bot: Shows current assigned roles
|
||||
Bot: Shows expected roles from discord_role_mappings
|
||||
Bot: Option to auto-assign missing roles
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Schema
|
||||
|
||||
### discord_links
|
||||
```sql
|
||||
id UUID PRIMARY KEY
|
||||
discord_id TEXT UNIQUE NOT NULL -- Discord user ID
|
||||
user_id UUID NOT NULL REFERENCES user_profiles(id)
|
||||
primary_arm TEXT -- 'labs', 'gameforge', etc
|
||||
linked_at TIMESTAMP DEFAULT now()
|
||||
```
|
||||
**Used by**: All flows
|
||||
**Query patterns**:
|
||||
- Find user by discord_id (Flow 2, 3, 4, 5)
|
||||
- Find discord_id by user_id (Dashboard connections check)
|
||||
- Update primary_arm (Flow 5 /set-realm)
|
||||
|
||||
### discord_linking_sessions
|
||||
```sql
|
||||
id UUID PRIMARY KEY
|
||||
user_id UUID NOT NULL REFERENCES user_profiles(id)
|
||||
session_token TEXT UNIQUE NOT NULL -- Random hex string
|
||||
expires_at TIMESTAMP NOT NULL -- 5 minute expiry
|
||||
```
|
||||
**Used by**: Flow 2 (OAuth Linking)
|
||||
**Query patterns**:
|
||||
- Insert when user clicks "Link Discord" (create-linking-session endpoint)
|
||||
- Select when OAuth callback received (lookup user_id from token)
|
||||
- Delete after lookup (cleanup)
|
||||
|
||||
### discord_verifications
|
||||
```sql
|
||||
id UUID PRIMARY KEY
|
||||
discord_id TEXT NOT NULL -- Discord user ID
|
||||
verification_code TEXT UNIQUE NOT NULL
|
||||
expires_at TIMESTAMP NOT NULL -- 15 minute expiry
|
||||
```
|
||||
**Used by**: Flow 3 (Verification Code)
|
||||
**Query patterns**:
|
||||
- Insert when bot /verify command runs (generate code)
|
||||
- Select when user submits code (verify-code endpoint)
|
||||
- Delete after verification (cleanup)
|
||||
|
||||
### discord_role_mappings
|
||||
```sql
|
||||
id UUID PRIMARY KEY
|
||||
arm TEXT NOT NULL -- 'labs', 'gameforge', etc
|
||||
user_type TEXT NOT NULL -- 'game_developer', 'community_member', etc
|
||||
discord_role_name TEXT NOT NULL -- Role name in Discord
|
||||
discord_role_id TEXT -- Role ID (optional)
|
||||
server_id TEXT -- Optional (specific server)
|
||||
```
|
||||
**Used by**: Flow 5 (Bot role assignment)
|
||||
**Query patterns**:
|
||||
- Select by (arm, user_type) to find which role to assign
|
||||
- Managed in Admin panel
|
||||
|
||||
### discord_user_roles
|
||||
```sql
|
||||
id UUID PRIMARY KEY
|
||||
discord_id TEXT NOT NULL -- Discord user ID
|
||||
server_id TEXT NOT NULL -- Discord server ID
|
||||
role_id TEXT NOT NULL -- Discord role ID
|
||||
role_name TEXT NOT NULL -- Role name
|
||||
assigned_at TIMESTAMP DEFAULT now()
|
||||
last_verified TIMESTAMP -- When role was last verified
|
||||
UNIQUE(discord_id, server_id, role_id)
|
||||
```
|
||||
**Used by**: Flow 5 (Bot tracking)
|
||||
**Query patterns**:
|
||||
- Insert when role is assigned
|
||||
- Update when verified
|
||||
- Select to show /verify-role command
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
# Required
|
||||
DISCORD_CLIENT_ID="578971245454950421"
|
||||
DISCORD_CLIENT_SECRET="JKlilGzcTWgfmt2wEqiHO8wpCel5VEji"
|
||||
DISCORD_PUBLIC_KEY="d9771dd29e3a6f030cb313e33bb4b51384c7c36829bd551df714681dcf1e1eb0"
|
||||
DISCORD_BOT_TOKEN="NTc4OTcxMjQ1NDU0OTUwNDIx.GS3vNk.QbRXV0vC6OoUFxhChI6Tp-YEDVtT-pDqrfczvk"
|
||||
|
||||
# Optional
|
||||
DISCORD_ADMIN_REGISTER_TOKEN="aethex-link"
|
||||
DISCORD_BOT_HEALTH_URL="https://aethex.railway.internal:8044/health"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Comparison
|
||||
|
||||
| Flow | Entry | Goal | Auth Type | Endpoints | Status |
|
||||
|------|-------|------|-----------|-----------|--------|
|
||||
| **1: OAuth Login** | /login button | Create account or link to existing email | OAuth + email | /api/discord/oauth/start, /callback | ✅ Working |
|
||||
| **2: OAuth Linking** | Dashboard button | Link to logged-in account | OAuth + session token | /api/discord/create-linking-session, /oauth/start, /callback | ✅ Working |
|
||||
| **3: Verification Code** | Discord bot /verify | Link to logged-in account | Manual code | /api/discord/verify-code | ✅ Working |
|
||||
| **4: Activity** | Discord Activity | Show dashboard in Discord | Discord SDK | /api/discord/activity-auth | ✅ Working |
|
||||
| **5: Bot Commands** | Discord slash commands | Manage account & roles | None (bot to backend) | /api/discord/interactions | ✅ Working |
|
||||
|
||||
---
|
||||
|
||||
## Common Issues & Solutions
|
||||
|
||||
### Session Lost During OAuth Linking
|
||||
**Problem**: User logs in with email, clicks "Link Discord", gets redirected to login page
|
||||
**Cause**: Session cookies not sent during Discord redirect
|
||||
**Solution**: We use `discord_linking_sessions` table to store user_id before redirect ✅
|
||||
|
||||
### Forced Onboarding After Email Login
|
||||
**Problem**: User logs in with email, is sent to onboarding even though they completed it before
|
||||
**Cause**: Profile not marked as `onboarded: true` after completion
|
||||
**Solution**: Onboarding now sets `onboarded: true` flag ✅
|
||||
|
||||
### Discord Already Linked Error
|
||||
**Problem**: User tries to link Discord account that's already linked to different AeThex account
|
||||
**Cause**: discord_links.discord_id is UNIQUE
|
||||
**Solution**: Check if discord_id exists and belongs to different user, show error ✅
|
||||
|
||||
### Verification Code Expired
|
||||
**Problem**: User takes too long to click Discord link or verify
|
||||
**Cause**: discord_verifications has 15-min expiry
|
||||
**Solution**: Tell user to ask bot to run /verify again ✅
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [ ] **Flow 1**: Login with Discord (new account)
|
||||
- [ ] **Flow 1**: Login with Discord (existing email account)
|
||||
- [ ] **Flow 2**: Login with email, then link Discord from Dashboard
|
||||
- [ ] **Flow 3**: Login with email, use bot /verify code to link
|
||||
- [ ] **Flow 4**: Open Activity in Discord desktop app
|
||||
- [ ] **Flow 5**: Try /verify, /set-realm, /profile commands
|
||||
- [ ] **Flow 5**: Check roles are assigned correctly after /set-realm
|
||||
- [ ] Unlink Discord and re-link via different flow
|
||||
- [ ] Multiple users linking same Discord fails gracefully
|
||||
- [ ] Expired codes show proper error message
|
||||
|
||||
---
|
||||
|
||||
## Architecture Summary
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ DISCORD FLOWS │
|
||||
├────────────────────────────────────────────────────────────<EFBFBD><EFBFBD><EFBFBD>┤
|
||||
│ │
|
||||
│ Flow 1: OAuth Login ──→ /oauth/start → /callback │
|
||||
│ Flow 2: OAuth Linking ──→ Session + /oauth/start │
|
||||
│ Flow 3: Verify Code ──→ bot /verify + manual code │
|
||||
│ Flow 4: Activity SPA ──→ Activity.tsx + SDK auth │
|
||||
│ Flow 5: Bot Commands ──→ /interactions endpoint │
|
||||
│ │
|
||||
│ All flows converge on: discord_links table │
|
||||
│ All require: DISCORD_CLIENT_ID + CLIENT_ID │
|
||||
│ │
|
||||
│ Authentication: │
|
||||
│ • Flow 1: OAuth (Discord) │
|
||||
│ • Flow 2: Session token (database stored) │
|
||||
│ • Flow 3: User session (already logged in) │
|
||||
│ • Flow 4: Discord SDK token │
|
||||
│ • Flow 5: Bot token (server-side only) │
|
||||
│ │
|
||||
└────────────────────────────────────────<EFBFBD><EFBFBD>────────────────────┘
|
||||
```
|
||||
|
||||
Loading…
Reference in a new issue