An origin the profile declares, with what it may serve and whether it is cacheable.
⚠️ This replaces routing by GUESSWORK. The service worker currently decides by hostname
substring (hostname.includes("tile") matches mon-site-hostile.tilerie.com), by path
sniffing, by a hardcoded provider domain, and by a blanket /api/ exclusion that skips
the most common path of a data API. None of those can be reviewed, and two of them are
exploitable.
cacheable: false is meaningful and must stay expressible: a cross-origin tile provider
answering opaquely cannot have its content validated, so it is not cached — a correct
decision whose CONSEQUENCE (no raster basemap offline) has to be declared rather than
discovered.
The invariant, and the ONE thing it does not cover
Declaring any origin refuses every origin left undeclared. Silence is a refusal, not a
permission — that is what makes a declaration reviewable, and it governs everything below.
⚠️ It does NOT cover the origin that SERVES the application (decision B-119, arbitrated
07/08/2026). That origin changes with every deployment — localhost:8766 on the ports
target, demo.geoleaf.local.test behind nginx, production elsewhere — so no PORTABLE
profile can write it. Before the exception, a profile that declared its data origins lost
the cache of its own shell, i.e. offline altogether: all-or-nothing, where "nothing" was
only reachable by declaring nothing at all.
The exception is narrow, and the narrowness is the point. It covers what serves the
application — profile resources and static assets — and NOT same-origin data. A data API
served from the very same origin is still a DATA origin, by the exact motive that grants
the exception, and it must be declared like any other. Widening it to "same-origin" would
cache an authenticated same-origin response by default, i.e. open one defect while closing
another.
🛑 So the invariant is not weakened, it is delimited: silence refuses caching of DATA;
the application shell is not data. Enforced in kernel/storage/sw-core.js (routeRequest),
which is a standalone worker and cannot import this file — the parity is held by the source
guard in __tests__/storage/sw-core.test.js.
An origin the profile declares, with what it may serve and whether it is cacheable.
⚠️ This replaces routing by GUESSWORK. The service worker currently decides by hostname substring (
hostname.includes("tile")matchesmon-site-hostile.tilerie.com), by path sniffing, by a hardcoded provider domain, and by a blanket/api/exclusion that skips the most common path of a data API. None of those can be reviewed, and two of them are exploitable.cacheable: falseis meaningful and must stay expressible: a cross-origin tile provider answering opaquely cannot have its content validated, so it is not cached — a correct decision whose CONSEQUENCE (no raster basemap offline) has to be declared rather than discovered.The invariant, and the ONE thing it does not cover
Declaring any origin refuses every origin left undeclared. Silence is a refusal, not a permission — that is what makes a declaration reviewable, and it governs everything below.
⚠️ It does NOT cover the origin that SERVES the application (decision B-119, arbitrated 07/08/2026). That origin changes with every deployment —
localhost:8766on theportstarget,demo.geoleaf.local.testbehind nginx, production elsewhere — so no PORTABLE profile can write it. Before the exception, a profile that declared its data origins lost the cache of its own shell, i.e. offline altogether: all-or-nothing, where "nothing" was only reachable by declaring nothing at all.The exception is narrow, and the narrowness is the point. It covers what serves the application — profile resources and static assets — and NOT same-origin data. A data API served from the very same origin is still a DATA origin, by the exact motive that grants the exception, and it must be declared like any other. Widening it to "same-origin" would cache an authenticated same-origin response by default, i.e. open one defect while closing another.
🛑 So the invariant is not weakened, it is delimited: silence refuses caching of DATA; the application shell is not data. Enforced in
kernel/storage/sw-core.js(routeRequest), which is a standalone worker and cannot import this file — the parity is held by the source guard in__tests__/storage/sw-core.test.js.