(
row: ConnectionRow,
provider: CredentialProvider,
trigger: RefreshTrigger = "proactive",
)
| 2589 | ); |
| 2590 | |
| 2591 | const refreshConnectionToken = ( |
| 2592 | row: ConnectionRow, |
| 2593 | provider: CredentialProvider, |
| 2594 | trigger: RefreshTrigger = "proactive", |
| 2595 | ): Effect.Effect<string | null, StorageFailure | CredentialResolutionError> => |
| 2596 | // Share a single refresh per connection so concurrent resolves of the same |
| 2597 | // connection all await one refresh-token grant (the AS rotates the refresh |
| 2598 | // token; parallel grants would race on a consumed token — v1's refresh |
| 2599 | // deferred-map). The gate is cleared once the refresh settles so a later |
| 2600 | // expiry can refresh again. |
| 2601 | Effect.suspend(() => { |
| 2602 | const key = connectionKey(row); |
| 2603 | // Joining an in-flight grant is correct for BOTH triggers: whatever |
| 2604 | // that peer mints is newer than the token this fiber just saw rejected, |
| 2605 | // which is exactly what a reactive retry wants. The gate is cleared on |
| 2606 | // settle, so a 401 arriving after a refresh completed starts a fresh |
| 2607 | // grant rather than replaying a stale result. |
| 2608 | const existing = refreshInFlight.get(key); |
| 2609 | if (existing) return Deferred.await(existing); |
| 2610 | |
| 2611 | // The grant runs on a DETACHED fiber and every caller — including this |
| 2612 | // one — only awaits its deferred. The entry is shared across execution |
| 2613 | // stacks, so the fiber that registers it is merely the first arrival, |
| 2614 | // not an owner. Running the grant ON that fiber would hand it that |
| 2615 | // caller's interruption: a disconnected MCP client, an execution |
| 2616 | // deadline or a cancelled tool call would fail every peer awaiting the |
| 2617 | // same entry with an interrupt none of them caused and none can act on. |
| 2618 | // Awaiting is per-caller, so a cancelled peer detaches without touching |
| 2619 | // the grant or its siblings, and a grant nobody is left waiting on |
| 2620 | // still settles and still persists the rotated token — which is what |
| 2621 | // keeps the next caller off a consumed one. Token requests are bounded |
| 2622 | // by `AbortSignal.timeout`, so the detached fiber cannot outlive its |
| 2623 | // request. |
| 2624 | const deferred = Deferred.makeUnsafe< |
| 2625 | string | null, |
| 2626 | StorageFailure | CredentialResolutionError |
| 2627 | >(); |
| 2628 | // Nothing suspends between the lookup above and this registration, so |
| 2629 | // check-and-set is atomic against peer fibers and cannot double-fire. |
| 2630 | refreshInFlight.set(key, deferred); |
| 2631 | const run = performTokenRefresh(row, provider, trigger).pipe( |
| 2632 | Effect.exit, |
| 2633 | Effect.flatMap((exit) => Deferred.done(deferred, exit)), |
| 2634 | Effect.ensuring(Effect.sync(() => void refreshInFlight.delete(key))), |
| 2635 | ); |
| 2636 | return Effect.forkDetach(run).pipe(Effect.andThen(Deferred.await(deferred))); |
| 2637 | }); |
| 2638 | |
| 2639 | // Resolve every named input of a connection (`variable → value`). A |
| 2640 | // single-secret connection yields `{ token: <value> }`; an apiKey method with |
no test coverage detected