# The Arbiter - Discord Bot & Admin Panel

**Service:** The Arbiter  
**Purpose:** Discord subscription automation and role management  
**Server:** Command Center (63.143.34.217)  
**Status:** ✅ Deployed and operational  
**Deployed:** March 27, 2026  
**Deployed by:** The Verifier (Chronicler #42)

---

## Overview

The Arbiter is a Discord bot that automates subscription-based role assignment for Firefrost Gaming. It receives webhooks from Paymenter when subscriptions are created, renewed, cancelled, or expired, and automatically assigns or removes Discord roles accordingly.

The bot includes a web-based admin panel where Holly, Meg, and Michael can manage Discord role mappings without SSH access.

---

## Architecture

**Flow:**
```
User Subscribes → Paymenter → Webhook (port 3500) → The Arbiter Bot → Discord Role → LuckPerms → In-game Permissions
```

**Components:**
1. **Discord Bot** - Monitors Firefrost Gaming server, assigns roles
2. **Webhook Receiver** - Receives Paymenter subscription events
3. **Admin Panel** - Web interface for managing role mappings
4. **OAuth2 Authentication** - Discord login for authorized admins

---

## Access Information

**Admin Panel URL:** https://discord-bot.firefrostgaming.com/admin

**Authorized Users:**
- Holly (unicorn20089) - Discord ID: `269225344572063754`
- Michael (Frostystyle) - Discord ID: `219309716021444609`
- Meg (Gingerfury) - Discord ID: `669981568059703316`

**Discord Bot:**
- Name: The Arbiter
- Username: The Arbiter#6636
- Application ID: `1487080166969577502`
- Guild ID (Firefrost Gaming): `1260574715546701936`

**Server Location:**
- Command Center: 63.143.34.217
- Directory: `/opt/firefrost-discord-bot`
- Port: 3500 (internal)
- HTTPS: 443 (Nginx reverse proxy)

---

## Bot Branding

**Visual Identity:**
- **Icon:** Scales of Justice with Fire (left, orange #FF6B35) and Frost (right, cyan #4ECDC4) balanced by purple Arcane energy (#A855F7)
- **Banner:** Judgment hall with Fire path (left) and Frost path (right) divided by Arcane beam
- **Theme:** Fire/Frost/Arcane gradient throughout UI

**Generated by:** Gemini AI (Google)  
**Design Philosophy:** The Arbiter judges who enters the realm and assigns paths

---

## Configuration

**Environment File:** `/opt/firefrost-discord-bot/.env`

```bash
DISCORD_BOT_TOKEN=MTQ4NzA4MDE2Njk2OTU3NzUwMg.GU5EsT.mqBwo7XUHsciN9jNy9OygTRkaMZ9qJ2tHw7HbI
GUILD_ID=1260574715546701936
DISCORD_CLIENT_ID=1487080166969577502
DISCORD_CLIENT_SECRET=xOK9ZYgionyqd-huGJRE2Rym98zy0W-m
REDIRECT_URI=https://discord-bot.firefrostgaming.com/auth/discord/callback
ADMIN_USERS=269225344572063754,219309716021444609,669981568059703316
PORT=3500
NODE_ENV=production
SESSION_SECRET=[auto-generated on deployment]
```

**⚠️ Security Note:** All credentials stored in Vaultwarden. Never commit .env to Git.

---

## Role Mappings

**Configuration File:** `/opt/firefrost-discord-bot/role-mappings.json`

**Status:** ✅ **COMPLETE** - All 10 tiers configured by Holly on March 27, 2026

**Current Mappings:**
```json
{
  "the-awakened": "1482490386634248273",
  "the-sovereign": "1482488242677874778",
  "fire-elemental": "1487181476755996823",
  "frost-elemental": "1487184348474218778",
  "fire-knight": "1487183625751880818",
  "frost-knight": "1487184476371222558",
  "fire-master": "1487183822951895546",
  "frost-master": "1487184618860249261",
  "fire-legend": "1487184056387748935",
  "frost-legend": "1487184718152138865"
}
```

**By Path:**

🔥 **Fire Path:**
- Fire Elemental ($5): `1487181476755996823`
- Fire Knight ($10): `1487183625751880818`
- Fire Master ($15): `1487183822951895546`
- Fire Legend ($20): `1487184056387748935`

❄️ **Frost Path:**
- Frost Elemental ($5): `1487184348474218778`
- Frost Knight ($10): `1487184476371222558`
- Frost Master ($15): `1487184618860249261`
- Frost Legend ($20): `1487184718152138865`

⚡ **Universal Tiers:**
- The Awakened ($1): `1482490386634248273`
- The Sovereign ($499): `1482488242677874778`

**Mapping Structure:**
- Keys: Paymenter product slugs (lowercase, hyphenated)
- Values: Discord role IDs (18-19 digit snowflakes)

**Configured By:** Holly (unicorn20089 / The Catalyst)  
**Date Completed:** March 27, 2026

**Full Documentation:** See `docs/systems/arbiter-discord-role-mappings.md` for complete mapping table, testing checklist, and troubleshooting guide.

---

## Systemd Service

**Service File:** `/etc/systemd/system/firefrost-discord-bot.service`

```ini
[Unit]
Description=The Arbiter - Firefrost Gaming Discord Bot
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/firefrost-discord-bot
ExecStart=/usr/bin/node /opt/firefrost-discord-bot/bot.js
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=firefrost-discord-bot

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

**Management Commands:**
```bash
# View status
systemctl status firefrost-discord-bot

# View logs (live)
journalctl -u firefrost-discord-bot -f

# View last 50 log entries
journalctl -u firefrost-discord-bot -n 50

# Restart service
systemctl restart firefrost-discord-bot

# Stop service
systemctl stop firefrost-discord-bot

# Start service
systemctl start firefrost-discord-bot
```

---

## Nginx Configuration

**Config File:** `/etc/nginx/sites-available/discord-bot.firefrostgaming.com`

```nginx
server {
    listen 63.143.34.217:80;
    server_name discord-bot.firefrostgaming.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 63.143.34.217:443 ssl http2;
    server_name discord-bot.firefrostgaming.com;

    ssl_certificate /etc/letsencrypt/live/discord-bot.firefrostgaming.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/discord-bot.firefrostgaming.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    location / {
        proxy_pass http://localhost:3500;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }

    access_log /var/log/nginx/discord-bot.access.log;
    error_log /var/log/nginx/discord-bot.error.log;
}
```

**SSL Certificate:**
- Provider: Let's Encrypt
- Issued: March 27, 2026
- Expires: June 25, 2026
- Auto-renewal: Certbot handles this automatically

---

## Dependencies

**Node.js:** v20.20.0 (LTS)  
**npm:** 10.8.2

**npm Packages:**
```json
{
  "discord.js": "^14.14.1",
  "express": "^4.18.2",
  "body-parser": "^1.20.2",
  "express-session": "^1.18.1",
  "passport": "^0.7.0",
  "passport-discord": "^0.1.4",
  "cookie-parser": "^1.4.7",
  "dotenv": "^17.3.1"
}
```

**Install dependencies:**
```bash
cd /opt/firefrost-discord-bot
npm install
```

---

## Admin Panel Features

**Role Management:**
- View all 10 subscription tiers
- Add/update Discord role IDs
- See current role status (configured/not configured)
- Real-time validation of role IDs

**Authentication:**
- Discord OAuth2 login
- Whitelist-based authorization (only Holly, Meg, Michael)
- Session-based authentication with secure cookies

**User Interface:**
- Fire Path tiers (orange accent)
- Frost Path tiers (cyan accent)
- Universal tiers (purple accent)
- Responsive design
- User avatar and logout in header

---

## Webhook Endpoints

**Paymenter Webhook:**
- URL: `https://discord-bot.firefrostgaming.com/webhook/paymenter`
- Method: POST
- Content-Type: application/json

**Expected Payload:**
```json
{
  "event": "subscription.created",
  "user": {
    "discord_id": "123456789012345678"
  },
  "product": {
    "slug": "fire-elemental",
    "id": "1"
  }
}
```

**Supported Events:**
- `subscription.created` - Add role
- `subscription.renewed` - Add role
- `subscription.cancelled` - Remove role
- `subscription.expired` - Remove role

**Health Check:**
- URL: `https://discord-bot.firefrostgaming.com/health`
- Method: GET
- Returns: Bot status, uptime

---

## OAuth2 Configuration

**Discord Developer Portal:**
- Application: The Arbiter
- Client ID: `1487080166969577502`
- Redirect URI: `https://discord-bot.firefrostgaming.com/auth/discord/callback`

**OAuth2 Scopes:**
- `identify` - Read user profile

**Privileged Gateway Intents (Enabled):**
- Presence Intent ✅
- Server Members Intent ✅ (CRITICAL for role assignment)
- Message Content Intent ✅

---

## Troubleshooting

### Bot Shows Offline in Discord
```bash
# Check service status
systemctl status firefrost-discord-bot

# Check logs for errors
journalctl -u firefrost-discord-bot -n 50
```

**Common causes:**
- Invalid bot token
- Discord API outage
- Service not running

### Admin Panel Login Loop
**Symptoms:** Redirects to login after authorizing Discord

**Solution:** Verify `app.set('trust proxy', 1);` is present in bot.js (line 62)

**Why this happens:** Nginx does SSL termination, Express sees HTTP requests, refuses to set secure cookies without trusting X-Forwarded-Proto header.

### Role Not Assigned After Webhook
```bash
# Check webhook logs
journalctl -u firefrost-discord-bot | grep "Webhook received"

# Verify role mapping exists
cat /opt/firefrost-discord-bot/role-mappings.json

# Check Discord bot permissions
# Bot must have "Manage Roles" permission
# Bot's role must be HIGHER than the roles it's assigning
```

### Nginx 502 Bad Gateway
```bash
# Verify bot is listening on port 3500
netstat -tlnp | grep 3500

# Restart bot service
systemctl restart firefrost-discord-bot

# Check Nginx config
nginx -t
```

---

## Deployment History

**March 27, 2026 - Initial Deployment & Configuration**
- Created Discord bot application "The Arbiter"
- Generated icon and banner via Gemini AI
- Deployed bot.js on Command Center
- Configured systemd service
- Set up Nginx reverse proxy with Let's Encrypt SSL
- Deployed admin panel with Discord OAuth2
- Fixed SSL termination / secure cookie issue with `app.set('trust proxy', 1);`
- Created Holly's role setup guide
- **Holly completed all 10 role ID mappings** (Fire/Frost paths + Universal tiers)
- Status: ✅ **Fully Operational** - All tiers configured, ready for webhook testing

---

## Security Considerations

**Secrets Management:**
- All credentials in .env file
- .env never committed to Git
- Session secret auto-generated with openssl
- Client secret rotated during deployment

**Authentication:**
- Whitelist-based admin access (3 users)
- Discord OAuth2 for identity verification
- Session-based authentication
- Secure cookies in production

**Network Security:**
- Bot only accessible via HTTPS
- Nginx handles SSL termination
- Internal port 3500 not exposed externally
- Rate limiting via Nginx (if needed, add later)

**Bot Permissions:**
- Minimal Discord permissions (Manage Roles, Send Messages)
- No Administrator permission
- Bot role positioned correctly in Discord hierarchy

---

## Future Enhancements

**Potential additions:**
- Audit logging to Discord channel for role changes
- Webhook retry logic for failed deliveries
- Role assignment history/statistics
- Integration with LuckPerms for in-game permission sync
- Multi-server support (if Firefrost expands to multiple Discord servers)

---

## Related Documentation

- **Holly's Role Setup Guide:** `docs/guides/holly-discord-roles-setup.md`
- **Subscription Automation Guide:** `docs/guides/subscription-automation-guide.md`
- **Discord Bot Admin Panel Guide:** `docs/guides/discord-bot-admin-panel.md`
- **Paymenter Configuration:** `docs/services/paymenter-configuration.md`
- **LuckPerms MySQL Database:** `docs/services/luckperms-mysql-database.md`

---

## Support Contacts

**Technical Issues:**
- Michael (Frostystyle) - Server owner, technical lead
- Discord: #staff-lounge channel

**Role Management Questions:**
- Holly (unicorn20089) - Lead builder, role configuration

---

**Last Updated:** March 27, 2026  
**Originally Deployed By:** The Verifier (Chronicler #42)  
**Role Configuration Completed By:** Holly (The Catalyst) via The Herald (Chronicler #43)  
**Status:** Production - Fully Configured ✅ - All 10 tiers mapped, ready for Paymenter webhook integration
