Admin panel
What the platform admin sees: personas, job queue, GPU provisioning, LoRA dashboard, events feed, Plan-100 control plane.
TL;DR
The admin is a separate React 19 SPA, accessible only to the admin role. It manages cross-workspace resources: system personas, prompt recipes, LoRA models, job queue, Vast.ai instances, provisioning rules, billing, audit. The headline new feature — the Plan-100 Control Plane Console with coordinator/runner/reconciler and shadow-tables for cutover.
Admin overview
The GoraGen admin is the operations cockpit. Through it the platform team sees what's happening across the entire product at once: how many GPUs are rented, which jobs hung, which users spend the most, which models perform poorly.
The shell — AdminShell.tsx with a sidebar and keyboard shortcuts for fast navigation.
Dashboard
Main screen — KPIs and live metrics:
- Active jobs (by type: video, storyboard, kling, lora_training)
- Queue depth and average lead time
- Error counter for the last 5/15/60 minutes with severity filter
- Current Vast.ai instances and their state (booting / ready / running / cancelling / destroyed)
/admin/system/workers-health monitors the heartbeat loop from the workers container — if the last heartbeat is older than 60 seconds, the dashboard fires a "workers down" alert.
Users
/admin/users — user browser. Clicking a user_id opens details: workspace, generation history, credit balance, daily-spend profile, plan, IPs of recent logins.
The admin can:
- Change the user's plan (Free → Starter → Pro)
- Add/deduct credits manually
- Impersonate (cookie with
impersonated_by=:admin_idflag) — to triage "X doesn't work for me" complaints
All these actions are written to domain_events and visible in compliance for audit.
Personas / Presets / Workflows
Three separate CRUD sections for the platform's content backbone:
/personas— system personas. Each has a lookbook (12+ frames), presets (camera, background, lighting), a list of LoRA models./presets— library of prompt templates and camera moves./workflows— ComfyUI graph templates. A template can be tied to a model (WAN, Hunyuan, LTX) and used by the renderer.
Tasks
/admin/tasks — job queue console. Four tabs: queued / live / recent / failed.
Clicking a specific job opens full details: workspace, user, instance, input parameters, execution log, progress WS messages, Gemini evaluation, total cost. On failure — a stack trace with the Sentry event id.
From live you can cancel (graceful — let the current iteration finish, don't start the next). From failed you can re-run (a new job with the same parameters).
Instances
/admin/instances — Vast.ai instance browser. For each instance:
- offer_id, image, region, $/hour price
- state (booting / ready / running / cancelling / destroyed)
- current job (if any)
- cost since launch
- buttons terminate / SSH-connect / re-init
All manual instance operations now go through the Control Plane (see below), not via a direct Vast API call.
LoRA dashboard
/admin/lora — cross-workspace view of all LoRA training jobs. For each:
- status (preparing / captioning / training / validating / done / failed)
- percent progress, ETA
- link to validation grid (result preview)
- cost, duration
The admin can kill a stuck training, restart a failed task, look at the kohya_ss log.
System
/admin/system — the technical part of the admin, split into sub-tabs:
audit— admin action loghealth— extended health page (Phase 9): workers heartbeat, DB latency, disk usage, queue depthprovisioning— auto-provisioning rules (when the platform rents a new instance, when it kills one)spend— financial summary by GPU hours and Anthropic / Gemini / Kling API callsevents— Phase 9 domain events feed (append-only, last 1000 events) with a JSON modal for each
Plan-100 Control Plane Console
/admin/system/control-plane — a dedicated page for managing the coordinated provisioning system.
This is the move from direct Vast API calls to an orchestration model where three loops sit between the admin and Vast:
- Coordinator — reads
instance_requests(provisioning requests), checks parallel limits and velocity guard, inserts intoprovision_attempts. - Runner — picks up claimed attempts, calls
scripts/vast_provision.ensure_instance(...), applies the terminal reducer. - Reconciler — every N seconds scans stale leases, force-terminates instances stuck in
cancelling, releases destroyed instances.
All three — leader-elected via the provision_leader table. If the container with the leader dies, the second one (if any) picks up leadership within 60 seconds.
On the page:
- Live status of the three loops (running / lost / draining)
- Observability metrics: 7 numbers (active requests, queued attempts, success rate, etc.)
- Pause button — emergency flag that stops all three loops within 30 seconds
- Resume button — clears the emergency pause
Under the hood — 5 cutover flags with a 60-second TTL cache: workflow_spawn, auto_provisioner, parallel_limits, provisioning_cutover_admin_rule_action, provisioning_emergency_pause. You can flip each one independently — for example, disable the auto-provisioner while keeping the rest.
Settings
/admin/settings — runtime-tunable system settings:
- maintenance_mode — global 503 for non-admins
- prices — generation costs (per shot, per second, per LoRA train)
- retention — TTL for videos, events, idempotency keys
Setting changes propagate to all workers within 60 seconds via polling.
Events feed
Phase 9 introduced append-only domain_events. Every significant platform event (new user, new job, provisioning failure, plan upgrade) is written as a separate row with type, actor, payload JSON.
In the admin, /admin/system/events — a reactive feed with filters by event type, actor, date range. Double-click — a modal with pretty-printed JSON.
This delivers two things: forensic audit (what happened in the last 24 hours) and an event source for integrations (event delivery to external webhooks via webhook_dispatcher).