Development
Repository layout
What lives where, and which pieces are duplicated on purpose.
apps/hub Fastify: device sockets, scheduler, source pollers, artifact cache
apps/web Next.js dashboard
apps/docs This documentation site (Fumadocs)
packages/db Prisma schema + client
packages/protocol Wire protocol shared by hub and dashboard (mirrored in Go)
agent The Go agent
agent/magisk The Magisk module's own files: module.prop and the three hooks
deploy Compose stacks and the Caddy edge
scripts Bulk provisioning, fake fleet, buildsA pnpm workspace (apps/*, packages/*) on Node 22. make module packs
agent/magisk plus the two ARM binaries into dist/, stamping the version
from VERSION — nothing in agent/magisk is edited per release.
Inside the hub
apps/hub/src
├── index.ts Fastify bootstrap, /healthz
├── env.ts Typed environment
├── bus.ts In-process event bus, fanned out over SSE
├── registry.ts Live device sockets
├── routes/
│ ├── enroll.ts POST /api/enroll
│ ├── authz.ts GET /internal/authz (Caddy forward_auth)
│ ├── files.ts GET /files/* (only when SERVE_ARTIFACTS)
│ ├── events.ts GET /internal/events (SSE to the dashboard)
│ ├── logs.ts POST /api/logs/* (log bundles a box uploads)
│ ├── screenshots.ts POST /api/screenshots/* (screen captures a box uploads)
│ └── internal.ts Everything the dashboard commands
├── services/
│ ├── scheduler.ts Dispatch, concurrency caps, stall detection
│ ├── rollouts.ts Canary, soak, pause/resume
│ ├── jobs.ts Per-device job lifecycle
│ ├── artifacts.ts Cache-once + sha256
│ ├── autoUpdate.ts The hands-off pipeline
│ ├── monitor.ts Rules, escalation, circuit breakers
│ ├── notify.ts Discord, ntfy and web push, for alerts and events
│ ├── fleetEvents.ts What the fleet announces: rollouts, builds, machines
│ ├── rotom.ts Scanning state, matching, restart
│ ├── hubSettings.ts The cached copy of the settings groups
│ ├── uploads.ts Manual installs: an APK in, an AppVersion out
│ └── sources/ feed.ts, poller.ts, types.ts
└── ws/deviceSocket.ts The protocol, server side