From 361328c788e13fa471a1f6ced5c44411a131d503 Mon Sep 17 00:00:00 2001 From: "Kai (Tam Nhu) Tran" <61256810+kaitranntt@users.noreply.github.com> Date: Tue, 16 Jun 2026 08:45:35 -0400 Subject: [PATCH] fix: enforce tier lock during quota preflight (#1550) Tier lock now fails closed in quota preflight when no healthy locked-tier account is available, instead of falling through cross-tier. --- src/cliproxy/quota/quota-manager.ts | 11 +++-- .../cliproxy/quota-manager-tier-lock.test.ts | 43 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/cliproxy/quota/quota-manager.ts b/src/cliproxy/quota/quota-manager.ts index 81f38150..43a376bd 100644 --- a/src/cliproxy/quota/quota-manager.ts +++ b/src/cliproxy/quota/quota-manager.ts @@ -658,8 +658,8 @@ export async function preflightCheck(provider: CLIProxyProvider): Promise { expect(result).toBeNull(); }); + // ------------------------------------------------------------------------- + // preflightCheck must enforce the same strict tier lock as findHealthyAccount + // ------------------------------------------------------------------------- + + it('preflightCheck blocks a cross-tier default when no healthy locked-tier account exists', async () => { + writeMinimalConfig(tempHome, { agy: 'pro' }); + _mockAccounts = [ULTRA_ACCOUNT, PRO_ACCOUNT]; + + const uid = `preflight-lock-pro-exhausted-${Date.now()}-${Math.random()}`; + const { preflightCheck, setCachedQuota } = await import( + `../../../src/cliproxy/quota/quota-manager?${uid}` + ); + + // Default is ultra, but agy is locked to pro. The only pro account is + // exhausted, so preflight must not fail open to the healthy ultra default. + setCachedQuota('agy', ULTRA_ACCOUNT.id, HEALTHY_QUOTA as never); + setCachedQuota('agy', PRO_ACCOUNT.id, EXHAUSTED_QUOTA as never); + + const result = await preflightCheck('agy'); + expect(result.proceed).toBe(false); + expect(result.accountId).not.toBe(ULTRA_ACCOUNT.id); + expect(result.reason).toBe('Tier lock: no healthy pro account available'); + }); + + it('preflightCheck switches a cross-tier default to a healthy locked-tier account', async () => { + writeMinimalConfig(tempHome, { agy: 'pro' }); + _mockAccounts = [ULTRA_ACCOUNT, PRO_ACCOUNT]; + + const uid = `preflight-lock-pro-healthy-${Date.now()}-${Math.random()}`; + const { preflightCheck, setCachedQuota } = await import( + `../../../src/cliproxy/quota/quota-manager?${uid}` + ); + + setCachedQuota('agy', ULTRA_ACCOUNT.id, HEALTHY_QUOTA as never); + setCachedQuota('agy', PRO_ACCOUNT.id, HEALTHY_QUOTA as never); + + const result = await preflightCheck('agy'); + expect(result.proceed).toBe(true); + expect(result.accountId).toBe(PRO_ACCOUNT.id); + expect(result.switchedFrom).toBe(ULTRA_ACCOUNT.id); + expect(result.reason).toBe('Tier lock: selected pro account'); + }); + // ------------------------------------------------------------------------- // Baseline: no tier_lock — any available healthy account is returned. //