import { describe, expect, test } from "bun:test"; import { CredentialRefreshCoordinator, CredentialRefreshError, runWithCredentialRefresh, } from "../../src/auth/credentialRefresh.js"; import { type RuntimeSessionContext } from "../../src/runtime/sessionContext.js"; const context = (overrides: Partial = {}) => ({ accessToken: "old-token", actorKey: "user-1", clientSessionId: "client-1", projectId: "project-1", projectKey: "project-1", sessionId: "session-1", traceId: "trace-1", ...overrides, }); describe("CredentialRefreshCoordinator", () => { test("deduplicates concurrent refreshes for one session", async () => { const coordinator = new CredentialRefreshCoordinator(); const requestIds: string[] = []; coordinator.subscribe("session-1", (event) => { if (event.type === "credential_refresh_required") { requestIds.push(event.requestId); } }); const expired = context({ tokenExpiresAt: new Date(0).toISOString() }); const execute = async (active: RuntimeSessionContext) => ({ status: 200, token: active.accessToken, }); const first = runWithCredentialRefresh(coordinator, expired, execute); const second = runWithCredentialRefresh(coordinator, expired, execute); await Promise.resolve(); expect(requestIds).toHaveLength(1); expect(coordinator.getPendingEvent("session-1")).toMatchObject({ type: "credential_refresh_required", requestId: requestIds[0], reason: "access_token_expired", }); coordinator.resolve( "session-1", requestIds[0]!, context({ accessToken: "fresh-token" }), ); expect(await first).toEqual({ status: 200, token: "fresh-token" }); expect(await second).toEqual({ status: 200, token: "fresh-token" }); expect(coordinator.getPendingEvent("session-1")).toBeNull(); }); test("retries one time on 401 and never refreshes a 403", async () => { const coordinator = new CredentialRefreshCoordinator(); let requestId = ""; coordinator.subscribe("session-1", (event) => { if (event.type === "credential_refresh_required") { requestId = event.requestId; } }); let attempts = 0; const resultPromise = runWithCredentialRefresh( coordinator, context(), async () => ({ status: ++attempts === 1 ? 401 : 401 }), ); await Promise.resolve(); coordinator.resolve("session-1", requestId, context({ accessToken: "fresh-token" })); expect((await resultPromise).status).toBe(401); expect(attempts).toBe(2); requestId = ""; expect( (await runWithCredentialRefresh(coordinator, context(), async () => ({ status: 403 }))) .status, ).toBe(403); expect(requestId).toBe(""); }); test("fails explicitly when no event stream can refresh credentials", async () => { await expect( runWithCredentialRefresh( new CredentialRefreshCoordinator(), context({ tokenExpiresAt: new Date(0).toISOString() }), async () => ({ status: 200 }), ), ).rejects.toBeInstanceOf(CredentialRefreshError); }); test("reports run cancellation separately from authentication failure", async () => { const coordinator = new CredentialRefreshCoordinator(); coordinator.subscribe("session-1", () => undefined); const pending = coordinator.request("session-1", "access_token_rejected"); coordinator.cancelSession("session-1"); await expect(pending).rejects.toMatchObject({ code: "cancelled" }); }); });