Problem
An anonymous dashboard load dispatches 5 summarize-article round-trips that cannot produce a summary, then logs [Summarization] All providers failed — a warning that reads like a provider outage but is the designed anon path.
Measured on a live anonymous www.worldmonitor.app/dashboard session:
performance.getEntriesByType('resource').filter(e => e.name.includes('summarize'))
// 5 requests — [status, startMs, durationMs]
[[200,1404,447],[200,1404,487],[200,1404,558],[200,1405,516],[200,1405,338]]
All five return 200 — the server gate added for #4675/#4913 is working correctly and declines gracefully (resp.fallback / SUMMARIZE_STATUS_SKIPPED). This is not a 401/403 flood; #4913 and #5207 are genuinely fixed. The residual cost is 5 concurrent round-trips of ~340–560 ms each, fired in a ~1 ms burst, that are guaranteed no-ops for this user class.
Root cause — #4913 fix direction 1 never landed
#4913's proposed fix had two parts. Part 2 (server-side graceful gate) shipped. Part 1 did not:
- Enqueue gate: check
panel-gating.hasPremiumAccess() before dispatching any API-provider summarize attempt; anon/free goes straight to the browser T5 fallback (the designed anon path) with zero network calls.
src/services/summarization.ts contains no reference to hasPremiumAccess or panel-gating (origin/main c45acd49c):
$ grep -n "hasPremiumAccess\|panel-gating" src/services/summarization.ts
(no matches)
Its only pre-dispatch check is isFeatureAvailable(providerDef.featureId) (src/services/summarization.ts:338), which gates on provider/feature availability, not on the caller's entitlement. So the chain still fans out across API_PROVIDERS for users who can never receive a summary.
Then src/services/summarization.ts:320 reports the outcome as a failure:
console.warn('[Summarization] All providers failed');
Two call sites reach it per load — trending-keywords and panels-intel updateInsights:
at c0 (main-BXxARTx3.js:2:129385)
at l0 → G (trending-keywords-pwCxGERt.js:1:7357)
at l0 → updateFromClient (panels-intel-BwxhCj3q.js:616:41) → updateInsights → loadNews
Why this is worth fixing despite being small
Proposed fix
Related
Acceptance
- Anonymous dashboard load issues zero
summarize-article requests; verify with performance.getEntriesByType('resource').filter(e => e.name.includes('summarize')).length === 0.
- Signed-in premium path still summarizes normally (regression check — do not gate paying users out).
[Summarization] All providers failed no longer appears on a healthy anon load; a real provider failure still surfaces at warn.
Problem
An anonymous dashboard load dispatches 5
summarize-articleround-trips that cannot produce a summary, then logs[Summarization] All providers failed— a warning that reads like a provider outage but is the designed anon path.Measured on a live anonymous
www.worldmonitor.app/dashboardsession:All five return
200— the server gate added for #4675/#4913 is working correctly and declines gracefully (resp.fallback/SUMMARIZE_STATUS_SKIPPED). This is not a 401/403 flood; #4913 and #5207 are genuinely fixed. The residual cost is 5 concurrent round-trips of ~340–560 ms each, fired in a ~1 ms burst, that are guaranteed no-ops for this user class.Root cause — #4913 fix direction 1 never landed
#4913's proposed fix had two parts. Part 2 (server-side graceful gate) shipped. Part 1 did not:
src/services/summarization.tscontains no reference tohasPremiumAccessorpanel-gating(origin/mainc45acd49c):Its only pre-dispatch check is
isFeatureAvailable(providerDef.featureId)(src/services/summarization.ts:338), which gates on provider/feature availability, not on the caller's entitlement. So the chain still fans out acrossAPI_PROVIDERSfor users who can never receive a summary.Then
src/services/summarization.ts:320reports the outcome as a failure:Two call sites reach it per load —
trending-keywordsandpanels-intelupdateInsights:Why this is worth fixing despite being small
200s. Anyone triaging prod console noise will hit the same trap.Proposed fix
src/services/summarization.ts:320— a skipped/gated outcome should log atdebug/info(or not at all), reservingwarnfor real provider failure. Same for the[BETA]sibling at:301.Related
200, not401.Acceptance
summarize-articlerequests; verify withperformance.getEntriesByType('resource').filter(e => e.name.includes('summarize')).length === 0.[Summarization] All providers failedno longer appears on a healthy anon load; a real provider failure still surfaces atwarn.