mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-04 14:57:42 +00:00
* 🔒 fix: Single-Flight MCP OAuth Token Refresh per User/Server Concurrent refresh-token redemptions (tool-call 401, ping, reconnect retries, expired-token reads) each replayed the same stored refresh token at the OAuth token endpoint. RFC 9700 reuse detection treats the replay as theft and revokes the entire grant family, forcing manual re-consent every access-token expiry. MCPTokenStorage.forceRefreshTokens is the choke point every refresh path converges on; it now single-flights redemptions per (tenantId, userId, serverName) so concurrent callers share one wire call and receive the same rotated result. The refresh token is re-read from storage inside the locked execution — never from a caller snapshot — so a redemption starting after another refresh completed uses the rotated token instead of replaying the consumed one. Fixes #14583 * 🧪 test: Isolate Single-Flight Keys per Test via Unique Server Names * 🔒 fix: Evict Stalled Refresh Slots, Decouple Waiter Aborts from Shared Redemption Codex review round 1: - A redemption that never settles no longer wedges the single-flight slot until process restart: a stale-entry timer evicts the map entry so later refreshes start fresh, while existing waiters keep their promise. - Caller AbortSignals no longer thread into the shared redemption. An impatient waiter (silent refresh's short timeout) resolves its own wait with null via a per-waiter race; the shared wire call proceeds for everyone else, bounded by transport timeouts plus eviction. * 🔒 fix: Abort Stalled Refreshes Before Slot Release, Hook Cache Invalidation to Redemption Codex review round 2: - The stale timer now aborts the wedged execution instead of deleting its slot; the slot frees only once the execution has settled, and an abort guard before the token-endpoint call stops a woken pre-wire stall from replaying a refresh token a successor already rotated. - New onRefreshSuccess hook runs inside the shared redemption after rotated tokens persist, so the silent-refresh path's mcp_get_tokens cache invalidation fires even when the initiating waiter timed out before the redemption completed. * 📝 docs: Record Post-Dispatch Abort Recovery Rationale on Stale-Refresh Valve |
||
|---|---|---|
| .. | ||
| src | ||
| types | ||
| .gitignore | ||
| babel.config.cjs | ||
| jest.config.mjs | ||
| jest.setup.cjs | ||
| package.json | ||
| tsconfig-paths-bootstrap.mjs | ||
| tsconfig.build.json | ||
| tsconfig.json | ||
| tsconfig.spec.json | ||
| tsdown.config.mjs | ||