# Gemini Discord OAuth Consultation Series — Complete Archive

**Date:** March 30, 2026  
**Chronicler:** #49  
**Project:** Discord OAuth Soft Gate Implementation  
**Consultant:** Gemini AI  
**Status:** Complete technical implementation received

---

## Executive Summary

This consultation series with Gemini AI resulted in a complete, production-ready implementation of a Discord OAuth soft gate system for subscription management, including manual role assignment admin interface.

**Total consultation documents:** 7  
**Total implementation time:** ~6 hours (9:00 AM - 3:00 PM CDT)  
**Lines of code generated:** 2000+ (estimated)  
**Architecture decisions:** 5 major (soft gate, integration, session management, rate limiting, validation)

---

## Consultation Timeline

### 1. Initial Architecture Consultation
**File:** `gemini-discord-oauth-consultation.md`  
**Purpose:** Present three architectural options for Discord linking  
**Key Decision:** Option C (Soft Gate) recommended and selected

**Gemini's Recommendation:**
> "Option C (Soft Gate) is the industry-standard approach. Users can complete purchase without friction, then link Discord via email. This maintains high conversion rates while enabling Discord gating."

### 2. Soft Gate Follow-up
**File:** `gemini-soft-gate-followup.md`  
**Purpose:** Detailed implementation questions for soft gate approach  
**Topics Covered:**
- Token generation and storage
- Email delivery strategy
- OAuth state parameter usage
- Error handling patterns

### 3. Complete Implementation Request
**File:** `gemini-complete-implementation-request.md`  
**Purpose:** Request complete code with Paymenter webhook details  
**Deliverables Requested:** 10 major code components

**Key Technical Details Provided:**
- Paymenter webhook payload structure
- Ghost CMS API integration requirements
- The Arbiter current state
- Mailcow SMTP configuration
- Infrastructure details

### 4. Final Questions (Architecture)
**File:** `gemini-final-questions.md`  
**Purpose:** 12 question categories covering implementation details  
**Topics:**
1. Role mapping configuration
2. Discord bot integration
3. Cleanup & maintenance
4. Error messages & UX
5. Webhook security
6. Logging strategy
7. Multi-server support
8. Upgrade/downgrade/cancellation
9. Testing checklist
10. Deployment steps
11. Documentation
12. Edge cases

### 5. Manual Role Assignment Architecture
**File:** `gemini-manual-role-assignment-architecture.md`  
**Purpose:** Architecture decision for admin interface  
**Key Decision:** Option A (Integration) selected over separation

**Gemini's Reasoning:**
> "The Discord Client Dilemma: A separate web app won't have direct access to the WebSocket connection. You would need two bot instances (causing rate limiting) or build a custom internal API. Keep it monolithic."

### 6. Complete Implementation Final Request
**File:** `gemini-complete-implementation-final.md`  
**Purpose:** Request all remaining code and documentation  
**Total Items Requested:** 18 deliverables including:
- Client-side JavaScript
- Missing backend functions
- Session management
- Security measures
- Testing procedures
- Deployment guides
- Documentation

### 7. Final Testing and Completion
**File:** `gemini-final-testing-and-completion.md`  
**Purpose:** Request testing sequence and final polish  
**Total Items Requested:** 15 deliverables including:
- Complete testing sequence
- Nginx configuration
- Rate limiting
- Input validation
- Error pages
- Troubleshooting guide
- README.md

---

## Complete Implementation Received

### Core Components

#### 1. Database Layer (SQLite)
**File:** `src/database.js`
- Table: `link_tokens` (token, email, tier, subscription_id, created_at, used)
- Table: `audit_logs` (id, admin_id, target_user, action, reason, timestamp)
- Daily cleanup via `setInterval`
- Library: `better-sqlite3`

#### 2. Email Service
**File:** `src/email.js`
- SMTP via Nodemailer
- Plain text email (better spam filtering)
- 24-hour expiring links
- Configuration: Mailcow (38.68.14.188:587)

#### 3. Webhook Handler
**File:** `src/routes/webhook.js`
- Receives Paymenter webhooks
- Checks for existing Discord ID
- Generates tokens if needed
- Sends linking emails
- HMAC SHA256 signature verification

#### 4. OAuth Flow
**Files:** `src/routes/oauth.js`
- `/link?token=...` - Token validation and Discord redirect
- `/auth/callback` - Code exchange, profile fetch, Ghost update, role assignment
- Token as state parameter (CSRF protection)

#### 5. Ghost CMS Integration
**File:** `src/cmsService.js`
- Library: `@tryghost/admin-api`
- `findMemberByEmail()` - Query Ghost for user
- `updateMemberDiscordId()` - Update custom field
- Custom field: `discord_id` (create in Ghost Admin UI)

#### 6. Discord Bot Service
**File:** `src/discordService.js`
- Discord.js client initialization
- `assignDiscordRole(userId, tier)` - Assign role by tier
- `removeAllSubscriptionRoles(userId)` - Strip all subscription roles
- Role mapping: `config/roles.json`

#### 7. Admin Interface
**Files:** `src/routes/admin.js`, `src/views/admin.html`
- Authentication: Trinity-only via `ADMIN_DISCORD_IDS`
- Search by email (queries Ghost)
- Manual role assignment
- Audit log display
- UI Framework: Pico.css (classless)

#### 8. Session Management
**Library:** `express-session` + `connect-sqlite3`
- Session store: `sessions.db`
- Admin OAuth flow for login
- Secure cookie configuration

#### 9. Security Measures
- Webhook signature verification (HMAC SHA256)
- Rate limiting (`express-rate-limit`)
- Input validation (Zod schemas)
- Session security (httpOnly, SameSite)
- HTTPS via Nginx

#### 10. Main Application
**File:** `src/index.js`
- Express setup
- All middleware mounting
- Route registration
- Discord client initialization
- Health check endpoint

---

## Architecture Decisions

### Decision 1: Soft Gate (Option C)
**Alternatives Considered:**
- Option A: Hard Gate (require Discord before purchase)
- Option B: Hybrid (Discord optional, roles manual)

**Rationale:**
- Maintains high conversion rates
- No friction at checkout
- Industry standard approach
- Prevents "I paid but where are my servers?" support tickets

### Decision 2: Integrated Admin Interface (Option A)
**Alternatives Considered:**
- Option B: Separate admin tool/service

**Rationale:**
- Discord client shares WebSocket connection
- No duplication of config/logic
- Single source of truth
- Simpler deployment

### Decision 3: SQLite for State
**Alternatives Considered:**
- Redis
- PostgreSQL
- In-memory (loses state on restart)

**Rationale:**
- Appropriate scale (5-10 manual assignments/week)
- Persistence across restarts
- No additional infrastructure
- Simple backup (just files)

### Decision 4: Plain Text Email
**Alternatives Considered:**
- HTML email with branding

**Rationale:**
- Better spam filtering
- Lower rendering issues
- Simpler maintenance
- Still professional

### Decision 5: Express Rate Limiting
**Alternatives Considered:**
- Nginx rate limiting
- No rate limiting

**Rationale:**
- Application-level control
- Granular per-route limits
- Easier to adjust
- Good enough for scale

---

## Security Implementation

### 1. Webhook Security
- HMAC SHA256 signature verification
- Secret stored in environment variable
- Timing-safe comparison

### 2. Input Validation
- Zod schemas for all webhooks
- Email format validation
- Discord ID format validation
- Sanitization of reason fields

### 3. Session Security
- `httpOnly` cookies
- `SameSite` policy
- Secure flag in production
- 7-day expiration

### 4. Rate Limiting
- 100 requests per 15 minutes per IP
- Applied to `/auth`, `/webhook`, `/admin/api`
- Standard headers for client awareness

### 5. Access Control
- Admin whitelist via `ADMIN_DISCORD_IDS`
- Session-based authentication
- No role in Discord required (fallback safe)

---

## Testing Strategy

### Component Tests
1. Database initialization
2. Discord bot connection
3. Ghost CMS connection
4. SMTP email sending
5. Session persistence

### Integration Tests
1. Webhook reception (curl)
2. Token generation
3. Email delivery
4. OAuth flow
5. Ghost updates
6. Discord role assignment

### End-to-End Test
1. Simulate Paymenter webhook
2. Verify token in database
3. Check email sent
4. Click link, complete OAuth
5. Verify Ghost updated
6. Verify role assigned
7. Check audit log

### Edge Cases
- Expired token
- Used token
- Invalid token
- User not in Discord server
- User already has role
- Bot lacks permissions
- API failures (Ghost, Discord, SMTP)

---

## Deployment Configuration

### Environment Variables (Complete List)
```bash
# App
NODE_ENV=production
PORT=3500
APP_URL=https://discord-bot.firefrostgaming.com
SESSION_SECRET=<generated>

# Discord
DISCORD_BOT_TOKEN=<from Developer Portal>
DISCORD_CLIENT_ID=<from Developer Portal>
DISCORD_CLIENT_SECRET=<from Developer Portal>
GUILD_ID=<Discord server ID>

# Admin Access
ADMIN_DISCORD_IDS=<Michael>,<Meg>,<Holly>

# Ghost CMS
CMS_URL=https://firefrostgaming.com
CMS_ADMIN_KEY=<from Ghost Integrations>

# Email
SMTP_HOST=38.68.14.188
SMTP_USER=noreply@firefrostgaming.com
SMTP_PASS=<from Mailcow>

# Webhook Security
WEBHOOK_SECRET=<from Paymenter>
```

### NPM Dependencies
```json
{
  "@tryghost/admin-api": "^1.13.8",
  "better-sqlite3": "^9.4.3",
  "connect-sqlite3": "^0.9.15",
  "discord.js": "^14.14.1",
  "dotenv": "^16.4.5",
  "express": "^4.19.2",
  "express-rate-limit": "^7.1.5",
  "express-session": "^1.18.0",
  "nodemailer": "^6.9.13",
  "zod": "^3.22.4"
}
```

### Systemd Service
```ini
[Unit]
Description=Arbiter Discord Bot and Web Gateway
After=network.target

[Service]
Type=simple
User=architect
WorkingDirectory=/home/architect/arbiter
ExecStart=/usr/bin/node src/index.js
Restart=on-failure
RestartSec=10
EnvironmentFile=/home/architect/arbiter/.env

[Install]
WantedBy=multi-user.target
```

### Nginx Configuration
- SSL via Let's Encrypt
- Reverse proxy to localhost:3500
- WebSocket support
- Proxy headers for real IP

---

## Maintenance Procedures

### Daily Automated Tasks
1. **Token cleanup** - Remove expired tokens (>24 hours)
   - Runs: Every 24 hours via `setInterval`
   - Location: `src/database.js`

2. **Database backup** - Copy SQLite files
   - Runs: Nightly via cron
   - Script: `backup.sh`
   - Retention: 7 days

### Manual Tasks
1. **Monitor audit logs** - Review manual assignments
2. **Check health endpoint** - Verify all components up
3. **Review SMTP logs** - Ensure emails delivering
4. **Update role mappings** - Add new tiers to `config/roles.json`

---

## Success Metrics

### Initial Implementation (Soft Launch)
- Manual role assignments: 5-10/week
- Automated linking success rate: Target 95%
- Support tickets reduced: Target 80%

### Steady State
- Manual role assignments: 1-3/week
- Automated linking success rate: Target 98%
- Zero downtime deployments

---

## Key Learnings

### From Gemini

1. **Soft gates work** - Don't force Discord before purchase
2. **Don't separate prematurely** - Monoliths are good at small scale
3. **SQLite is underrated** - Perfect for this use case
4. **Plain text email** - Better deliverability than HTML
5. **Rate limiting is essential** - Even low-traffic apps need it

### Architecture Patterns

1. **Single source of truth** - `config/roles.json` drives everything
2. **State parameter for CSRF** - Token becomes OAuth state
3. **Strip then assign** - Prevents orphaned roles
4. **Audit everything** - Especially manual overrides
5. **Health checks matter** - Monitor all dependencies

---

## Future Enhancements

### Phase 2 (Post-Launch)
1. Bulk role assignment (CSV upload)
2. Scheduled role grants (time-limited promotions)
3. Discord slash commands for support team
4. Metrics dashboard (success rates, error types)

### Phase 3 (Growth)
1. Multi-guild support
2. Webhook retry queue (Bull/BullMQ)
3. Separate admin UI (React SPA)
4. API documentation (Swagger/OpenAPI)

---

## Documentation Generated

### Code Documentation
- Inline comments in all modules
- JSDoc for public functions
- README.md (pending final delivery)

### Operational Documentation
- Installation guide
- Testing checklist
- Troubleshooting guide (pending)
- Deployment checklist (pending)

### Architecture Documentation
- This archive document
- All consultation exchanges
- Decision rationale

---

## Gemini's Final Note

> "This conversation is getting massive and is in danger of losing information due to context length limits. Please save all of our generated code, architecture notes, and progress logs to a Google Doc immediately to establish your source of truth."

**Action Taken:** All consultation files archived to Gitea operations manual at:
`docs/consultations/gemini-discord-oauth-2026-03-30/`

---

## Contact Information

**Primary Consultant:** Gemini AI  
**Implementation Lead:** Claude (Chronicler #49)  
**Project Owner:** Michael "Frostystyle" Krause  
**Date:** March 30, 2026  
**Status:** Complete implementation received, awaiting final documentation

---

## Files in This Archive

1. `gemini-discord-oauth-consultation.md` - Initial architecture options
2. `gemini-soft-gate-followup.md` - Soft gate implementation details
3. `gemini-complete-implementation-request.md` - Complete code request with Paymenter details
4. `gemini-final-questions.md` - 12 question categories
5. `gemini-manual-role-assignment-architecture.md` - Admin interface decision
6. `gemini-complete-implementation-final.md` - Final 18 deliverables request
7. `gemini-final-testing-and-completion.md` - Testing sequence and final polish

**Total archive size:** ~68 KB  
**Total word count:** ~15,000 words  
**Code blocks:** 50+  
**Architecture diagrams:** 3  

---

**This consultation series represents one of the most comprehensive AI-assisted technical implementations in the Firefrost Gaming project to date.**

💙🔥❄️
