diff --git a/documentation/reference.md b/documentation/reference.md index 57385b5c9..93796add9 100644 --- a/documentation/reference.md +++ b/documentation/reference.md @@ -304,9 +304,9 @@ eight `--url` flags from scratch, which is why the gate had never been run acros ```sh cd doxa-maps-plugin-studio -( cd public && python3 -m http.server 4950 --bind 127.0.0.1 & ) # serve the built tree, LOOPBACK ONLY -export MAPBOX_TOKEN=$(curl -s https://doxa.life/api/maps/token \ - | python3 -c 'import json,sys;print(json.load(sys.stdin)["token"])') +( node internal/serve-strict.mjs --port 4950 & ) # serve the built tree, LOOPBACK ONLY +# ★ Take the token from the BUILD CONFIG, not from doxa.life/api/maps/token — see the note below. +export MAPBOX_TOKEN=$(python3 -c "import json;print(json.load(open('vite.doxa-maps-build-config.json'))['token'])") B=http://127.0.0.1:4950/doxa-maps ARGS="" @@ -330,17 +330,40 @@ node internal/share-roundtrip-smoke.mjs $ARGS --browser chromium | `smoke:embeds` · `verify:map-paint` · `verify:5-caps` | `MAPBOX_TOKEN` in the environment | **does not fail — it DEGRADES.** Without a token map profiles cannot mount, and `smoke:embeds` reports them as TIMEOUTS. It once read 27/40 for this reason and 40/40 with a token. A timeout here means "no token" far more often than "broken plugin" | ```sh -# the token every map gate wants. Verified 2026-09-22: returns 200 to a plain curl (no browser -# User-Agent needed — that requirement belongs to pray.doxa.life, a different host) and yields a -# 90-char pk. token. -export MAPBOX_TOKEN=$(curl -s https://doxa.life/api/maps/token | python3 -c 'import json,sys;print(json.load(sys.stdin)["token"])') +# The token every map gate wants. Read it from the build config: measured 2026-09-23, the config +# token serves tiles (200) from any origin, while the doxa.life endpoint's token returns 403 from +# anywhere but doxa.life. Both are 90-odd-char pk. public keys; only one of them works here. +export MAPBOX_TOKEN=$(python3 -c "import json;print(json.load(open('vite.doxa-maps-build-config.json'))['token'])") ``` -> **The token is URL-restricted, and that limits what these gates can prove here.** Measured: tiles -> return **200** with a `doxa.life` Referer and **403** from `127.0.0.1`, `localhost`, `nuxtbase.app` -> or no Referer. So on this box a map can *mount*, load its style and paint its data layer while the -> basemap stays empty — `verify:map-paint` still passes, because a live GL context and attribution -> are exactly what it asserts. Judging "does it LOOK right" needs an allow-listed origin. +> **THIS LIMITATION WAS SELF-INFLICTED, and it is fixed — corrected 2026-09-23.** This paragraph +> used to say a blank basemap was simply the cost of working here. It measured the right thing about +> the WRONG TOKEN: the one served by `https://doxa.life/api/maps/token` is URL-restricted to +> `doxa.life`, returning **403** from `127.0.0.1`, `localhost`, `nuxtbase.app` or no Referer. That is +> a property of that token, not of this box — and the command above used to fetch it, so the doc +> diagnosed the blank basemap and then kept prescribing its cause. +> +> The `token` field in `vite.doxa-maps-build-config.json` returns **200** on the identical request +> from any origin. It is a `pk.` public key baked deliberately (Driver ruling 2026-09-21), protected +> by URL restrictions rather than secrecy; `check:public-hygiene` allows `pk.` and fails the build on +> `sk.`/`tk.`. So the SHELL COMMANDS above — the ones that curl a token and hand it to a gate as +> `MAPBOX_TOKEN` — now work where they previously fetched a token that 403s. +> +> **★ BE PRECISE ABOUT WHAT THIS FIXES, because an earlier draft of this very paragraph overstated +> it.** Measured 2026-09-23 with the doxa.life token: curl returns **403** with no Referer, **403** +> with `Referer: http://127.0.0.1:4173/`, and **200** with `Referer: https://doxa.life/`. So the +> restriction is real and it does block the curl path. But a browser gate loading a leaf still fetched +> **9 `/v4/` tiles with 0 failures** — because the page resolves its token through a LADDER and the +> built bundle carries the working baked token, so the `?tk=` rung is not necessarily what the map +> ends up using. The fix is to the SHELL commands; the browser gates were never the ones affected. +> +> Two corrections that came out of measuring this, both worth inheriting. First, the basemap here is +> **Mapbox Light** — pale land, grey water, minimal detail so the choropleth dominates. Looking at a +> screenshot I briefly called it "not painting" because I expected terrain and roads; the country +> labels and borders ARE the basemap. Judge tile loading by the `/v4/` response count, not by whether +> the image looks like a road map. Second, `verify:map-paint` passes under BOTH tokens, because it +> asserts a live GL context and attribution rather than loaded tiles — so it is not the signal to +> consult about whether tiles arrived. > **★ AN EXIT CODE IS NOT A VERDICT UNTIL YOU HAVE READ THE MESSAGE.** Two of these read as FAIL in a > batch run and are neither passing nor failing — they never started. A checklist that turns a