Add a static /register page (en/es/eu) that calls the Drasl REST API v2
directly from the browser: register -> login -> optional skin upload, all
in the pixel design. Guests never touch Drasl's own web UI.
Drasl config gains the pieces this needs:
- CORSAllowOrigins scoped to the apex (the API has no CORS until set;
never "*").
- [RateLimit] for the now public-facing anonymous POST /users.
- [RegistrationNewPlayer] with RequireInvite driven by a new
REGISTRATION_MODE (invite|open) .env flag.
REGISTRATION_MODE has two consumers from one key: render-config.sh derives
the TOML boolean for Drasl (drasl is TOML-only, no env), and the landing
build reads it to show/hide the invite-code field. render-config.sh halts
on any value other than invite/open.
Security verified against drasl source: anonymous POST /users cannot set
privileged fields (isAdmin/isLocked/chosenUuid/maxPlayerCount are gated on
callerIsAdmin in CreateUser), so browser-direct registration is safe.
Docs: plan/16-landing-registration.md captures the design + the B1 vs fork
decision; build-order, deploy, and the deploy skill wire REGISTRATION_MODE
and the landing-rebuild requirement (www/ is gitignored, not updated by a
git pull).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The server JVM agent (runtime/authlib-injector.jar, mounted at /extras) is
gitignored and was previously fetched by the deleted build-stack.sh prep. A
fresh checkout had no jar, so minecraft crashlooped with "Error opening zip
file or JAR manifest missing". Add a standalone fetch tool: resolves the latest
release asset, downloads, and verifies it's a real zip/jar (PK magic) before
trusting it. Idempotent (skips if valid, --force to re-download). Wire it into
the deploy skill and README launch steps.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the override-file matrix into a single docker-compose.yml holding the
whole stack: drasl, minecraft, mc-backup, caddy, nmsr, uptime-kuma. Bring-up is
now just `docker compose up -d --build`.
Removed features (dead-ends for this deployment):
- airgap / full asset mirror (mirror-airgap.sh, mirror-mods.sh, 20-mirror.caddy,
caddy local-CA export, /ca.crt)
- dnsmasq + avahi/mDNS + dns-records.sh + mdns-host-setup.sh + ENABLE_MDNS;
DNS is now handled outside this repo (HOST_LAN_IP dropped)
- Blessing Skin auth variant (compose + 00-core-blessingskin.caddy + BS_* env)
- host-nginx-static variant (docker-compose.nginx.yml, nginx/ulicraft.conf.tmpl)
- build-stack.sh and its run modes (online/airgap/core)
Production ingress is the only path now: host nginx terminates TLS (LE certs)
in front of caddy on a localhost-only port; caddy routes every vhost by Host
header. Launcher downloads move mirror/launcher -> launcher/.
Docs: README, deploy skill, and plan/ rewritten to match; obsolete plan docs
(dnsmasq, blessing-skin, assets-mirror, full-airgap-mirror, dns-and-run-modes)
deleted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
plan/14-deploy.md: git pull main + hard restart (compose down ->
build-stack.sh --up online), drasl/online, verify + rollback.
.claude/skills/deploy: skill to run it (pre-check, pull, hard restart,
verify) with prod guardrails.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>