Skip to content

TvdbProvider::bearer_token() issues a fresh HTTP login on every search and get_metadata call #416

Description

@forkwright

Finding

TvdbProvider calls self.bearer_token().await? at the top of both search() and get_metadata(). bearer_token() unconditionally POSTs to {BASE_URL}/login with the API key to obtain a fresh JWT, with no token caching. TVDB JWTs remain valid for 30 days after issuance, so every TVDB query issues a redundant login round-trip.

Evidence

crates/epignosis/src/providers/tvdb.rs:98:

let token = self.bearer_token().await?;

The same pattern appears at crates/epignosis/src/providers/tvdb.rs:141 in get_metadata(). The TvdbProvider struct holds no token-storage field, so the JWT is never retained between calls.

Why this matters

Each TVDB operation consumes 2 of the 10 req/s rate-limit budget (1 login + 1 actual call), halving effective throughput. During a batch enrichment run the login endpoint can itself become rate-limited, surfacing as intermittent ProviderRequestSnafu failures that read as "TVDB is down" rather than a client-side defect. Two concurrent TVDB queries each log in independently, compounding the redundancy. Under a network-observing adversary the doubled login traffic also doubles the observable request footprint per query, leaking more about device activity than necessary.

Desired correction

Cache the token and its expiry on TvdbProvider (e.g. Arc<tokio::sync::RwLock<Option<(String, Instant)>>>). On each call, reuse the cached token while it is still valid (e.g. issued within the last 24 hours) and POST to /login only when the token is absent or expired. Done when: 100 consecutive TVDB searches result in exactly 1 login request.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions