Skip to content

fix(rate-limit): five paid-provider market routes missing from FAIL_CLOSED_ENDPOINT_RATE_POLICY_REQUIRED #6236

Closed

Description

@koala73

Summary

server/_shared/rate-limit.ts:341 defines FAIL_CLOSED_ENDPOINT_RATE_POLICY_REQUIRED — the registry
for routes that proxy paid providers and must not fail open when Redis is unavailable.

Five market/economic routes that proxy paid providers are absent from it entirely (verified: zero
matches for any of them in rate-limit.ts). They fall through to the global 600/min per-IP fallback,
which fails open, and none is Pro-gated.

The routes

Route Paid provider reached on cache miss
/api/market/v1/analyze-stock Finnhub + the Exa → Brave → SerpAPI ladder inside stock-news-search.ts:196,247,283
/api/market/v1/backtest-stock Yahoo Finance (keyless, but scraped — ban risk)
/api/market/v1/get-insider-transactions Finnhub (get-insider-transactions.ts:69, FINNHUB_API_KEY)
/api/market/v1/get-country-stock-index Yahoo Finance
/api/economic/v1/list-world-bank-indicators World Bank (keyless)

All five take unbounded input (arbitrary ticker / arbitrary indicator × country × year), so cache-key
cardinality is caller-controlled. A caller cycling distinct symbols drives real fan-out to three paid
key pools purely from free-tier traffic.

Why this is inconsistent with the rest of the codebase

This is exactly the risk class the codebase already recognizes and gates. lookup-sanction-entity,
get-company-enrichment, list-company-signals and search-sec-filings all sit in
FAIL_CLOSED_ENDPOINT_RATE_POLICY_REQUIRED at 30/min, with the reasoning spelled out at
server/_shared/rate-limit.ts:267-271:

each cache miss proxies SEC EDGAR and/or Finnhub on the caller's behalf, and the per-company inputs
are effectively unbounded (any ticker/name/domain), so these cannot inherit the fail-open global
fallback.

That reasoning applies verbatim to all five routes above. They were simply never added.

Proposed fix

Add all five to FAIL_CLOSED_ENDPOINT_RATE_POLICY_REQUIRED at the same 30/min provider-proxy budget.

analyze-stock deserves a lower budget than the rest — it is the only one that fans out to four
providers in a single request (Finnhub + the three-rung search ladder).

Acceptance criteria

  • All five routes have a fail-closed entry in FAIL_CLOSED_ENDPOINT_RATE_POLICY_REQUIRED
  • A test proves each fails closed when Redis is unavailable (mutation-tested: remove the entry,
    test goes red)
  • The enforce-rate-limit-policies lint (if it covers this registry) sees them

Context

Found during a full sweep of request-time external fetches while reviewing #6223.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions