bridge: REQ-2026-04-16-modpack-installer — Task #101, full spec, ready for Code
This commit is contained in:
250
docs/code-bridge/requests/REQ-2026-04-16-modpack-installer.md
Normal file
250
docs/code-bridge/requests/REQ-2026-04-16-modpack-installer.md
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user