zlh-grind/SESSION_LOG/2026-02-23-modrinth-install-integration.md

5.0 KiB
Raw Blame History

Session Summary Modrinth Mod Install Integration

Date: 2026-02-23 Type: Foundational Architecture + Implementation Status: Core flow complete, polish pending


Objective

Implement automated mod installation from Modrinth into Minecraft game containers via:

Portal → API → Agent → Filesystem

With security controls, validation, and production-grade guardrails.


What Was Completed

1. Modrinth Resolver (API Side)

Implemented resolveCompatibleVersion():

  • Fetches project versions from Modrinth API
  • Filters by loader (neoforge, fabric, quilt, etc.) and game version (e.g. 1.21.4)
  • Excludes alpha builds
  • Sorts by publish date (newest first)
  • Selects primary file and extracts filename, downloadUrl, sha512 (preferred), sha1 (fallback), size

Hardened:

  • .jar only enforcement
  • Host allowlist (cdn.modrinth.com)
  • Required hash presence validation
  • Proper 400 mapping for "not found" and "no compatible version"

2. Engine Metadata Bug Fix

Before (broken):

engineType = "minecraft"
engineVersion = "neoforge-1.21.4"

After (correct):

engineType = "neoforge"
engineVersion = "1.21.4"

Loader filtering now works correctly. The version string no longer includes the loader prefix.

3. API → Agent Payload Contract Fix

API was sending:

{
  "fileName": "...",
  "downloadUrl": "...",
  "size": 12345,
  "sha512": "..."
}

Agent expected:

{
  "source": "modrinth",
  "download_url": "...",
  "filename": "...",
  "sha512": "..."
}

Mismatch caused invalid mod_id errors. API payload corrected to match agent contract.

4. Agent Host Allowlist Expanded

Added cdn.modrinth.com alongside existing artifacts.zerolaghub.com.

Redirect policy still enforced:

  • HTTPS only
  • Must resolve to allowed host
  • Max 3 redirects

5. Agent Filename Validation Updated

Modrinth filenames contain + (e.g. sodium-neoforge-0.6.13+mc1.21.4.jar).

Updated allowed character set from [a-zA-Z0-9._-] to [a-zA-Z0-9._+-].

Still blocks: /, \, whitespace, path traversal, control characters.

6. End-to-End Install Verified

Mod successfully:

  • Downloaded from Modrinth CDN
  • SHA verified
  • Written to /tmp/zlh-agent/mods
  • Moved to /opt/zlh/minecraft/neoforge/world/mods/
  • Ownership set to minecraft, permissions 0644

Second install correctly returned mod already exists — duplicate protection confirmed working.


Security Controls Now In Place

Agent level:

  • HTTPS-only downloads
  • Host allowlist enforcement
  • Redirect limit (max 3)
  • 200MB hard cap
  • SHA256 verification
  • Filename sanitization
  • Duplicate prevention
  • Ownership enforcement (minecraft:minecraft)
  • Temp file cleanup on failure
  • Controlled mod directory write path
  • Cache invalidation

API level:

  • Auth + ownership enforcement
  • VMID validation
  • Timeout protection with AbortController
  • Resolver filtering (loader + version + stability)
  • Correct payload contract to agent

Current System State

Component Status
Modrinth resolver Stable
API route Working
Agent integration Working
Install flow Confirmed
Duplicate protection Working
Security model Intact

Remaining Issues

Response Corruption (Needs Verification)

One early curl output appeared corrupted — part of the curl command echoed in the response. Needs clean reproduction to determine root cause:

curl -sS -D headers.txt -o body.txt ...

Could be: terminal wrap artifact, API returning raw non-JSON, agent returning malformed error, or logging leaking into response body.

Reproduce before wiring portal.

API Error Mapping Refinement

Currently all agent non-2xx responses return 502. Should improve:

  • "mod already exists"409 Conflict

Small API enhancement, low effort.


Next Steps

  1. Reproduce and resolve response corruption issue with clean curl test
  2. Tighten API error mapping (409 for duplicate, etc.)
  3. Wire install endpoint to portal UI — display Installing, Already installed, Failed (reason)
  4. Begin dev-server linking system (see docs/architecture/dev-to-game-artifact-pipeline.md)

Future Work (Not Blocked On)

  • Automatic server restart after install
  • Update detection and mod version upgrade logic
  • Rollback integration (snapshot + shadow — see docs/architecture/mod-deployment-safety.md)
  • Mod state tracking in DB
  • Curated artifact coordinator

Strategic Note

This session was not routine bug fixing. The work done today:

  • Aligned contract layers across API and agent
  • Corrected the loader/version metadata architecture
  • Established a secure mod ingestion path
  • Created the foundation for the full mod management system

The architecture decisions locked here (host allowlist, filename validation, channel separation, payload contract) will apply to every future mod install path including dev promotion, curated updates, and self-healing rollback.

This was a foundational milestone.