Make NOT MEASURED name the blocked requests instead of guessing why

This gate reported a 403 as "tileset entitlement, not the embed" and printed
only the first blocked URL. Both halves were wrong.

The claim is disproved. Measured on this gate's own token: /v4/ streets-v8 and
country-boundaries both return 200 -- with no Referer, and from
research.nuxtbase.app, maps-dev.nuxtbase.app, doxa.life, 127.0.0.1 and
example.com. The token is unrestricted and entitled. The old conclusion rested
on three no-Referer probes, which cannot tell a URL-restricted token from a
missing entitlement; it named a cause those probes could not support. Whatever
403s is a different request -- a style, a sprite, glyphs, a composite -- or a
different token than the one measured.

Printing one URL is what hid that. A leaf blocked on forty tiles showed
whichever tile lost the race, so the tileset was never legible and a second
blocked endpoint was invisible behind the first.

NOT MEASURED now names every distinct blocked path, with tile coordinates
folded to {z}/{x}/{y} so one blocked tileset is one fact rather than forty, and
styles, sprites and glyphs stay separate -- which is exactly the class the
evidence now points at. It also names where the token came from (env var or the
leaf's own baked one), never its value: the query string is stripped before any
path is printed, asserted in the exercise below. The real-failure arm gets the
same treatment.

The gate asserts no cause any more. It reports what was blocked and lets the
reader judge.

Exercised on six URLs spanning two tilesets, a sprite and a glyph range: 6 ->
4 distinct facts, and a planted token value does not appear in the output.
This commit is contained in:
driver 2026-09-29 04:21:58 +00:00 committed by Doxa Maps
parent 38f027bac4
commit 496cd88091

View file

@ -20,11 +20,18 @@
* rendered fully blank while "a real GL canvas exists at 1200x780" passed. So drawing is asserted
* with queryRenderedFeatures() > 0 on the leaf's own rendered features, not by canvas geometry.
*
* ★ THREE EXIT STATES, BECAUSE TWO WOULD FORCE A LIE. On this sandbox the Mapbox /v4/ composite
* raster endpoint and country-boundaries both 403 — proven outside the browser with no Referer, with
* 127.0.0.1 and with localhost, so it is TILESET ENTITLEMENT, not the embed (PRODUCTION-MATRIX:235).
* Counting that as a failure would manufacture work for every owner; counting it as a pass would be
* false. It exits 75 NOT MEASURED instead, and says which endpoint.
* ★ THREE EXIT STATES, BECAUSE TWO WOULD FORCE A LIE. When a tile endpoint 403s, the leaf draws
* nothing through no fault of its owner. Counting that as a failure would manufacture work for every
* owner; counting it as a pass would be false. It exits 75 NOT MEASURED instead, NAMING every
* distinct blocked request path and the token's source, so the next reader can tell which
* credential was in play without the gate ever printing it.
* ✗ AN EARLIER VERSION CALLED THIS "TILESET ENTITLEMENT" AND THAT WAS WRONG. Measured 2026-09-29 by
* rega on this gate's own token: /v4/ streets-v8 and country-boundaries both return 200, with no
* Referer and from research.nuxtbase.app, maps-dev.nuxtbase.app, doxa.life, 127.0.0.1 and
* example.com. The token is unrestricted and entitled. The old claim rested on three no-Referer
* probes, which cannot distinguish a URL-restricted token from a missing entitlement. Whatever 403s
* is a different request or a different token — which is exactly what the gate must now report
* instead of guessing.
*
* USAGE MAP_TOKEN=pk.… node internal/check-mapbox-drew.mjs [--dir <tree>] [--only a/b,c/d]
* Run through internal/browser-slot.sh — it needs the browser seat.
@ -91,8 +98,30 @@ async function serve(dir) {
return { port, stop: () => { try { srv.kill() } catch (_) {} } }
}
// The endpoints known to 403 on the sandbox token. Entitlement, not the owner's bug.
// Endpoints whose 403 is NOT the leaf owner's bug, so a leaf blocked on one is NOT MEASURED
// rather than FAILED.
//
// ✗ WHY THIS NO LONGER CLAIMS "ENTITLEMENT" (corrected 2026-09-29). It used to report a 403 here
// as "tileset, not the embed", on the strength of three no-Referer probes. MEASURED since, by rega,
// with the very token this gate runs on: /v4/ streets-v8 AND country-boundaries return 200 — with
// no Referer, and with research.nuxtbase.app, maps-dev.nuxtbase.app, doxa.life, 127.0.0.1 and
// example.com. The token is unrestricted and entitled, so whatever 403s here is a DIFFERENT
// request (a style, sprite, glyphs, a composite with terrain) or a different token than the one
// tested. Three no-Referer cases cannot tell a URL-restricted token from a missing entitlement,
// and the old comment stated a conclusion those cases could not support.
// So this list stays — a 403 on a tile endpoint still makes a leaf unjudgeable — but the gate now
// NAMES every distinct blocked path and where its token came from, and asserts no cause.
const ENTITLEMENT = [/\/v4\//, /country-boundaries/]
// Where the token came from, so a NOT MEASURED says which credential was in play. Never the value.
const TOKEN_SOURCE = process.env.MAP_TOKEN ? 'env MAP_TOKEN'
: process.env.MAPBOX_TOKEN ? 'env MAPBOX_TOKEN'
: 'none in env (the leaf used its own baked token, if any)'
// Distinct request paths, query dropped and TILE COORDINATES folded to {z}/{x}/{y}: one blocked
// tileset requested over 40 tiles is ONE fact, not forty, and a reader needs the tileset name, not
// which tile happened to be first. The query goes first, so a token can never reach the output.
const pathsOf = (urls) => [...new Set(urls.map((u) => String(u)
.replace(/\?.*/, '')
.replace(/\/\d+\/\d+\/\d+(?=(\.|@|$))/, '/{z}/{x}/{y}')))]
async function measure(page, url, provider) {
const errs = []
@ -143,10 +172,10 @@ for (const id of leaves) {
if (!drew) { notMeasured.push(`${id}: no sized canvas appeared within 30s`); continue }
// ── 4. THE ENGINE. A silent fallback is the failure worth catching. ──
if (drew.engine !== 'mapbox') { fails.push(`${id}: asked for ?provider=mapbox and the canvas that drew is ${drew.engine.toUpperCase()} — a silent fallback`); continue }
if (otherForbidden.length) { fails.push(`${id}: 403 on ${otherForbidden[0]} — not the known entitlement endpoints`); continue }
if (otherForbidden.length) { fails.push(`${id}: 403 on ${pathsOf(otherForbidden).join(' , ')} — not a tile endpoint [token: ${TOKEN_SOURCE}]`); continue }
// ── 5/6. DREW, or an entitlement 403 that makes it unjudgeable. ──
if (drew.features > 0) { passes.push(`${id}: mapbox canvas, ${drew.features} rendered feature(s)`); continue }
if (entitlement.length) { notMeasured.push(`${id}: 0 features and an entitlement 403 (${entitlement[0].replace(/\?.*/, '')}) — tileset, not the embed`); continue }
if (entitlement.length) { notMeasured.push(`${id}: 0 features; 403 on ${pathsOf(entitlement).join(' , ')} [token: ${TOKEN_SOURCE}]`); continue }
if (errs.length) { fails.push(`${id}: 0 rendered features, page error: ${errs[0].slice(0, 90)}`); continue }
fails.push(`${id}: mapbox canvas drew 0 rendered features, and no 403 explains it`)
}