PM-tok, PRODUCTION-MATRIX.md:285. `tokenUrl` names a token SERVICE a host points at instead of pasting a key: the element asks that URL when it was handed no token. Only ProfileLoader ever read it. A pane composite bakes its children in rather than mounting them through ProfileLoader, so a composite embedded BARE -- one tag on a partner's page, which is the entire point of a composite -- dropped a tokenUrl-only config on the floor. It worked in every place anyone looked, because a ProfileLoader elsewhere on the page fetched and published the token: the composite was passing an exam somebody else sat. And the failure wears the wrong face. No token is "No Mapbox access token provided", 0 tiles, no canvas -- identical to a missing `tk`, which IS threaded -- so the natural reading is that the host mistyped their config rather than that a knob is unread. The rule lives in library/composables, not in each composite, because it has already been copied once (ProfileLoader.vue:132) and a third and fourth copy is how one of them later learns to ask ALWAYS -- which a token service billed per call notices before we do. The pure decision is split into host-token-url.js with NO framework import, because a fresh worktree has no node_modules and a module importing vue is unloadable by the gate that proves it right. Same shape as describeGroup keeping countryName injectable. check-composite-token-url takes its expectation from ProfileLoader -- the contract a composite REPLACES -- not from the composites it audits, so it cannot pass by construction; it exercises the decision rather than grepping for it; and it finds its subjects by a PROPERTY, a production bundle already forwarding `tk: hostToken`, so a third composite is covered the day it is written. stack-demo has the same shape and is excluded by its STAGE, not by name, so promoting it pulls it in automatically. Negative-tested 5 ways. The fifth found a bug in the gate itself: /tokenUrl/ also matches `tokenUrlX`, so the check meant to notice the contract being renamed could not fail. It is \btokenUrl\b now. A guard that cannot fail is the one nobody ever finds by reading.
23 lines
1.1 KiB
JavaScript
23 lines
1.1 KiB
JavaScript
/**
|
|
* host-token-url.js — the `tokenUrl` rule, with NO framework import, so a gate can run it.
|
|
*
|
|
* Split out of useHostTokenUrl.js deliberately. The composable needs vue's computed/watch; a headless
|
|
* gate has no node_modules in a fresh worktree, so a module that imports vue is unloadable by the test
|
|
* that proves it right. Same shape as library/packets/describeGroup.js keeping countryName injectable:
|
|
* the DECISION lives where it can be executed, the WIRING lives where it needs a framework.
|
|
*/
|
|
|
|
/**
|
|
* Ask the token service ONLY when nothing else supplied a token.
|
|
* Mirrors ProfileLoader.vue:133 — `url && !tk && !shared` — because a composite must behave the way the
|
|
* loader it replaces behaves, and because a service billed per call should be asked once, not always.
|
|
*/
|
|
export function shouldFetchTokenUrl({ tokenUrl = '', token = '', sharedToken = '' } = {}) {
|
|
return Boolean(tokenUrl) && !token && !sharedToken
|
|
}
|
|
|
|
/** The `tokenUrl` a host actually wrote, or ''. A non-string is not a URL and is not passed on. */
|
|
export function readHostTokenUrl(cfg) {
|
|
const u = cfg && cfg.tokenUrl
|
|
return typeof u === 'string' && u ? u : ''
|
|
}
|