fix(requesty): apply the dedicated proxy and placeholder guards to Requesty

A saved Requesty proxy profile carries the requesty route id, but
buildLaunchEnv's noncanonical-launch list and buildStartupEnvFromProfile's
retained-proxy guard did not include Requesty. Ambient OPENAI_API_KEY,
OPENAI_API_KEYS and REQUESTY_API_KEY could reach the proxy on relaunch,
and a concrete shell selection skipped the guard entirely. LLMTR,
Merge, Command Code and API Route already withhold them.

REQUESTY_API_KEY was also missing from the placeholder-aware credential
checks in validation, route credential resolution and the picker, so a
template value such as SUA_CHAVE counted as usable and beat a real
OPENAI_API_KEY.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jatmn
2026-11-04 19:32:00 -08:00
co-authored by Claude Opus 5.5
parent 591f4a08af
commit 9b56ef2ebc
6 changed files with 75 additions and 0 deletions
+1
View File
@@ -45,6 +45,7 @@ function hasUsableEnvValue(envVar: string, value: string | undefined): boolean {
envVar === 'OPENAI_API_KEYS' ||
envVar === 'OPENAI_API_KEY' ||
envVar === 'LLMTR_API_KEY' ||
envVar === 'REQUESTY_API_KEY' ||
envVar === 'MERGE_GATEWAY_API_KEY' ||
envVar === 'CMD_API_KEY' ||
envVar === 'COMMANDCODE_API_KEY' ||
+1
View File
@@ -245,6 +245,7 @@ function hasUsableEnvCredentialValue(
envVar === 'APISMART_API_KEY' ||
envVar === 'CONCENTRATE_API_KEY' ||
envVar === 'LLMTR_API_KEY' ||
envVar === 'REQUESTY_API_KEY' ||
envVar === 'MERGE_GATEWAY_API_KEY' ||
envVar === 'CMD_API_KEY' ||
envVar === 'COMMANDCODE_API_KEY' ||
+37
View File
@@ -3990,3 +3990,40 @@ test('a shell URL retarget onto canonical Requesty drops a saved proxy profile c
assert.equal(explicit.REQUESTY_API_KEY, 'shell-requesty-key')
assert.equal(explicit.OPENAI_API_KEY, undefined)
})
test('a saved Requesty proxy profile withholds ambient credentials on restart', async () => {
// The startup file a Requesty proxy profile writes: route identity, its own
// URL and its own custom auth, but no saved key.
const persisted = profile('openai', {
CLAUDE_CODE_PROVIDER_ROUTE_ID: 'requesty',
OPENAI_BASE_URL: 'https://requesty-proxy.example/v1',
OPENAI_MODEL: 'openai/gpt-5-mini',
OPENAI_AUTH_HEADER: 'X-Proxy-Auth',
OPENAI_AUTH_SCHEME: 'raw',
OPENAI_AUTH_HEADER_VALUE: 'saved-proxy-secret',
})
const ambient = {
OPENAI_API_KEY: 'ambient-requesty-key',
OPENAI_API_KEYS: 'ambient-requesty-key',
REQUESTY_API_KEY: 'ambient-requesty-key',
}
for (const processEnv of [
ambient,
// A concrete shell selection must not skip the saved profile's boundary.
{
...ambient,
CLAUDE_CODE_USE_OPENAI: '1',
OPENAI_BASE_URL: 'https://requesty-proxy.example/v1',
OPENAI_MODEL: 'openai/gpt-5-mini',
},
]) {
const env = await buildStartupEnvFromProfile({ persisted, processEnv })
assert.equal(env.OPENAI_BASE_URL, 'https://requesty-proxy.example/v1')
assert.equal(env.CLAUDE_CODE_PROVIDER_ROUTE_ID, 'requesty')
assert.equal(env.OPENAI_API_KEY, undefined)
assert.equal(env.OPENAI_API_KEYS, undefined)
assert.equal(env.REQUESTY_API_KEY, undefined)
assert.equal(env.OPENAI_AUTH_HEADER_VALUE, 'saved-proxy-secret')
}
})
+12
View File
@@ -2373,6 +2373,10 @@ export async function buildLaunchEnv(options: {
effectiveOpenAIRouteId === 'llmtr' &&
!!env.OPENAI_BASE_URL?.trim() &&
!isCanonicalLlmtrInferenceBaseUrl(env.OPENAI_BASE_URL)
const isNoncanonicalRequestyLaunch =
effectiveOpenAIRouteId === 'requesty' &&
!!env.OPENAI_BASE_URL?.trim() &&
!isCanonicalRequestyInferenceBaseUrl(env.OPENAI_BASE_URL)
const isNoncanonicalMergeGatewayLaunch =
effectiveOpenAIRouteId === 'merge-gateway' &&
!!env.OPENAI_BASE_URL?.trim() &&
@@ -2390,6 +2394,7 @@ export async function buildLaunchEnv(options: {
isNoncanonicalApismartLaunch ||
isNoncanonicalConcentrateLaunch ||
isNoncanonicalLlmtrLaunch ||
isNoncanonicalRequestyLaunch ||
isNoncanonicalMergeGatewayLaunch ||
isNoncanonicalCommandcodeLaunch ||
isNoncanonicalApiRouteLaunch
@@ -2406,6 +2411,7 @@ export async function buildLaunchEnv(options: {
} else if (
!isNoncanonicalConcentrateLaunch &&
!isNoncanonicalLlmtrLaunch &&
!isNoncanonicalRequestyLaunch &&
!isNoncanonicalMergeGatewayLaunch &&
!isNoncanonicalCommandcodeLaunch
) {
@@ -2889,6 +2895,11 @@ export async function buildStartupEnvFromProfile(options?: {
persisted.env.CLAUDE_CODE_PROVIDER_ROUTE_ID === 'llmtr' &&
!!persisted.env.OPENAI_BASE_URL?.trim() &&
!isCanonicalLlmtrInferenceBaseUrl(persisted.env.OPENAI_BASE_URL)
const persistedRequestyProxy =
persisted?.profile === 'openai' &&
persisted.env.CLAUDE_CODE_PROVIDER_ROUTE_ID === 'requesty' &&
!!persisted.env.OPENAI_BASE_URL?.trim() &&
!isCanonicalRequestyInferenceBaseUrl(persisted.env.OPENAI_BASE_URL)
const persistedMergeGatewayProxy =
persisted?.profile === 'openai' &&
persisted.env.CLAUDE_CODE_PROVIDER_ROUTE_ID === 'merge-gateway' &&
@@ -2909,6 +2920,7 @@ export async function buildStartupEnvFromProfile(options?: {
!persistedApismartProxy &&
!persistedConcentrateProxy &&
!persistedLlmtrProxy &&
!persistedRequestyProxy &&
!persistedMergeGatewayProxy &&
!persistedCommandcodeProxy &&
!persistedApiRouteProxy
+23
View File
@@ -618,6 +618,29 @@ test('noncanonical Requesty host paths do not validate a dedicated credential',
await expect(getProviderValidationError(process.env)).resolves.toBeNull()
})
test.each([undefined, '', 'undefined', 'null', 'SUA_CHAVE', 'requesty-key'])('Requesty validation, picker and runtime agree on usable dedicated credentials: %s', async key => {
const { getProviderPresetUiMetadata } = await import('../integrations/providerUiMetadata.js')
const { resolveRouteCredentialValue } = await import('../integrations/routeMetadata.js')
const usable = key === 'requesty-key'
const env: NodeJS.ProcessEnv = {
CLAUDE_CODE_USE_OPENAI: '1', OPENAI_MODEL: 'openai/gpt-5-mini',
OPENAI_BASE_URL: 'https://router.requesty.ai/v1', REQUESTY_API_KEY: key,
}
const credential = () => resolveRouteCredentialValue({ routeId: 'requesty', baseUrl: env.OPENAI_BASE_URL, processEnv: env })
expect((await getProviderValidationError(env)) === null).toBe(usable)
expect(credential()).toBe(usable ? key : undefined)
expect(getProviderPresetUiMetadata('requesty', env).apiKey).toBe(usable ? key : '')
// An unusable dedicated key falls back to a usable generic credential.
env.OPENAI_API_KEY = 'openai-fallback-key'
await expect(getProviderValidationError(env)).resolves.toBeNull()
expect(credential()).toBe(usable ? key : 'openai-fallback-key')
delete env.OPENAI_API_KEY
env.OPENAI_API_KEYS = 'pool-key-a,pool-key-b'
await expect(getProviderValidationError(env)).resolves.toBeNull()
})
test('noncanonical Concentrate host paths fall back to generic OpenAI validation', async () => {
process.env.CLAUDE_CODE_USE_OPENAI = '1'
process.env.OPENAI_BASE_URL = 'https://api.concentrate.ai/staging/v1'
+1
View File
@@ -158,6 +158,7 @@ function hasUsableCredentialEnvValue(
envVar === 'API_ROUTE_API_KEY' ||
envVar === 'CONCENTRATE_API_KEY' ||
envVar === 'LLMTR_API_KEY' ||
envVar === 'REQUESTY_API_KEY' ||
envVar === 'MERGE_GATEWAY_API_KEY' ||
envVar === 'CMD_API_KEY' ||
envVar === 'COMMANDCODE_API_KEY' ||