-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Mirrors
docs/architecture.mdin the repo.
BotFleet is a single Next.js 16 (App Router) application backed by PostgreSQL via Prisma. There's no separate backend service yet - the admin dashboard, the admin API, and the customer API are all routes in the same app.
app/admin/** Server-rendered dashboard pages (auth-guarded in
app/admin/layout.tsx)
app/api/admin/** Admin API - every route calls requireAdmin()
app/api/customer/** Customer portal API - every route scopes to the
signed-in user's own Customer/Bot rows
app/status Public, unauthenticated status page
app/setup First-run setup checklist (public until an owner exists)
auth.ts NextAuth v5 config (Discord OAuth + Prisma adapter)
lib/db.ts Prisma client singleton (driver adapter: pg)
lib/crypto.ts AES-256-GCM token vault
lib/plans.ts Plan tier limits (free/starter/pro/enterprise)
lib/runner/* RunnerAdapter interface + PM2/Docker stubs
lib/rebalance.ts Pure worker-rebalancing recommendation algorithm
lib/worker-assignment.ts Keeps Bot.workerGroupId, Worker.currentBots, and
WorkerAssignment in sync in one transaction
lib/security-checks.ts Real, dynamically computed security report
lib/alerts/discord-webhook.ts Discord embed alerts (mass mentions disabled)
prisma/schema.prisma The full data model
-
User/Account/Session/VerificationToken- the standard Auth.js Prisma adapter shape, extended withdiscordUserIdandrole(owner/admin/member). -
Customer- owned by aUser(ownerUserId). Any signed-in user who owns aCustomerrow can access that customer's bots through/api/customer/*. -
Bot- belongs to aCustomer, optionally assigned to aWorker. HoldstokenEncrypted(never returned by any API), plan, guild limit, shard count, and status. -
BotHealth- one-to-one withBot: guild count, ping, memory, restart count, last safe error. -
Worker/WorkerAssignment- a worker can run multiple bots (default 3-5, configurable viamaxBots);WorkerAssignmentis the join table, kept in sync withBot.workerGroupIdbylib/worker-assignment.ts. -
Shard- per-bot shard rows (only populated once a bot needs sharding). -
AuditLog- every admin/customer action that mutates state. -
Alert/WebhookDestination- alert records and where they're posted. -
Deployment- a record of what's deployed (not yet wired to an actual deploy pipeline).
lib/runner/types.ts defines a RunnerAdapter interface with
start/stop/restart. pm2-adapter.ts and docker-adapter.ts both
implement it today by updating Bot.status/BotHealth directly - they
don't spawn or control anything. Every method has a TODO(real-runner)
comment describing exactly what a real implementation needs (a worker
process that decrypts the token in-memory and either runs it under PM2 or
inside a Docker container). The rest of the product - dashboard actions,
audit logging, alerts, rebalancing recommendations - is built against the
interface, so wiring in a real runner later doesn't require changing any
caller.
lib/rebalance.ts is a pure function: given the current workers and bots,
it recommends (a) assigning any unassigned bot to the least-loaded worker
with spare capacity, and (b) moving bots off any worker that's over its
maxBots. It never moves anything itself - an admin applies a
recommendation from the bot's detail page, which calls
PATCH /api/admin/bots/:id with a new workerGroupId.
- Admin/owner: promoted via
BOTFLEET_ADMIN_DISCORD_IDSon first Discord sign-in (seeauth.ts'ssessioncallback). Can use/adminand every/api/admin/*route. Owners can promote/demote other users' roles at/admin/users(the last remaining owner can never be demoted). - Any other signed-in user: can create/own
Customerrows and manage their own bots via/api/customer/*, but has no access to/adminor/api/admin/*.