Context
Follow-up to #4485 and the live bootstrap validation.
api/bootstrap.js now validates user API keys correctly and returns no-store for bad/user/enterprise key auth. The remaining cache boundary should be explicit: only anonymous GET /api/bootstrap?keys=weatherAlerts is allowed to be shared-cacheable.
Evidence
- Live retest shows fake
X-WorldMonitor-Key and fake X-Api-Key on /api/bootstrap return 401 no-store after cache bypass.
- Source review shows
successCacheHeaders() is public/CDN-cacheable for non user-key auth kinds by default, so session/default/tiered bootstrap success paths can remain shared-cacheable by accident.
Scope
- Make public shared caching opt-in for
authKind === "public-weather" only.
- Make session/default/tiered bootstrap success responses no-store or private non-shared; choose the safest posture unless product requires browser-private caching.
- Keep the existing anonymous weather exception cacheable.
Acceptance Criteria
- Anonymous
/api/bootstrap?keys=weatherAlerts remains 200 and cacheable.
- API-key and session/default bootstrap success responses are not shared-cacheable.
- Bad bootstrap auth stays 401 no-store and never returns the gateway-validation sentinel.
- Bootstrap tests cover the cache matrix.
Context
Follow-up to #4485 and the live bootstrap validation.
api/bootstrap.jsnow validates user API keys correctly and returns no-store for bad/user/enterprise key auth. The remaining cache boundary should be explicit: only anonymousGET /api/bootstrap?keys=weatherAlertsis allowed to be shared-cacheable.Evidence
X-WorldMonitor-Keyand fakeX-Api-Keyon/api/bootstrapreturn 401 no-store after cache bypass.successCacheHeaders()is public/CDN-cacheable for non user-key auth kinds by default, so session/default/tiered bootstrap success paths can remain shared-cacheable by accident.Scope
authKind === "public-weather"only.Acceptance Criteria
/api/bootstrap?keys=weatherAlertsremains 200 and cacheable.