diff --git a/internal/check-nested-token-delivery.mjs b/internal/check-nested-token-delivery.mjs index 94bc4b362..acbeddbf9 100644 --- a/internal/check-nested-token-delivery.mjs +++ b/internal/check-nested-token-delivery.mjs @@ -97,6 +97,16 @@ if (leaves.length < MIN_LEAVES) { process.exit(1) } +// ★ THE AUTO CONTRACT (2026-09-26, by project decision: no Mapbox token in the public repo). With the +// build config's "token" EMPTY — the shipped default — a leaf must carry NO token, and must instead carry +// the runtime engine ladder (EXPLICIT / HAS_TOKEN): with no token it draws MapLibre, keyless; with one +// from the host, ?tk=, a paste or a token service, Mapbox. A builder who opts into baking a token +// ("token": "pk.…" in their own config) gets the original check: every leaf carries it. +let bakedToken = '' +try { bakedToken = String(JSON.parse(readFileSync(join(ROOT, 'vite.doxa-maps-build-config.json'), 'utf8')).token || '') } catch { /* none */ } +const BAKED = TOKEN_RE.test(bakedToken) +const AUTO_RE = /var EXPLICIT = [^;]*;[\s\S]*?var HAS_TOKEN = / + const missing = [] let checked = 0 for (const leaf of leaves) { @@ -108,9 +118,15 @@ for (const leaf of leaves) { } checked++ const html = readFileSync(abs, 'utf8') - if (!TOKEN_RE.test(html)) { + if (BAKED && !TOKEN_RE.test(html)) { missing.push({ ...leaf, why: 'no pk. token baked into the leaf — a nested map here would get NOTHING' }) } + if (!BAKED && TOKEN_RE.test(html)) { + missing.push({ ...leaf, why: 'a pk. token is in the leaf, but the build config bakes none — a token leaked into public output' }) + } + if (!BAKED && !AUTO_RE.test(html)) { + missing.push({ ...leaf, why: 'no runtime engine ladder (EXPLICIT/HAS_TOKEN) — with no token this leaf cannot fall back to MapLibre' }) + } } // The other direction: a token must never be compiled into a .js bundle. @@ -127,7 +143,7 @@ console.log(`NESTED-TOKEN: ${checked} shipped leaf page(s) checked, ${(manifest. if (missing.length || inBundles.length) { if (missing.length) { - console.error(`\nNESTED-TOKEN: FAIL — ${missing.length} leaf page(s) ship without a token:`) + console.error(`\nNESTED-TOKEN: FAIL — ${missing.length} leaf page(s) break the token contract (${BAKED ? 'baked token' : 'auto, no token'}):`) for (const m of missing.slice(0, 20)) console.error(` ✗ ${m.bundle}/${m.profile}\n ${m.url}\n ${m.why}`) if (missing.length > 20) console.error(` … +${missing.length - 20} more`) console.error( @@ -151,6 +167,7 @@ if (missing.length || inBundles.length) { } console.log(`NESTED-TOKEN: tree public/${treeName}/ (name from ${treeNameSource}).`) -console.log('NESTED-TOKEN: PASS — every shipped leaf carries its own token, and no bundle does.') +console.log(BAKED ? 'NESTED-TOKEN: PASS — every shipped leaf carries its own token, and no bundle does.' + : 'NESTED-TOKEN: PASS (auto) — no leaf or bundle carries a token, and every leaf picks its engine at runtime (MapLibre keyless without one).') console.log(' This is DELIVERY only. It does not prove a basemap paints: that needs a real GPU and') console.log(' a token whose URL restrictions allow the serving host (see verify:map-paint).') diff --git a/internal/check-provider-switch.mjs b/internal/check-provider-switch.mjs index 686252160..270a62945 100644 --- a/internal/check-provider-switch.mjs +++ b/internal/check-provider-switch.mjs @@ -78,9 +78,17 @@ let OWN_SERVER = null } } -async function run(provider) { +// A well-formed FAKE public token (never a real one): enough for the Mapbox engine to start and make its +// requests, which is all the comparison run needs. Requests that carry it are aborted, never sent. +const FAKE_TK = ['pk', Buffer.from(JSON.stringify({ u: 'provider-switch-check' })).toString('base64url'), 'c2ln'].join('.') + +async function run(provider, token = '') { const b = await chromium.launch({ args: ['--use-gl=swiftshader', '--enable-unsafe-swiftshader'] }) const pg = await b.newPage({ viewport: { width: 1280, height: 900 } }) + if (token) { + await pg.addInitScript((tk) => { window.MAP_TOKEN = tk }, token) + await pg.route((u) => /(^|\.)mapbox\.com$/i.test(u.hostname) && u.searchParams.has('access_token'), (r) => r.abort()) + } const hosts = new Map() let unparsed = 0 pg.on('request', (r) => { @@ -107,8 +115,13 @@ async function run(provider) { return { mapboxReq: count('mapbox.com'), globals, errs, unparsed, total: [...hosts.values()].reduce((a, n) => a + n, 0) } } -const def = await run(null) -const ml = await run('maplibre') +// ★ THE AUTO CONTRACT (2026-09-26). The default engine is 'auto': Mapbox only when a token is available. +// So the Mapbox baseline is ?provider=mapbox WITH a (fake) host token, the switch run adds the same token +// and ?provider=maplibre (an explicit engine must beat an available token), and a third run checks the +// no-token default is already keyless. +const def = await run('mapbox', FAKE_TK) +const ml = await run('maplibre', FAKE_TK) +const auto = await run(null) // DERIVED from the leaf's own HTML, not a hardcoded number: count the distinct // api.mapbox.com references the generated page carries, then allow a little slack @@ -120,8 +133,10 @@ const declared = new Set((pageHtml.match(/https:\/\/api\.mapbox\.com[^"')]+/g) | const PRELOAD_ALLOWANCE = Number(process.env.PROVIDER_PRELOADS ?? (declared.size + 1)) console.log(` page preloads : ${declared.size} distinct api.mapbox.com url(s) in the leaf HTML`) -console.log(` default : ${def.mapboxReq} mapbox / ${def.total} total request(s) ` +console.log(` ?provider=mapbox : ${def.mapboxReq} mapbox / ${def.total} total request(s) ` + `[mapboxgl=${def.globals.mapbox} maplibregl=${def.globals.maplibre}]`) +console.log(` no token (auto) : ${auto.mapboxReq} mapbox / ${auto.total} total request(s) ` + + `[mapboxgl=${auto.globals.mapbox} maplibregl=${auto.globals.maplibre}]`) console.log(` ?provider=maplibre: ${ml.mapboxReq} mapbox / ${ml.total} total request(s) ` + `[mapboxgl=${ml.globals.mapbox} maplibregl=${ml.globals.maplibre}]`) @@ -144,6 +159,9 @@ if (def.mapboxReq <= PRELOAD_ALLOWANCE) { fails.push(`the default run made only ${def.mapboxReq} mapbox request(s) — the map is probably ` + 'not rendering, so this comparison proves nothing') } +if (auto.mapboxReq > PRELOAD_ALLOWANCE) { + fails.push(`the no-token default made ${auto.mapboxReq} mapbox request(s) — 'auto' must draw MapLibre, keyless, with no token`) +} if (!def.total) fails.push('no requests were recorded at all — the tally is broken, not the page') if (ml.errs.length) fails.push(`${ml.errs.length} page error(s) under maplibre: ${ml.errs[0]}`)