Skip to content

fix(providers): scope ChatGPT usage cache by credentials - #3594

Open
GautamSharma99 wants to merge 1 commit into
letta-ai:mainfrom
GautamSharma99:fix/chatgpt-usage-cache-scope
Open

fix(providers): scope ChatGPT usage cache by credentials#3594
GautamSharma99 wants to merge 1 commit into
letta-ai:mainfrom
GautamSharma99:fix/chatgpt-usage-cache-scope

Conversation

@GautamSharma99

Copy link
Copy Markdown

Summary

Fixes #3584.

Successful ChatGPT usage responses were cached for 30 seconds under keys derived only from the target, base URL, and provider name. The cache lookup happened before credential resolution, so a long-lived process could return one account usage data after switching credentials or local storage profiles.

This change resolves the effective authentication context first and scopes every cache lookup to an opaque fingerprint of that context.

What changed

Credential-scoped cache keys

Added a small CredentialScopedCache owner that derives keys with HMAC-SHA256 using a random, process-local 256-bit key.

  • Raw API keys, OAuth access tokens, account IDs, and storage paths are never stored in cache keys.
  • The same identity is stable for cache reuse during the process lifetime.
  • Changing any identity component creates a cache miss.
  • A process-local HMAC key prevents cache fingerprints from becoming reusable unsalted credential hashes if a key is ever surfaced in diagnostics.
  • Expired entries are removed opportunistically when new successful results are cached.

Cloud/API usage

Cloud credentials are now resolved, including any required token refresh, before cache access. The identity includes:

  • resolved cloud base URL;
  • provider name;
  • effective API/access token.

Changing credentials under the same URL and provider therefore cannot reuse the previous account cache. Removing credentials returns unauthorized before cache access instead of returning stale usage.

Local OAuth usage

Local OAuth credentials and the effective ChatGPT account ID are now resolved before cache access. The identity includes:

  • canonical absolute provider-auth file path, which distinguishes local storage roots/profiles;
  • provider name;
  • effective OAuth account ID;
  • effective OAuth access token.

This isolates identical provider names across storage directories, distinguishes account replacement even if a token value is unchanged, and invalidates reuse when OAuth refresh replaces the credential.

Invalidation behavior

Explicit cross-layer invalidation hooks are not required for correctness:

  • local provider existence is checked before cache access;
  • cloud authentication is resolved before cache access;
  • logout/provider removal returns an auth/not-connected error before any cached success can be read;
  • account or token replacement selects a different opaque key;
  • inaccessible old entries expire after the existing 30-second TTL.

This avoids introducing a dependency from backend credential storage into the provider usage service.

Tests

Added regression coverage proving:

  • two local storage roots with the same provider, account ID, and token still fetch independently;
  • a repeated read for the same local storage/account context uses the cache;
  • changing only the OAuth account ID under the same storage root and token causes a cache miss;
  • changing only cloud credentials under the same base URL/provider causes a cache miss;
  • repeated reads with the same cloud credential use the cache;
  • removing cloud authentication cannot return a previously cached success;
  • generated cache keys are stable for one identity, change with credentials, and contain none of the raw token, account ID, or storage path.

Validation completed:

  • bun test src/providers/chatgpt-usage-service.test.ts — 13 passed, 0 failed
  • bun run check — all 12 checks passed

The oversized chatgpt-usage-service.ts baseline is also ratcheted down from 1,112 to 1,111 lines.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ChatGPT usage cache is not scoped to the authenticated account

2 participants