From af297f2cdafd1431ea6e83ac440ebcdb265587e6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Apr 2026 05:13:34 +0000 Subject: [PATCH] =?UTF-8?q?bridge:=20REQ-2026-04-16-modpack-installer=20?= =?UTF-8?q?=E2=80=94=20Task=20#101,=20full=20spec,=20ready=20for=20Code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../REQ-2026-04-16-modpack-installer.md | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 docs/code-bridge/requests/REQ-2026-04-16-modpack-installer.md diff --git a/docs/code-bridge/requests/REQ-2026-04-16-modpack-installer.md b/docs/code-bridge/requests/REQ-2026-04-16-modpack-installer.md new file mode 100644 index 0000000..5431346 --- /dev/null +++ b/docs/code-bridge/requests/REQ-2026-04-16-modpack-installer.md @@ -0,0 +1,250 @@ +# REQ-2026-04-16-modpack-installer + +**From:** Chronicler #93 +**Date:** 2026-04-16 +**Priority:** HIGH — Michael wants this done tonight +**Status:** PENDING +**Linked Task:** #101 — AI-Powered Modpack Server Installer +**Architecture:** Fully locked via 4-round Gemini consultation +**Consultation docs:** +- `firefrost-operations-manual/docs/consultations/gemini-modpack-installer-trinity-console-2026-04-15.md` +- `firefrost-operations-manual/docs/consultations/gemini-modpack-installer-followup-2026-04-15.md` +- `firefrost-operations-manual/docs/holly-review-modpack-installer.md` + +--- + +## What This Is + +A full modpack installer integrated into Trinity Console. Holly reviewed and approved the full feature set. Bitch Bot (the first-boot provisioning mod) is already built and compiled — this is the Arbiter/Trinity Console side that drives everything. + +--- + +## Database Migrations + +### Migration 143 — server_config updates + +```sql +ALTER TABLE server_config +ADD COLUMN modpack_provider VARCHAR(50), +ADD COLUMN modpack_id VARCHAR(100), +ADD COLUMN current_version_id VARCHAR(100), +ADD COLUMN is_version_locked BOOLEAN DEFAULT FALSE, +ADD COLUMN locked_version_id VARCHAR(100) DEFAULT NULL, +ADD COLUMN lock_reason TEXT DEFAULT NULL, +ADD COLUMN spawn_verified BOOLEAN DEFAULT FALSE, +ADD COLUMN ram_allocation_mb INT NOT NULL DEFAULT 8192, +ADD COLUMN ram_ceiling_mb INT NOT NULL DEFAULT 16384, +ADD COLUMN hibernation_status VARCHAR(50) DEFAULT 'active'; +``` + +### Migration 144 — install_history table + +```sql +CREATE TABLE install_history ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + server_id UUID REFERENCES server_config(id) ON DELETE CASCADE, + pterodactyl_server_id VARCHAR(100), + job_type VARCHAR(50) NOT NULL, + target_version_id VARCHAR(100) NOT NULL, + triggered_by VARCHAR(100) NOT NULL, + status VARCHAR(50) NOT NULL, + started_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + completed_at TIMESTAMP WITH TIME ZONE, + duration_seconds INT, + mods_injected INT DEFAULT 0, + log_output JSONB DEFAULT '{}' +); + +CREATE INDEX idx_install_history_recent_failures +ON install_history(server_id, status, started_at); +``` + +--- + +## Job Queue (pg-boss) + +Add `pg-boss` as a dependency. Three queues: + +- `modpack-installs` — concurrency 2 (heavy file I/O) +- `maintenance-tasks` — concurrency 5 (ghost updates, hibernation) +- `fast-sync` — concurrency 20 (LuckPerms pings, Discord alerts) + +### Worker Execution Flow (modpack-installs) + +1. Job picked up → install_history status = `running` +2. Pre-flight: check node RAM/disk headroom, map Java version → correct egg. Refuse with clear error if insufficient headroom. +3. Pterodactyl server provisioned +4. Download pack mods via provider API. Scrub client-only mods (cross-reference `serverPackFileId` for CurseForge; skip 403s silently). +5. Inject Firefrost Standard Mod Stack from NextCloud (`standard-mods/{mc_version}/`) +6. Drop `provision.json` + `BitchBot-1.0.0-neoforge-1.21.1.jar` into server mods folder (skip if spawn_type = skyblock or has_lobby) +7. Stream everything to Pterodactyl via Wings SFTP +8. Create Cloudflare A + SRV records +9. Create Discord category + 5 channels (chat, in-game, forum, voice, status) +10. Add to status poller +11. Seed server_config record +12. Power on server → set spawn_verified = false → post staff Discord ping → install_history = success + +--- + +## Trinity Console Pages + +### GET /admin/modpack-installer + +Main installer page. Sections: + +**Provider Selection** — 6 providers with logos: CurseForge, Modrinth, FTB, ATLauncher, Technic, VoidsWrath + +**Pack Browser** (after provider selected): +- Search box +- Filters: category (Magic, Tech, Quests, Sci-Fi, Skyblock, Horror), mod loader (Forge, Fabric, NeoForge), MC version +- Pack cards: name, thumbnail, mod count, mod loader, MC version, short description + +**Pack Details + Version Selection** (after pack selected): +- Full description, screenshots if available +- Version dropdown (default: latest) +- Resource estimates: recommended RAM, disk based on mod count/pack size +- Smart node recommendation: query existing servers' RAM usage, recommend best node + +**Install Form:** +- Short name / subdomain (auto-suggested from pack name, slugified) — becomes Discord prefix + Cloudflare subdomain + DB short_name +- Display name +- Node selector (TX1 Dallas / NC1 Charlotte) — pre-filled from recommendation, overridable +- RAM allocation (pre-filled from estimate, adjustable) +- Spawn type: Standard / Skyblock / Has Lobby +- Confirm button → enqueues job → redirects to install status page + +### GET /admin/modpack-installer/status/:job_id + +Live install progress page. Shows: +- Current step (streaming via SSE or polling) +- Log output +- Success/failure state +- Link to server card on completion + +### GET /admin/modpack-installer/history + +Install history table. Columns: server, job type, version, triggered by, status, duration, started at. Filterable by status and server. + +### GET /admin/modpack-installer/pending-spawns + +Holly's queue. Lists all servers where spawn_verified = false. Each row: server name, installed date, "Mark Verified" button. This is Holly's only job after an install — log in, confirm spawn looks right, click verified. + +--- + +## Pre-Flight Mod Loader Check + +During step 2 of the worker flow, after downloading mods: +- Crack open each mod jar +- Read `META-INF/mods.toml` (NeoForge/Forge) or `fabric.mod.json` (Fabric) +- Verify loader matches the selected egg +- Log mismatches as warnings, don't hard-fail (some jars are multi-loader) +- If >20% of mods are wrong-loader, hard-fail with clear error before touching Pterodactyl + +--- + +## provision.json Structure (Bitch Bot input) + +Arbiter generates and drops this into the server root during step 6: + +```json +{ + "version": "1.0", + "schematic_name": "firefrost-spawn-v1.schem", + "schematic_url": "https://downloads.firefrostgaming.com/Firefrost-Schematics/firefrost-spawn-v1.schem", + "schematic_hash": "REAL_SHA256_GOES_HERE", + "spawn_type": "standard", + "spawn_coords": { "x": -5000, "y": 64, "z": -5000 }, + "paste_origin": "center", + "worldspawn_offset": { "x": 0, "y": 1, "z": 0 }, + "command_blocks": [ + { "position": { "x": -4998, "y": 65, "z": -4998 }, "facing": "up" }, + { "position": { "x": -5002, "y": 65, "z": -4998 }, "facing": "up" }, + { "position": { "x": -4998, "y": 65, "z": -5002 }, "facing": "up" }, + { "position": { "x": -5002, "y": 65, "z": -5002 }, "facing": "up" } + ], + "rules_signs": [ + { + "position": { "x": -4999, "y": 65, "z": -5005 }, + "lines": ["Welcome to", "Firefrost!", "Read /rules", "Have fun!"] + } + ], + "yawp_region": { + "name": "spawn", + "min": { "x": -5050, "y": 0, "z": -5050 }, + "max": { "x": -4950, "y": 255, "z": -4950 }, + "flags": ["no-pvp", "no-mob-spawning", "break-blocks", "place-blocks"] + }, + "self_destruct_on_success": true +} +``` + +Note: `schematic_hash` is a placeholder until Holly exports the real schematic. The installer should store this in .env or a config table so it can be updated without a code change. + +--- + +## .env additions + +``` +CURSEFORGE_API_KEY=your_key_here +WIKIJS_API_KEY=your_key_here +BITCH_BOT_SCHEMATIC_HASH=placeholder_until_holly_exports +BITCH_BOT_SCHEMATIC_URL=https://downloads.firefrostgaming.com/Firefrost-Schematics/firefrost-spawn-v1.schem +``` + +--- + +## Files to Create/Modify + +**New:** +- `migrations/143_server_config_modpack.sql` +- `migrations/144_install_history.sql` +- `src/services/modpackInstaller.js` — job worker, provider API clients, install orchestration +- `src/services/providerApi/curseforge.js` — CurseForge API client +- `src/services/providerApi/modrinth.js` — Modrinth API client +- `src/services/providerApi/ftb.js` — FTB API client (stub ATLauncher/Technic/VoidsWrath for now) +- `src/routes/admin/modpack-installer.js` — all installer routes +- `src/views/admin/modpack-installer/index.ejs` +- `src/views/admin/modpack-installer/status.ejs` +- `src/views/admin/modpack-installer/history.ejs` +- `src/views/admin/modpack-installer/pending-spawns.ejs` + +**Modify:** +- `src/index.js` — register pg-boss, mount installer routes +- `src/views/layout.ejs` — sidebar link to installer + pending spawns badge +- `package.json` — add pg-boss + +--- + +## Scope Notes + +**In scope for tonight:** +- Full installer flow (CurseForge + Modrinth primary, FTB stub) +- DB migrations +- pg-boss queue +- Pre-flight mod loader check +- Holly's pending spawns queue +- Install history + +**Defer to follow-up tasks:** +- Ghost updates (zero-downtime staging) +- Hibernation/wake-up system +- Dynamic RAM scaling +- Crash loop sentinel +- Cursed Modpack Roulette +- Clone to dev +- AI patch notes +- Auto-tier syncing (Redis/LuckPerms messaging) + +These are all in the Gemini consultation and have approved architecture. They become separate tasks after #101 ships. + +--- + +## Deploy Steps (after build) + +Standard Arbiter deployment pattern: +1. Run migrations 143 + 144 on Command Center +2. `npm install` (picks up pg-boss) +3. Copy files to `/opt/arbiter-3.0` +4. Restart arbiter-3 +5. Verify sidebar link appears +6. Test with a real CurseForge pack ID