96 Commits

Author SHA1 Message Date
Claude
d227bce0a8 Add discord-channel-rename.js script
- Maps Pterodactyl servers to Discord categories
- Renames channels to consistent naming convention
- DRY_RUN=true by default (preview mode)
- 1.5s rate limit delay between operations
- Snart Doctrine: built to adapt when reality hits
2026-04-09 20:12:12 +00:00
Claude
47a600eeb5 Fix: Handle server names with subtitles for Discord channel matching
- 'Homestead - A Cozy Survival Experience' now matches 'homestead-chat'
- 'All The Mons (Private) - TX' now matches 'all-the-mons-chat'
- Strips subtitles after ' - ' and removes parentheticals
2026-04-09 20:03:41 +00:00
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
dc59e5c1de Add /delserver documentation script
Chronicler: #71
2026-04-08 17:30:12 +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
7ecce5da8f Add script to create #staff-commands with documentation
Creates channel in Staff Area with detailed embeds for:
- /link command (everyone)
- /createserver command (staff only)

Chronicler: #71
2026-04-08 17:21:52 +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
083885c874 Add emoji prefixes to remaining categories
📢 Welcome & Info
💬 Community Hub
🔊 Voice Channels
📞 Support

Chronicler: #71
2026-04-08 17:05:34 +00:00
Claude
05d23e2dfc Add script to archive welcome posts
Fixes forum channels staying visible when category collapsed.
Archived threads don't count as 'active'.

Chronicler: #71
2026-04-08 17:00:17 +00:00
Claude
940840d69a Fix Wold's Vaults v2 - use role ID directly
Whatever apostrophe variant that is, we're bypassing it.
Role ID: 1491029373640376330

Chronicler: #71
2026-04-08 16:53:42 +00:00
Claude
f5a75d204f Fix Wold's Vaults - curly apostrophe
Role uses ' (curly) not ' (straight)

Chronicler: #71
2026-04-08 16:52:36 +00:00
Claude
40cb6cef31 Add full Discord channel setup script (46 channels)
Task #98 implementation:
- Phase 1: Add 🎮 prefix to existing 5 server categories
- Phase 2: Add forums to existing 5 servers
- Phase 3: Create full setup for 10 new servers (category + chat + in-game + voice + forum)
- Phase 4: Create 📦 Archive category (staff-only)

Includes:
- DRY_RUN mode for safe testing
- Permission overwrites (Wanderer=view, Server Role=interact, Staff=full)
- 15 welcome posts with server-specific content
- 6 standard forum tags per forum
- Rate limiting (500ms between API calls)

Chronicler: #71
2026-04-08 16:50:05 +00:00
Claude
9752c6fd89 Add full Discord channel setup script (46 channels)
Task #98: Discord Channel Automation
- Phase 1: Add forums to existing 5 servers + rename categories
- Phase 2: Create 10 new server categories with all channels
- Phase 3: Create Archive category (staff only)

Includes:
- 15 server-specific welcome posts
- Standard forum tags (6 tags)
- Permission template (Wanderer view-only, Server Role full access)
- Rate limiting (500ms delays)
- Idempotent (skips existing channels)

Chronicler: #71
2026-04-08 16:48:48 +00:00
Claude
911f5801fc Fix .env path to /opt/arbiter-3.0/.env
Chronicler: #71
2026-04-08 16:40:40 +00:00
Claude
8768c6773f Add Discord channel creation test script
Phase 1 test for Task #98 Discord automation.
Creates one test category + one forum with tags + welcome post.
Includes DRY_RUN mode and permission checks.

Chronicler: #71
2026-04-08 16:39:48 +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
7f990933df Sync package.json with production dependencies
Added missing dependencies that were installed on server but not in repo:
- axios: ^1.14.0
- connect-pg-simple: ^10.0.0
- date-fns: ^4.1.0

This caused deploy script to fail with MODULE_NOT_FOUND errors.

Chronicler #69
2026-04-08 08:30:17 +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
91eea2c5ff Add Arbiter deployment script and documentation
Created:
- deploy.sh: One-command deployment script
- DEPLOYMENT.md: Full deployment guide

Features:
- Handles cleanup of old temp directories
- Shallow clone for speed
- Checks for dependency changes
- Verifies service after restart
- Clear error messages

Usage on Command Center:
  bash /opt/arbiter-3.0/deploy.sh

Or remote curl:
  curl -fsSL https://git.firefrostgaming.com/.../deploy.sh | bash

Chronicler #69
2026-04-08 08:22:22 +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