LIVE https://todo-go-rastrillo.bfj.oncarlos.com 1364616

## Checks (2026-10-23, after the review round)

- `make test`: vet, gofmt, Go tests under Rastrillo's budgets, and
  `rastrillo migration check`, all green. `make perf` (first build):
  every GET screen under 1 ms median locally, cold boot 64 ms.
- Shared suite locally on `dist/app`: 67 passed, 3 skipped (the suite's
  own skips: the visual check and blur/Escape editing with JS off).
- `scripts/boot-check.sh dist/app-linux-arm64`: `/healthz` and
  `/api/version` 200, clean exit on SIGTERM.
- `make deploy`: swapped on the live host; `/api/version` reports
  `1364616`.
- Shared suite against the live host: 67 passed, 3 skipped.

## Review findings fixed

1. **Origin check.** `origin.go` no longer delegates to `csrf.Protect`.
   A POST whose `Origin` isn't exactly the app's origin gets 403, whatever
   `Sec-Fetch-Site` says. A new test sends a foreign `Origin` with
   `Sec-Fetch-Site: same-origin` and with `none`, and expects 403. Also
   checked by hand on the live host: 403.
2. **Unread forms.** Every `/todos` post is capped at 1 MiB and parsed
   before a handler runs, as `form.Parse`'s docs recommend. Too big gets
   413, malformed gets 400, and nothing changes. A new test posts an edit
   over 2 MiB and checks that the item survives.
3. **Typing during an add.** `app.js` clears `.new-todo` when the add is
   sent. After the response, the swap keeps whatever is in the field
   (and the caret). Checked in Chromium with the add response delayed by
   800 ms: text typed meanwhile was still there afterwards.
4. **Loopback only.** `main.go` refuses any TCP address whose host isn't
   `127.0.0.1` (`0.0.0.0`, `:8080`, `[::]`, `localhost` and so on) and
   exits with an error. Unit-tested, and checked by hand with
   `--listen 0.0.0.0:18432`.

## Review findings not fixed

None.

## Notes

- Rastrillo's local flag is `--addr`. `main.go` translates the bakeoff's
  `--listen` to it before `rastrillo.Resolve`.
- `carlos.Host()` isn't in v0.28.0 (it's on Rastrillo's main branch), so
  `main.go` reads `CARLOS_HOST` directly.
