Admin Panel
The admin panel provides platform-level management tools for system administrators. It is separate from guild officer tools and requires the isAdmin flag on the user record.
Access Control
Admin routes are protected by @RequireAbilities({ action: Action.Manage, subject: 'all' }), which resolves to the platform admin check. Regular guild officers cannot access admin features.
Features
User Management
View and search all platform users. Displays:
- Display name, linked accounts (Discord, Battle.net)
- Last login timestamp
- Admin flag status
Organization Overview
Lists all organizations with:
- Name, type, alias
- Active/archived status
- Member count
- Creation date
Sync Triggers
Manually trigger background sync jobs:
| Trigger | Description |
|---|---|
| Journal Sync | Re-sync expansion, instance, and encounter data from Blizzard |
| Roster Sync (per guild) | Force refresh guild roster from Battle.net API |
Sync operations run as background jobs and report progress via WebSocket.
Platform Feature Flags
Admins can toggle platform-wide feature flags that control whether certain capabilities are available to all users. Flags are stored in a singleton PlatformConfig row with a JSON features column.
| Flag | Description | Default |
|---|---|---|
guildCreation | Allow users to create new guilds | false |
characterCreation | Allow users to create new characters | false |
When a flag is disabled:
- The corresponding create button is hidden from the UI
- Direct navigation to the create route redirects away
- New flags default to
false(opt-in)
The GET /admin/features endpoint is public (no auth required) so the frontend can check flags before the user logs in. The PATCH /admin/features endpoint requires admin privileges and accepts a partial object that is merged with existing flags.
Job Queue Monitoring
View the status of background jobs:
- Active/waiting/completed/failed counts
- Individual job details and error messages
- Retry failed jobs
User Inspector (Support Tooling)
Selecting a user from the admin user list opens an inspector with tabbed support tooling:
- Overview / Accounts / Characters / Activity — read-only context about the user, their linked accounts, and their characters. The Characters tab also exposes a "Sync from Battle.net" action that triggers a character sync for that user (disabled when no Battle.net account is linked), with inline progress while the sync is running.
- Sessions — list of active sessions with per-row revoke. Revoking a single session deletes just that session row; the user stays signed in on any other device.
- Notes — admin-only notes attached to a user. Each note is authored by the admin that created it and can be edited or deleted by any admin. Used to record support context (e.g. "confirmed identity via Discord on 2026-04-10"). Backed by the
AdminUserNotetable. - Danger Zone — destructive actions such as unlinking an account or soft-deleting the user. All destructive actions are recorded in the audit log.
Global Audit Log
Every admin-initiated mutation (user updates, account unlinks, note edits, session revokes, flag toggles, sync triggers, etc.) writes an entry to the audit log. The admin app exposes a dedicated /audit browser with:
- Filters: actor, target user, action type, date range
- Cursor pagination (stable ordering on
createdAt) - Per-row payload preview showing the diff of what changed
The set of action types is defined by the AdminAuditAction union on the API side.
API Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /admin/features | Public | Get platform feature flags |
| PATCH | /admin/features | Admin | Update feature flags |
| GET | /admin/users | Admin | List / search users (supports filters + cursor pagination) |
| PATCH | /admin/users/:id | Admin | Update user (display name, admin flag, etc.) |
| DELETE | /admin/users/:id/sessions/:sessionId | Admin | Revoke a single user session without signing the user out everywhere |
| POST | /admin/users/:id/accounts/unlink | Admin | Unlink a connected account (Discord / Battle.net) |
| GET | /admin/users/:userId/notes | Admin | List admin notes for a user |
| POST | /admin/users/:userId/notes | Admin | Create an admin note |
| PATCH | /admin/users/:userId/notes/:noteId | Admin | Update an admin note |
| DELETE | /admin/users/:userId/notes/:noteId | Admin | Delete an admin note |
| GET | /admin/audit | Admin | Browse the global audit log (filters + cursor pagination) |
| GET | /admin/organizations | Admin | List all organizations |
| POST | /admin/sync/journal | Admin | Trigger journal data sync |
| POST | /admin/sync/roster/:orgId | Admin | Trigger roster sync |
| POST | /admin/sync-user-characters/:userId | Admin | Trigger Battle.net character sync for a specific user |
| GET | /admin/sync-user-characters/:userId/active | Admin | Get active character sync session for a specific user |
| GET | /admin/jobs | Admin | List background jobs |
Frontend
The admin console is a separate Vite app under apps/admin, deployed to its own subdomain. The main web app (apps/web) only exposes an external link to it via the VITE_ADMIN_URL env var — no admin UI is bundled into the end-user app.
The admin app includes:
- Feature flag toggles (guild creation, character creation)
- Dashboard with platform statistics
- Users list + user inspector (accounts, characters, sessions, notes, danger zone)
- Global audit log browser (
/audit) - Organization list
- Sync controls with real-time progress indicators
- Job queue viewer
Every route in apps/admin is protected by the same isAdmin check on both the API and the app shell.