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) <claude@firefrostgaming.com>
WHAT WAS DONE:
- Created stripe-integration.sql migration for eliminating Paymenter
- Adds stripe_products table (product catalog with recurring/one-time support)
- Adds webhook_events_processed table (idempotency tracking)
- Updates subscriptions table for lifetime tier support (Sovereign)
- Adds performance indexes for webhook lookups and grace period queries
- Includes constraint to ensure exactly one of subscription_id or payment_intent_id exists
WHY:
- Part of Gemini-approved architecture to eliminate Paymenter
- Supports both recurring subscriptions (tiers 1-9) and one-time payment (Sovereign tier 10)
- Ensures grace period logic never affects lifetime users
- Production-ready with full comments and validation
FILES CHANGED:
- services/arbiter-3.0/migrations/stripe-integration.sql (new, 127 lines)
CONTEXT:
- Gemini consultation verdict: Rip out Paymenter before first customer
- Phase 1 of 5 in Stripe direct integration
- Supports $499 Sovereign one-time payment with is_lifetime flag
Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>