Phase 1 of task management consolidation (per Gemini consultation). Added standardized frontmatter with: - status: open | blocked | complete - priority: P1 | P2 | P3 | P4 - owner: Michael | Meg | Holly - created: YYYY-MM-DD Final counts: - 39 open tasks - 17 complete tasks - 1 blocked task Metadata extracted from existing inline markdown and audit results. Ready for Phase 2: 11ty mobile index generation. Chronicler #69
status, priority, owner, created
| status | priority | owner | created |
|---|---|---|---|
| complete | P1 | Michael | 2026-03-31 |
Task #90: Arbiter 2.x - Unified Access Manager
Status: OPEN
Priority: Tier 1 - Soft Launch Blocker
Estimated Time: 20-30 hours (5 phases)
Created: March 31, 2026
Architecture Validated By: Gemini AI
Overview
Complete rewrite merging Arbiter (Discord role management) + Whitelist Manager (server access control) into single Node.js application with PostgreSQL backend.
Goal: Subscription-driven Minecraft server whitelist access - user subscribes → links Minecraft account → automatically whitelisted on all servers.
Quick Links
- Implementation Guide:
IMPLEMENTATION-GUIDE.md(complete technical spec with code examples) - Architecture Decision:
../../reference/gemini-consultations/2026-03-31-arbiter-whitelist-architecture.md - Implementation Details:
../../reference/gemini-consultations/2026-03-31-arbiter-implementation-details.md - Main Task:
../../core/tasks.md#90
The Flow
- User subscribes via Paymenter (any tier, even $1 Awakened)
- Paymenter webhook → Arbiter assigns Discord role
- User runs
/link <minecraft_username>in Discord - Arbiter validates via Mojang API, gets UUID
- Stores in PostgreSQL: discord_id, minecraft_username, minecraft_uuid
- Master whitelist auto-syncs to all whitelisted servers
- User can now join any Minecraft server
Why Rewrite?
Current Whitelist Manager is broken:
- Hardcoded server name keywords (fails when servers change)
- WebSocket console commands (unreliable, returns "UNKNOWN")
- No subscription integration
- No master whitelist concept
- Manual-only operation
Current Arbiter doesn't:
- Store Minecraft usernames
- Communicate with Whitelist Manager
- Handle subscription-driven whitelist access
Architecture Decisions
All validated by Gemini AI consultation (March 31, 2026):
✅ Single unified app - Arbiter 2.x replaces both services
✅ PostgreSQL - Concurrent write safety at 500-user scale
✅ Discord /link slash command - Mojang API validation
✅ Pterodactyl File Management API - Replaces WebSocket console
✅ Hybrid sync - Event-driven push + hourly cron reconciliation
✅ UUIDs with dashes - Minecraft 1.8+ requirement
Implementation Phases
Phase 1: Database Migration
- Provision PostgreSQL 15+
- Execute schema creation
- Apply indexes for 500-user scale
- Migrate legacy SQLite data
Phase 2: Core Functions
- pg connection pool
- Mojang API validation + UUID formatting
- Pterodactyl Application API (auto-discovery)
- Pterodactyl Client API (file write, commands)
Phase 3: Discord Integration
/linkslash command registration- UUID validation flow
- Auto-DM new subscribers
- Paymenter webhook updates
Phase 4: Sync System
- Event-driven immediate sync
- node-cron hourly reconciliation
- Sequential batch processing
- Sync logging to database
Phase 5: Admin Panel
- server_sync_log dashboard
- Manual "Force Sync" trigger
- Linked accounts view
- Production deployment
Critical Gotchas
From Gemini consultation - these will break production if missed:
- Content-Type: text/plain for Panel file write (NOT application/json)
- Mojang UUIDs without dashes, Minecraft needs WITH dashes
- HTTP 412 = server offline, NOT an error (file saved for next boot)
- Sequential processing prevents Panel API rate limiting
- Application API for discovery, Client API for file operations
Database Schema
CREATE TABLE users (
discord_id VARCHAR(255) PRIMARY KEY,
minecraft_username VARCHAR(255) UNIQUE,
minecraft_uuid VARCHAR(255) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE subscriptions (
id SERIAL PRIMARY KEY,
discord_id VARCHAR(255) REFERENCES users(discord_id),
tier_level INT NOT NULL,
status VARCHAR(50) NOT NULL, -- active, grace_period, cancelled
stripe_customer_id VARCHAR(255)
);
CREATE TABLE server_sync_log (
server_identifier VARCHAR(50) PRIMARY KEY,
last_successful_sync TIMESTAMP,
last_error TEXT,
is_online BOOLEAN DEFAULT true
);
CREATE INDEX idx_users_discord_id ON users(discord_id);
CREATE INDEX idx_subscriptions_status ON subscriptions(status);
Success Criteria
- User subscribes → links account → auto-whitelisted within 5 minutes
- Master whitelist = database (single source of truth)
- All servers sync from master (hourly reconciliation)
- Server discovery is automatic (no hardcoded names)
- Works reliably for remote RV operations
- Handles 500 subscribers by September 2027
What Gets Retired
Once Arbiter 2.x is deployed:
- ❌ Old Whitelist Manager (Python Flask on Billing VPS)
- ❌ Old Arbiter 1.x (if not already migrated)
- ✅ Update all documentation to reference unified system
Dependencies
- PostgreSQL 15+
- Node.js 20 LTS
- Pterodactyl Panel v1.12.1 (Client + Application API keys)
- Mojang API (public, no auth)
- Discord Bot with slash command permissions
Fire + Frost + Foundation = Where Love Builds Legacy 💙🔥❄️