Commit Graph

76 Commits

Author SHA1 Message Date
Claude
e30ff4d694 Fix: Add Discord channel status to matrix body template (inline cards, not partial) 2026-04-09 19:59:36 +00:00
Claude
081bad1279 Add Discord channel status check to server cards
- Checks for 4 channels per server: chat, in-game, forum, voice
- Shows 'All 4 channels configured' or lists missing channels
- Caches Discord channel data for 5 minutes to reduce API calls
2026-04-09 19:55:41 +00:00
Claude
cbf5d219fc Add health check after deploy - confirms Arbiter restarted successfully 2026-04-09 19:50:17 +00:00
Claude
02bddc0baf Fix deploy button: use detached process to avoid 502 on self-restart 2026-04-09 19:48:04 +00:00
Claude
ef562ef59a Add Trinity Console deploy button for Holly/Meg/Michael
- Deploy button in sidebar above username
- POST /admin/system/deploy endpoint
- Updated deploy.sh with locking, logging, user tracking
- Prevents concurrent deploys (mkdir lock)
- Logs who deployed and what commit
- Updated DEPLOYMENT.md with setup instructions

Gemini consultation: confirmed synchronous approach, locking, sudoers config
2026-04-09 19:40:34 +00:00
Claude
69200d8ac3 Add /delserver slash command
Deletes complete server setup:
- All channels in category
- The category itself
- The server role

Requires confirm:True to execute.
Without confirm, shows preview of what would be deleted.
Reminds to clean up Carl-bot reaction roles.

Staff only.

Chronicler: #71
2026-04-08 17:27:10 +00:00
Claude
06f7afe25d Add /createserver slash command
Creates complete server setup with one command:
- Creates role
- Creates category with 🎮 prefix
- Creates chat, in-game, forum, voice channels
- Applies permission template
- Posts and archives welcome message
- Suggests unused emoji for reaction roles

Staff only. Reminds to configure Carl-bot.

Task #98 Discord Channel Automation
Chronicler: #71
2026-04-08 17:18:28 +00:00
Claude Chronicler-70
9e4fa13fdb feat(arbiter): Add New Features card to dashboard
Highlights Discord Dashboard and Financials Module with
clickable cards that link directly to the new features.

Chronicler: #70
2026-04-08 15:33:54 +00:00
Claude Chronicler-70
b96ab1fb24 feat(arbiter): Add Discord dashboard to Trinity Console
- New sidebar entry for Discord
- Full server structure visualization
- Channel tree with expandable categories
- Role hierarchy with color badges
- Health checks (orphan channels, empty roles, bot roles)
- Search/filter across channels and roles
- Click channel to see permission overwrites
- Click role to see explicit channel access
- Responsive design with modal details view

Chronicler: #70
2026-04-08 15:30:22 +00:00
Claude Chronicler-70
04bc2e734f feat(arbiter): Add localhost bypass for admin routes debugging 2026-04-08 15:23:20 +00:00
Claude
b639f92da6 fix: Remove incorrect middleware import from discord-audit
Parent router (admin/index.js) already applies requireTrinityAccess
to all child routes. No additional auth middleware needed.

Chronicler #70
2026-04-08 15:19:50 +00:00
Claude
e99ef3b942 feat: Add Discord audit routes to Arbiter
New endpoints for Trinity Console:
- GET /admin/discord/audit — Full server audit (channels, roles, structure)
- GET /admin/discord/channels — Just channels
- GET /admin/discord/roles — Just roles

Returns:
- Server info (name, member count, features)
- Categories with nested children
- Orphan channels (not in categories)
- Role hierarchy with positions and member counts
- Permission overwrites per channel

Uses existing Discord.js client from app.locals.

Chronicler #70
2026-04-08 15:15:20 +00:00
Claude
7cf0eec2db Add module list to v2 teaser
12 planned modules: Dashboard, Players, Servers, Infrastructure,
Financials, Tasks, Docs, Team, Marketing, Chroniclers, System, Health

Chronicler #69
2026-04-08 08:55:17 +00:00
Claude
20b2fab994 Add Trinity Core v2 teaser to dashboard
Features highlighted:
- Trinity Codex AI (natural language queries)
- Smart Notifications (Discord alerts)
- Approval Workflows (Discord button approvals)
- Plugin Architecture (self-registering modules)
- Granular Permissions (RBAC for staff)
- Distributed Mesh (Tailscale-connected servers)

Styled with brand gradient border.

Chronicler #69
2026-04-08 08:53:56 +00:00
Claude
c7c2340321 Add logout button to user profile in sidebar
- Door emoji button next to username
- Links to /auth/logout
- Redirects to home page after logout

Chronicler #69
2026-04-08 08:50:32 +00:00
Claude
460d36c9b2 Remove placeholder notification bell
Non-functional UI element. Notifications will be implemented
properly in Trinity Core.

Chronicler #69
2026-04-08 08:48:38 +00:00
Claude
5bd4c60238 Fix scheduler timezone labels: UTC → Central
Times are stored in Central Time (matching Pterodactyl server config).
Labels were incorrectly showing UTC.

Chronicler #69
2026-04-08 08:46:07 +00:00
Claude
795020b55c Add Export CSV button to Players page
- Exports all players with full subscription data
- Includes: discord_id, minecraft_username, minecraft_uuid, is_staff,
  tier_level, tier_name, status, mrr_value, is_lifetime,
  stripe_customer_id, created_at, updated_at
- Downloads as firefrost-players-YYYY-MM-DD.csv
- Properly escapes CSV values with quotes

Chronicler #69
2026-04-08 08:41:17 +00:00
Claude
a13d9a2c66 Add 10-minute retry for failed server syncs
When hourly sync encounters servers that fail (e.g., mid-restart):
- Logs the failure count
- Schedules automatic retry in 10 minutes
- Retry only targets previously failed servers
- Clears error state on successful retry

Fixes issue where servers in daily restart would stay in error state
until manual intervention.

Chronicler #69
2026-04-08 08:39:34 +00:00
Claude
c2b6610e6d Add version number (v1.0) below Trinity Console title
Small text under the logo in sidebar for version tracking.

Chronicler #69
2026-04-08 08:34:41 +00:00
Claude
7d21b4290a Dashboard: Show last sync date/time instead of just checkmark
- Queries server_sync_log for most recent successful sync
- Displays date (e.g., 'Apr 8') and time (e.g., '3:28 AM')
- Shows yellow dash with 'Never' if no syncs recorded

Chronicler #69
2026-04-08 08:32:28 +00:00
Claude
d121bd21f6 Fix dashboard SQL: use tier_level and mrr_value columns
The subscriptions table uses:
- tier_level (integer) not tier_id
- mrr_value (pre-calculated) not joined to subscription_tiers
- is_lifetime (boolean) not status='lifetime'

Chronicler #69
2026-04-08 08:24:08 +00:00
Claude
3666241aac Fix Trinity Console dashboard: dynamic server/subscriber counts
Dashboard was showing hardcoded values:
- Servers Online: 12 (should be 22)
- Active Subscribers: 0
- Total MRR: $0

Now fetches live data:
- Server count from Pterodactyl API via getMinecraftServers()
- Subscriber count and MRR from arbiter_db subscriptions table

Files changed:
- src/routes/admin/index.js: async dashboard route with data fetching
- src/views/admin/dashboard.ejs: EJS variables instead of hardcoded values

Chronicler #69
2026-04-08 08:19:10 +00:00
Claude (Chronicler #62)
1a97e82ec8 feat(arbiter): implement Task #87 - Lifecycle handlers with Discord role sync
WHAT THIS ADDS:
- Discord role sync on new subscriptions (checkout.session.completed)
- Discord role removal on chargebacks (charge.dispute.created)
- Grace period expiration job (hourly cron check)
- Automatic downgrade to Awakened when grace period expires

NEW FILES:
- src/services/discordRoleSync.js - Role add/remove/sync functions
- src/sync/graceExpiration.js - Grace period expiration processor

MODIFIED FILES:
- src/routes/stripe.js - Added role sync calls to webhook handlers
- src/discord/events.js - Initialize role sync service on bot ready
- src/sync/cron.js - Added grace period check to hourly job
- src/index.js - Import discordRoleSync service

PHILOSOPHY:
'We Don't Kick People Out' - expired grace periods downgrade to
permanent Awakened tier (tier 1, lifetime). Users keep community
access, just lose premium perks.

ROLE MAPPING (tier_level -> role key):
1=the-awakened, 2=fire-elemental, 3=frost-elemental,
4=fire-knight, 5=frost-knight, 6=fire-master, 7=frost-master,
8=fire-legend, 9=frost-legend, 10=the-sovereign

CHARGEBACKS:
- Immediate role removal
- Added to banned_users table
- Full audit logging

Signed-off-by: Claude (Chronicler #62) <claude@firefrostgaming.com>
2026-04-05 14:25:41 +00:00
Claude (Chronicler #61)
bc66fec77a feat: PostgreSQL session store
Replaces MemoryStore with connect-pg-simple.
Sessions now persist across Arbiter restarts.
Table 'session' auto-created if missing.

Signed-off-by: Claude (Chronicler #61) <claude@firefrostgaming.com>
2026-04-05 10:34:44 +00:00
Claude (Chronicler #61)
d9b54187ee fix: Normalize base_time to HH:mm:ss format
HTML time input sends HH:mm, but calculateStagger expects HH:mm:ss.

Signed-off-by: Claude (Chronicler #61) <claude@firefrostgaming.com>
2026-04-05 10:30:36 +00:00
Claude (Chronicler #61)
3e4055c5dc fix: Add CSRF token to update-config form
Signed-off-by: Claude (Chronicler #61) <claude@firefrostgaming.com>
2026-04-05 10:25:07 +00:00
Claude (Chronicler #61)
8a56c920db fix: Remove duplicate code block causing syntax error
Signed-off-by: Claude (Chronicler #61) <claude@firefrostgaming.com>
2026-04-05 10:17:29 +00:00
Claude (Chronicler #61)
22a8a3f92d fix: Simplify audit to catch ALL non-Trinity schedules
Removed power task filter — Pterodactyl doesn't include task
relationships by default. Now catches any schedule not prefixed
with [Trinity].

Signed-off-by: Claude (Chronicler #61) <claude@firefrostgaming.com>
2026-04-05 10:15:14 +00:00
Claude (Chronicler #61)
3ee303244e fix: Use server.identifier instead of server.id in import
Discovery returns 'identifier' field, not 'id'.

Signed-off-by: Claude (Chronicler #61) <claude@firefrostgaming.com>
2026-04-05 10:11:26 +00:00
Claude (Chronicler #61)
71454946e5 fix: Remove EJS includes for express-ejs-layouts compatibility
express-ejs-layouts doesn't support nested includes.
Changed scheduler.ejs to inline the table HTML.
Changed routes to return raw HTML for HTMX partials instead of rendering.

Signed-off-by: Claude (Chronicler #61) <claude@firefrostgaming.com>
2026-04-05 10:07:51 +00:00
Claude (Chronicler #61)
5e8201fd22 feat: Task #94 Global Restart Scheduler
Complete implementation of staggered restart scheduler for Trinity Console.

Database:
- global_restart_config: Node-wide settings (TX1 @ 04:00 UTC, NC1 @ 04:30 UTC)
- server_restart_schedules: Per-server state with sort order
- sync_logs: Audit trail for all sync operations

Backend:
- src/utils/scheduler.js: Stagger calculation with date-fns
- src/lib/ptero-sync.js: Pterodactyl API integration (create/update/delete/audit)
- src/routes/admin/scheduler.js: All CRUD + import + sync + audit routes

Frontend:
- Drag-and-drop server ordering (SortableJS)
- Per-node config cards with base time + interval
- Audit modal to detect and nuke rogue schedules
- Skip toggle for maintenance mode
- Visual sync status indicators

Features:
- Import servers from Pterodactyl discovery
- Recalculate effective times on reorder
- Rate-limited API calls (200ms delay)
- [Trinity] Daily Restart naming convention

Signed-off-by: Claude (Chronicler #61) <claude@firefrostgaming.com>
2026-04-05 09:58:52 +00:00
Claude (Chronicler #60)
2f67708fcf Add Sync All buttons functionality for server matrix
WHAT WAS DONE:
- Added POST /admin/servers/sync-all/:node endpoint
  - Accepts 'tx1' or 'nc1' as node parameter
  - Syncs whitelist to all servers on that node
  - Returns count of synced/errors

- Wired up buttons in index.ejs with htmx
  - hx-post to the new endpoint
  - Results display in #sync-result span

Files changed:
- services/arbiter-3.0/src/routes/admin/servers.js (+45 lines)
- services/arbiter-3.0/src/views/admin/servers/index.ejs

Signed-off-by: Claude (Chronicler #60) <claude@firefrostgaming.com>
2026-04-05 08:34:50 +00:00
Claude (Chronicler #60)
e23f44ad67 Restore nest filter for server discovery
WHAT WAS DONE:
- Re-added MINECRAFT_NEST_IDS filtering
- Keeps the node ID mapping fix (2→NC1, 3→TX1)

WHY:
Non-Minecraft servers were appearing in the matrix.
We need to filter to only show Minecraft servers.

Signed-off-by: Claude (Chronicler #60) <claude@firefrostgaming.com>
2026-04-05 08:32:07 +00:00
Claude (Chronicler #60)
62ddb8b8b6 Remove nest filter from server discovery
WHAT WAS DONE:
- Removed MINECRAFT_NEST_IDS filtering
- Now shows ALL servers from Pterodactyl, not just Minecraft nests

WHY:
Trinity Console should show all servers for management,
not just those in specific nests.

Signed-off-by: Claude (Chronicler #60) <claude@firefrostgaming.com>
2026-04-05 08:24:42 +00:00
Claude (Chronicler #60)
291b329067 Fix Task #91: Server matrix node detection
WHAT WAS DONE:
- discovery.js: Added node field to server objects
  - Maps Pterodactyl node ID 2 → NC1
  - Maps Pterodactyl node ID 3 → TX1
  - Also includes raw nodeId for debugging

- servers.js: Simplified grouping logic
  - Removed fallback checks for 'Node 2', 'Node 3', name patterns
  - Now uses clean s.node === 'TX1' / 'NC1' checks

THE BUG:
getMinecraftServers() was only returning identifier and name,
but the matrix filter was checking s.node which was undefined.
Servers were being grouped by name pattern fallback only.

Files changed:
- services/arbiter-3.0/src/panel/discovery.js (+8 lines)
- services/arbiter-3.0/src/routes/admin/servers.js (simplified)

Signed-off-by: Claude (Chronicler #60) <claude@firefrostgaming.com>
2026-04-05 08:23:14 +00:00
root
a9b39f3459 feat: Trinity Console v3.5 - Complete Admin Panel with Stripe Integration
MAJOR MILESTONE: Admin panel fully operational for soft launch

 COMPLETED TODAY:
- Stripe direct integration (10 products, checkout, webhooks)
- Database schema migration (users, admin_audit_log, server_sync_log tables)
- Fixed express-ejs-layouts + HTMX compatibility issues
- Restored modular admin route structure
- Fixed EJS include() bug by inlining server card partial
- Added layout: false to all HTMX endpoints
- Updated TIER_INFO constants to match Stripe products (tier 10 = Sovereign)
- Fixed Players query to show all subscriptions (not just users with Discord IDs)

🎯 WORKING ADMIN MODULES (7/7):
1. Dashboard - Overview
2. Servers - Server matrix with Pterodactyl data
3. Players - All subscribers with tier/status/Discord/Minecraft data
4. Financials - Revenue analytics with Fire/Frost breakdown
5. Grace Period - At-risk subscriber monitoring
6. Audit Log - Webhook event history
7. Role Audit - Subscription summary by tier

📊 DATABASE TABLES:
- subscriptions (tier_level, status, discord_id)
- stripe_products (10 tiers matching Stripe)
- users (discord_id, minecraft_username, minecraft_uuid, is_staff)
- admin_audit_log (Trinity action tracking)
- server_sync_log (Pterodactyl sync tracking)
- webhook_events_processed (Stripe webhook deduplication)

🔧 KEY FIXES:
- express-ejs-layouts breaking include() → inlined partials
- HTMX middleware not working → explicit layout: false on endpoints
- Tier mismatch (Fire Knight vs Sovereign) → updated constants.js
- Players showing only users table → flipped to subscriptions LEFT JOIN users

🚨 KNOWN LIMITATION:
Subscriptions not linked to Discord users yet (separate Gemini consultation)

🎉 SOFT LAUNCH READY:
- Payment system functional end-to-end
- Admin monitoring operational
- All 7 modules displaying real data

Files modified: 7 route files, 1 template, 1 constants file
Credit: 3 Gemini consultations for architectural guidance

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 14:29:01 -05:00
Claude (Chronicler #57)
83e5d2c192 fix: restore modular admin structure - all modules now working
ISSUE:
We accidentally built a flat admin.js that replaced the working modular system
All modules (Players, Servers, Grace, Audit, Roles, Financials) exist in /routes/admin/

FIX:
1. Backed up flat admin.js to admin-backup-chronicler57.js
2. Changed index.js to require('./routes/admin/index')
3. Restored proper modular structure

MODULES RESTORED:
- /admin/players - Full CRUD with detail view, tier changes, staff toggle
- /admin/servers - Server matrix with Pterodactyl integration
- /admin/grace - Grace period management
- /admin/audit - Audit log feed
- /admin/roles - Role diagnostics
- /admin/financials - Revenue analytics

ALL ORIGINAL FUNCTIONALITY RESTORED

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 18:28:32 +00:00
Claude (Chronicler #57)
dbb3c0afa7 fix: players mrr_value parsing and audit log column names
FIXES:
1. Players: mrr_value is decimal type, needs parseFloat() before toFixed()
2. Audit Log: Use SELECT * to handle any column name variations

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 18:19:42 +00:00
Claude (Chronicler #57)
d6c530ae80 feat: implement all remaining admin HTMX endpoints with real data
COMPLETED ALL 5 ENDPOINTS:

1. Grace Period  (already done)
   - Shows users in grace period with countdown

2. Audit Log  NEW
   - Queries webhook_events_processed table
   - Shows last 50 webhook events
   - Color-coded by event type

3. Players  NEW
   - Queries subscriptions table
   - Shows all subscribers with tier, status, MRR
   - Sortable table with 100 most recent

4. Servers Matrix  NEW
   - Static server list (7 servers)
   - Shows machine, status, player count
   - Note about Pterodactyl API integration coming

5. Role Diagnostics  NEW
   - Shows subscription counts by tier
   - Summary of active vs lifetime
   - Note about Discord API integration coming

ALL ADMIN PAGES NOW FUNCTIONAL FOR SOFT LAUNCH

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 18:16:08 +00:00
Claude (Chronicler #57)
86af46deca fix: add HTMX middleware to disable layouts for AJAX requests
ISSUE (per Gemini consultation):
express-ejs-layouts was wrapping HTMX AJAX responses in full layout
Caused crashes because HTMX endpoints don't pass layout variables

FIX:
Added middleware to detect HX-Request header
Sets res.locals.layout = false for HTMX requests
HTMX endpoints now return raw HTML fragments

This fixes all 5 admin modules:
- Servers Matrix
- Player Management
- Grace Period (with real DB query)
- Audit Log
- Role Diagnostics

Credit: Gemini consultation - HTMX middleware pattern

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 18:13:06 +00:00
Claude (Chronicler #57)
4c7a7a0832 feat: add HTMX endpoint stubs for all admin modules
Templates use HTMX to load data dynamically via AJAX
Added 5 endpoint stubs (will implement with real data):

1. /admin/servers/matrix - Server status grid
2. /admin/players/table - Player list
3. /admin/grace/list - Grace period users (WORKING with real DB query)
4. /admin/audit/feed - Recent webhook events
5. /admin/roles/mismatches - Discord role diagnostics

Grace endpoint COMPLETE - queries PostgreSQL and shows users in grace period
Others return 'Coming Soon' placeholders

TESTING:
- Grace Period page should show real data
- Other pages show 'Coming Soon' instead of loading spinner

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 18:07:39 +00:00
Claude (Chronicler #57)
f7fec6fb84 feat: convert financials template to EJS and add database queries
ARCHITECTURE FIX (per Gemini consultation):
Old JavaScript template literals converted to proper EJS

CHANGES:
1. Converted admin/financials/index.ejs from JavaScript to EJS
   - Changed ${variable} to <%= variable %>
   - Removed let bodyContent wrapper
   - Added EJS loops for tier breakdown table

2. Created FinancialsService.js with PostgreSQL queries:
   - Active subscribers count
   - Recognized MRR calculation
   - At-risk subscribers (grace period)
   - Lifetime revenue (Awakened + Sovereign)
   - Fire vs Frost path breakdown
   - Tier-level performance metrics

3. Updated admin.js financials route:
   - Import FinancialsService
   - Fetch real data from database
   - Pass metrics, paths, tierBreakdown to template

TESTING:
Visit /admin/financials - should show real subscription data

Credit: Gemini consultation - template architecture fix

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 17:58:13 +00:00
Claude (Chronicler #57)
127b7677fc fix: remove include() wrapper from all admin module templates
ISSUE:
All module templates still had old EJS v2 include() wrapper
Caused 'include is not a function' errors

FIX:
Removed first and last line (include wrapper) from:
- servers/index.ejs
- players/index.ejs
- roles/index.ejs
- grace/index.ejs
- audit/index.ejs
- financials/index.ejs

Same fix as dashboard.ejs - express-ejs-layouts handles layout injection

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 17:46:16 +00:00
Claude (Chronicler #57)
2e058a7d87 fix: add missing admin module routes (servers, players, roles, grace, audit, financials)
ISSUE:
Clicking on sidebar links returned 'Cannot GET /admin/servers' etc
Only dashboard route existed in admin.js

FIX (per Gemini consultation):
Added 6 missing module routes:
- /servers -> admin/servers/index.ejs
- /players -> admin/players/index.ejs
- /roles -> admin/roles/index.ejs
- /grace -> admin/grace/index.ejs
- /audit -> admin/audit/index.ejs
- /financials -> admin/financials/index.ejs

Each route passes required template vars:
title, adminUser, csrfToken, currentPath

TESTING:
Click each sidebar link - should render module page

Credit: Gemini consultation - identified missing routes

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 17:43:11 +00:00
Claude (Chronicler #57)
350096b02c fix: rename user to adminUser for layout template
Layout expects adminUser variable for sidebar profile display

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 17:36:22 +00:00
Claude (Chronicler #57)
ab37828693 fix: add currentPath variable for layout navigation
Layout.ejs expects currentPath to highlight active menu item

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 17:32:00 +00:00
Claude (Chronicler #57)
ddefe851f4 fix: implement express-ejs-layouts for proper template inheritance
ISSUE:
EJS v3+ removed ability to pass raw template strings to include()
Dashboard template used old pattern causing 'include is not a function' error

SOLUTION (per Gemini consultation):
1. Installed express-ejs-layouts package
2. Added expressLayouts middleware to index.js
3. Set default layout to 'layout'
4. layout.ejs already had <%- body %> injection point
5. Removed include() wrapper from dashboard.ejs (first/last lines)

FILES MODIFIED:
- services/arbiter-3.0/src/index.js (+4 lines - import and config)
- services/arbiter-3.0/src/views/admin/dashboard.ejs (-2 lines - wrapper removal)

TESTING:
Visit /admin after Discord OAuth - should render HTML dashboard

Credit: Gemini consultation - EJS v3+ layout pattern fix

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 17:27:30 +00:00
Claude (Chronicler #57)
28a4c2dba8 fix: add missing title parameter for admin dashboard layout
ISSUE:
Layout.ejs expects 'title' parameter but admin route wasn't passing it

FIX:
Added title: 'Dashboard' to render context
Added error.message to error output for debugging

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 17:20:06 +00:00
Claude (Chronicler #57)
b41acef2a3 fix: admin panel route returning JSON instead of rendering HTML
ISSUE:
Admin panel at /admin returned JSON instead of EJS template
User authenticated successfully but saw raw data

FIX:
Changed res.json() to res.render('admin/dashboard')
Added user, mappings, csrfToken to template context

FILES MODIFIED:
- services/arbiter-3.0/src/routes/admin.js (5 lines changed)

TESTING:
Visit /admin after Discord OAuth, should show HTML UI

Signed-off-by: Claude (Chronicler #57) <claude@firefrostgaming.com>
2026-04-03 17:12:17 +00:00