# electric-cherry Web app that manages a fleet of T5 Plutonium servers running under Komodo. Successor to `push_scripts.sh` — same job (push shared GSC scripts, run beta tests, restart empty servers, track deployments) with a live UI, real audit diffs, and a hard pause when the IW4MAdmin `!rt` token goes stale. ## Stack - SvelteKit (adapter-node) + TypeScript - SQLite via better-sqlite3 (replaces `script_metadata.json` as the source of truth) - Server-sent events for live pipeline / auth-state / server-status streams - Runs as a single Komodo-managed container on the same host as the game servers, with `/root/zombies` bind-mounted in ## Layout - `src/lib/server/db/` — schema, migrations, better-sqlite3 handle - `src/lib/server/fleet/` — file walking, push/beta engines - `src/lib/server/integrations/` — Komodo, IW4MAdmin, `!rt` token state - `src/lib/server/pipeline/` — sweep loop, event bus, worker singleton - `src/routes/api/` — REST + SSE endpoints - `src/routes/` — UI pages (dashboard, deployments, betas, per-server) - `docker/` — Dockerfile, entrypoint, docker-compose - `komodo/` — Komodo stack definition - `scripts/` — legacy JSON importer, fixture seeder - `tests/` — vitest unit tests ## Local dev Windows or macOS — no `/root/zombies` on disk, so seed a fixture tree first. ```bash npm install npm run seed:fixture # Point env at the fixture (PowerShell) $env:SHARED_SCRIPTS = "$PWD/test-fixtures/zombies/shared/scripts" $env:SERVERS_ROOT = "$PWD/test-fixtures/zombies/t5" $env:DB_PATH = "$PWD/data/cherry.db" npm run dev # open http://localhost:3000 ``` The `!rt` modal will block deployments until you paste a valid token. In local dev you can bypass it for exploration by leaving `IW4M_ADDRESS` unset and calling `sweep()` in a test that force-transitions the auth state (see `tests/unit/sweep.test.ts`). ## Tests ```bash npm test ``` Covers push (add/update/skip), beta lifecycle (open → rollback, open → promote, conflict blocks), sweep (frozen / manual branches), and IW4M login/status parsing (fetch mocked). ## Deploy to the Komodo host 1. Build the image once locally or on the host: ```bash docker compose build ``` 2. Import the shape of the stack into Komodo using `komodo/stack.toml` (or copy the compose file into a Komodo stack). 3. First boot triggers the legacy import: if `/root/zombies/script_metadata.json` exists and `/data/cherry.db` is empty, `docker/entrypoint.sh` runs `scripts/import-legacy.ts` before starting the server. The source JSON gets renamed to `.migrated`. 4. Load the app on the LAN or over tailscale (no web-app auth by design). Paste an `!rt` token to unfreeze the pipeline. ## What still lives in the shell script Nothing that's needed at runtime. Move `push_scripts.sh` to `archive/` once you've run a side-by-side parity check between the shell's dry-run and the app's `POST /api/push { dryRun: true }`. ## Non-goals - **Editing GSC files in-browser.** Do that in your editor of choice; the web app only cares about what's on disk in `SHARED_SCRIPTS`. - **Multi-user auth.** LAN/tailscale scoping is the security model. - **Two-way sync with `script_metadata.json`.** The importer runs once. If the shell script is ever used again after that, it'll write to the JSON file and the web app won't see it. ## References into the old script Every port carries a `// Ports push_scripts.sh:NN` comment pointing back to the original for the parts that had non-obvious behavior. Grep those if a behavior seems wrong — the shell script is the reference implementation until the parity check passes.