feat(landing): self-serve registration page via Drasl API (B1)

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>
This commit is contained in:
2026-06-09 21:55:51 +02:00
parent 067e990306
commit df8ffca53e
11 changed files with 766 additions and 11 deletions

View File

@@ -45,11 +45,25 @@ invoking this skill is the authorization to proceed, but:
report (local changes on the host need manual resolution).
- `render-config.sh` re-renders drasl/nmsr/packwiz configs from `.env`
(needs `.env` complete: `BASE_DOMAIN`, `RCON_PASSWORD`,
`DISTRIBUTION_WEB_ROOT`, `CADDY_HTTP_*`).
`DISTRIBUTION_WEB_ROOT`, `CADDY_HTTP_*`, `REGISTRATION_MODE`). It halts on
an invalid `REGISTRATION_MODE` (must be `invite` or `open`).
- `fetch-authlib.sh` ensures `runtime/authlib-injector.jar` exists (gitignored;
skips if already valid). Missing jar = minecraft crashloops with "Error
opening zip file or JAR manifest missing".
2b. **Landing rebuild (only if needed).** The static site `www/` is gitignored —
`git pull` does NOT update it. If the pulled commits (from the step-1
pre-check) touch `landing/`, or `REGISTRATION_MODE` changed, rebuild it;
otherwise skip:
```bash
ssh cochi 'set -e
cd /home/ubuntu/mc/ulicraft-server-v1
cd landing && set -a && . ../.env && set +a && pnpm run build'
```
Sourcing `.env` bakes `BASE_DOMAIN` + `REGISTRATION_MODE` (invite-field on/off)
into the output. A flag-only change just needs this rebuild + a `drasl`
restart (already covered by step 2's `up`), not the world downtime.
3. **Verify.**
```bash
ssh cochi 'cd /home/ubuntu/mc/ulicraft-server-v1 && docker compose ps'