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

@@ -31,6 +31,9 @@ Dependency-ordered. Each numbered item = one git commit. Operational steps
## Phase 5 — landing
10. `feat(landing): Astro+TS onboarding site → www/`
11. `chore(landing): wire logo + .gitignore for www/`
11b. `feat(landing): /register page → Drasl API (B1) + REGISTRATION_MODE flag`
(CORS/RateLimit/RegistrationNewPlayer in drasl config.toml.tmpl; see
`16-landing-registration.md`).
## Phase 6 — launcher distribution
12. `feat(tooling): add fetch-launcher.sh (all platforms + stable symlinks)`
@@ -49,8 +52,9 @@ Dependency-ordered. Each numbered item = one git commit. Operational steps
## Phase 10 — operational (no commits)
- [ops] Prep online (once): `tooling/render-config.sh`, build landing
(`cd landing && pnpm run build`), `tooling/fetch-launcher.sh`, fetch
authlib-injector into `runtime/`.
(`cd landing && set -a && . ../.env && set +a && pnpm run build` — sources
`.env` so `BASE_DOMAIN` + `REGISTRATION_MODE` bake into the static output),
`tooling/fetch-launcher.sh`, fetch authlib-injector into `runtime/`.
- [ops] TLS: `tooling/issue-letsencrypt.sh`, then
`tooling/render-nginx.sh --install`.
- [ops] Bring up: `docker compose up -d --build`.