docs(files): record the general.host trap + that a green monitor proves nothing

Propagate the bare-hostname fix (10b86ae) to the docs that still said "three
traps", and write down the meta-lesson it exposed.

The bug was invisible to every check we had: Filestash strips the scheme
before its own Host check, so `curl /` returned 200, the API answered, wrong
passwords were rejected, and the brand-new Uptime Kuma HTTP monitor stayed
green — while the SPA computed `http://https://files...` and no browser could
use the site. An HTTP monitor asserts "server returned 200", which is a much
weaker claim than "the app works".

- CLAUDE.md / README: four traps now, host-scheme first; add the post-change
  check (`/api/config` → origin must be the real https URL).
- 19-routes: login form only renders at ?action=redirect (a bare 303 is
  normal, not a bug); assert origin after config changes.
- 10-uptime-kuma: an HTTP monitor cannot see an SPA break — use a Keyword
  monitor if you want teeth, and don't read green as "users can log in".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-14 18:31:46 +02:00
parent 10b86ae23e
commit 08fe8c9c53
4 changed files with 44 additions and 6 deletions

View File

@@ -106,8 +106,14 @@ automatically; cosmetic-client mods that declare `BOTH` stay `both` until you
hand-edit `mods-sides.json` to `client`. No Modrinth/packwiz, no network at
classify/sync time. See `plan/04-mods.md`.
### Filestash (files.) — three traps
### Filestash (files.) — four traps
Full list in `plan/20-files.md`; the ones that cost real time:
- **`general.host` is a BARE HOSTNAME** (`files.${BASE_DOMAIN}`, no scheme) +
`force_ssl: true`. The SPA builds its origin as `scheme + host`, so a URL there
yields `http://https://files...` and every client-side redirect dies. The
server strips the scheme before its own Host check, so **curl and the uptime
monitor stay green while every browser is broken**. Cost a debugging round on
2026-07-14.
- The `local` backend is **admin-gated**: without `LOCAL_BACKEND_SECRET` in the
connection params, every login fails with `backend error - Not Allowed` (looks
like bad credentials, isn't).
@@ -117,6 +123,12 @@ Full list in `plan/20-files.md`; the ones that cost real time:
purpose). Single-file bind mount ⇒ **`--force-recreate` after re-rendering**,
never `restart`.
**Verifying an SPA:** a 200 on `/` proves the server is up, not that the app
works. After any filestash config change, check the browser-facing values
(`curl /api/config``origin`) and re-read `docker compose logs filestash`
the broken redirect announced itself there (`msg=Redirecting to http://https://`)
while every other check passed.
### Memory sizing
~50100 mods, 8 players, 1.21.1: `INIT_MEMORY: 4G`, `MAX_MEMORY: 10G`,
`USE_AIKAR_FLAGS: TRUE`.