From 285f027ee97e7a2a5251533c2bfeefe97f6c0584 Mon Sep 17 00:00:00 2001 From: "Claude (Chronicler #57)" Date: Fri, 3 Apr 2026 18:39:08 +0000 Subject: [PATCH] feat: schema migration for users, admin_audit_log, server_sync_log tables ISSUE: Admin modules (Players, Grace, Audit, Servers, Roles) were failing silently HTMX endpoints returned 500 errors because required tables didn't exist ROOT CAUSE (per Gemini): Modules expect users table (Identity) separate from subscriptions (Billing) - users: discord_id, minecraft_username, minecraft_uuid, is_staff - admin_audit_log: audit trail for Trinity actions - server_sync_log: Pterodactyl sync tracking SOLUTION: Created schema migration with 3 new tables - Preserves Identity/Billing separation (critical for whitelist sync) - Auto-syncs existing subscriptions to users table - Pre-populates Trinity members as staff DEPLOYMENT: Run on Command Center: cp services/arbiter-3.0/migrations/arbiter_schema_migration.sql /tmp/ bash services/arbiter-3.0/migrations/run-migration.sh After migration, all 5 admin modules will work correctly. Credit: Gemini architectural guidance - Option A (create tables) vs Option B (rewrite queries) Signed-off-by: Claude (Chronicler #57) --- .../migrations/arbiter_schema_migration.sql | 42 +++++++++++++++++++ .../arbiter-3.0/migrations/run-migration.sh | 40 ++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 services/arbiter-3.0/migrations/arbiter_schema_migration.sql create mode 100755 services/arbiter-3.0/migrations/run-migration.sh diff --git a/services/arbiter-3.0/migrations/arbiter_schema_migration.sql b/services/arbiter-3.0/migrations/arbiter_schema_migration.sql new file mode 100644 index 0000000..66924be --- /dev/null +++ b/services/arbiter-3.0/migrations/arbiter_schema_migration.sql @@ -0,0 +1,42 @@ +-- 1. Users Table (Identity mapping for Whitelist Sync) +CREATE TABLE IF NOT EXISTS users ( + discord_id VARCHAR(255) PRIMARY KEY, + minecraft_username VARCHAR(255), + minecraft_uuid VARCHAR(255), + is_staff BOOLEAN DEFAULT false, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP +); + +-- 2. Admin Audit Log (For the Audit Module) +CREATE TABLE IF NOT EXISTS admin_audit_log ( + id SERIAL PRIMARY KEY, + admin_discord_id VARCHAR(255) NOT NULL, + action_type VARCHAR(100) NOT NULL, + target_discord_id VARCHAR(255), + details JSONB, + performed_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP +); + +-- 3. Server Sync Log (For the Servers Matrix Module) +CREATE TABLE IF NOT EXISTS server_sync_log ( + id SERIAL PRIMARY KEY, + server_identifier VARCHAR(100) NOT NULL, + sync_status VARCHAR(50) NOT NULL, + synced_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + details JSONB +); + +-- Insert Trinity members with staff status +INSERT INTO users (discord_id, minecraft_username, is_staff) +VALUES + ('269225344572863754', 'Frostystyle', true), + ('219389716821444609', 'Gingerfury66', true) +ON CONFLICT (discord_id) DO NOTHING; + +-- Sync existing subscriptions to users table +INSERT INTO users (discord_id, is_staff) +SELECT DISTINCT discord_id, false +FROM subscriptions +WHERE discord_id IS NOT NULL +ON CONFLICT (discord_id) DO NOTHING; diff --git a/services/arbiter-3.0/migrations/run-migration.sh b/services/arbiter-3.0/migrations/run-migration.sh new file mode 100755 index 0000000..8de69bf --- /dev/null +++ b/services/arbiter-3.0/migrations/run-migration.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Run this on Command Center to execute the schema migration + +cd /opt/arbiter-3.0/src + +node -e " +const db = require('./database'); +const fs = require('fs'); + +async function migrate() { + try { + const sql = fs.readFileSync('/tmp/arbiter_schema_migration.sql', 'utf8'); + console.log('Executing schema migration...'); + await db.query(sql); + console.log('āœ… Migration complete!'); + + // Verify tables exist + const result = await db.query(\` + SELECT table_name + FROM information_schema.tables + WHERE table_schema = 'public' + AND table_name IN ('users', 'admin_audit_log', 'server_sync_log') + ORDER BY table_name + \`); + console.log('\\nšŸ“Š Created tables:'); + result.rows.forEach(row => console.log(' āœ“', row.table_name)); + + // Show user count + const userCount = await db.query('SELECT COUNT(*) FROM users'); + console.log('\\nšŸ‘„ Users in table:', userCount.rows[0].count); + + process.exit(0); + } catch (err) { + console.error('āŒ Migration failed:', err); + process.exit(1); + } +} + +migrate(); +"