Skip to content

fix(summarization): anon dashboards dispatch premium summarize-article RPCs — 401 flood + 3-provider fan-out since #4687 (client caller never swept) #4913

Description

@koala73

Symptom

Live console on https://worldmonitor.app/desktop (anonymous session, observed 2026-07-05 while verifying #4902/#4907):

[News Summarization] Failed: ApiError: Request failed with status 401
GET .../api/news/v1/summarize-article 401  [repeating]

Repeats continuously as news panels refresh (8+ in the first minute of page life).

Root cause — third instance of the server-gate-without-client-sweep pattern

#4675 → PR #4687 gated /api/news/v1/summarize-article LLM spend server-side (premium entitlement). The dashboard caller was never swept: src/services/summarization.ts routes every summarize attempt through premiumNewsClient = premiumFetch(..., { forcePremium: true }) — and premiumFetch is an auth-injection wrapper, not an entitlement gate (#4865): anon users fall through to a wms_ session token, dispatch the RPC anyway, and eat the 401.

Worse, API_PROVIDERS fans out ollama → groq → openrouter through the same RPC, so a single summarization attempt can burn up to 3 gated calls before falling back to browser T5. The tryApiProvider catch returns null (no 401/403-specific suppression), so every news refresh retries the whole chain.

Same class as: classify-event #4779#4865 (fixed by #4869 enqueue-gate + timed 403 suppress-drain) and health #4715#4902 (fixed by PR #4905).

Fix direction (per the #4869 pattern)

  1. 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.
  2. Server 401/403 → timed suppression window (suppress the whole API-provider chain, not per-provider) so signal drift can't recreate the flood; a mid-session upgrade self-heals when the window expires.
  3. Regression tests for the anon path (no RPC dispatched) and the suppression window.

Evidence

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions