Duplicate Code Opportunity
Summary
Pattern : API proxy/OIDC environment variables are enumerated once when building WrapperConfig from CLI/env input, then repeated when projecting that config into the api-proxy sidecar environment.
Locations : src/commands/build-config.ts lines 176-220 and src/services/api-proxy-env-config.ts lines 193-251.
Impact : Roughly 40 repeated env/config mappings remain on a security-sensitive credential/OIDC path. This appears to reproduce the completed prior finding [Duplicate Code] API proxy environment variable matrix is duplicated between wrapper config and provider adapters #5198 and should be tracked again.
Evidence
src/commands/build-config.ts maps API proxy and OIDC env vars into config fields:
176 openaiApiKey : process . env [ OPENAI_ENV . KEY ] ,
177 anthropicApiKey : process . env [ ANTHROPIC_ENV . KEY ] ,
178 copilotGithubToken : process . env [ COPILOT_ENV . GITHUB_TOKEN ] ,
179 copilotProviderApiKey : process . env [ COPILOT_ENV . PROVIDER_API_KEY ] ,
180 copilotProviderType :
181 ( options . copilotProviderType as string | undefined ) || process . env [ COPILOT_ENV . PROVIDER_TYPE ] ,
...
204 authType : ( options . authType as string | undefined ) || process . env . AWF_AUTH_TYPE ,
205 authProvider : ( options . authProvider as string | undefined ) || process . env . AWF_AUTH_PROVIDER ,
206 authOidcAudience : ( options . authOidcAudience as string | undefined ) || process . env . AWF_AUTH_OIDC_AUDIENCE ,
207 authAzureTenantId : ( options . authAzureTenantId as string | undefined ) || process . env . AWF_AUTH_AZURE_TENANT_ID ,
208 authAzureClientId : ( options . authAzureClientId as string | undefined ) || process . env . AWF_AUTH_AZURE_CLIENT_ID ,
209 authAzureScope : ( options . authAzureScope as string | undefined ) || process . env . AWF_AUTH_AZURE_SCOPE ,
210 authAzureCloud : ( options . authAzureCloud as string | undefined ) || process . env . AWF_AUTH_AZURE_CLOUD ,
211 authAwsRoleArn : ( options . authAwsRoleArn as string | undefined ) || process . env . AWF_AUTH_AWS_ROLE_ARN ,
212 authAwsRegion : ( options . authAwsRegion as string | undefined ) || process . env . AWF_AUTH_AWS_REGION ,
213 authAwsRoleSessionName : ( options . authAwsRoleSessionName as string | undefined ) || process . env . AWF_AUTH_AWS_ROLE_SESSION_NAME ,
214 authGcpWorkloadIdentityProvider : ( options . authGcpWorkloadIdentityProvider as string | undefined ) || process . env . AWF_AUTH_GCP_WORKLOAD_IDENTITY_PROVIDER ,
215 authGcpServiceAccount : ( options . authGcpServiceAccount as string | undefined ) || process . env . AWF_AUTH_GCP_SERVICE_ACCOUNT ,
216 authGcpScope : ( options . authGcpScope as string | undefined ) || process . env . AWF_AUTH_GCP_SCOPE ,
217 authAnthropicFederationRuleId : ( options . authAnthropicFederationRuleId as string | undefined ) || process . env . AWF_AUTH_ANTHROPIC_FEDERATION_RULE_ID ,
218 authAnthropicOrganizationId : ( options . authAnthropicOrganizationId as string | undefined ) || process . env . AWF_AUTH_ANTHROPIC_ORGANIZATION_ID ,
219 authAnthropicServiceAccountId : ( options . authAnthropicServiceAccountId as string | undefined ) || process . env . AWF_AUTH_ANTHROPIC_SERVICE_ACCOUNT_ID ,
220 authAnthropicWorkspaceId : ( options . authAnthropicWorkspaceId as string | undefined ) || process . env . AWF_AUTH_ANTHROPIC_WORKSPACE_ID ,
src/services/api-proxy-env-config.ts repeats the same OIDC/env matrix when forwarding to the sidecar:
193 // OIDC authentication (Azure, AWS, GCP, Anthropic)
194 . . . pickEnvVars (
195 'AWF_AUTH_TYPE' ,
196 'AWF_AUTH_PROVIDER' ,
197 'AWF_AUTH_OIDC_AUDIENCE' ,
198 // Azure
199 'AWF_AUTH_AZURE_TENANT_ID' ,
200 'AWF_AUTH_AZURE_CLIENT_ID' ,
201 'AWF_AUTH_AZURE_SCOPE' ,
202 'AWF_AUTH_AZURE_CLOUD' ,
203 // AWS
204 'AWF_AUTH_AWS_ROLE_ARN' ,
205 'AWF_AUTH_AWS_REGION' ,
206 'AWF_AUTH_AWS_ROLE_SESSION_NAME' ,
207 // GCP
208 'AWF_AUTH_GCP_WORKLOAD_IDENTITY_PROVIDER' ,
209 'AWF_AUTH_GCP_SERVICE_ACCOUNT' ,
210 'AWF_AUTH_GCP_SCOPE' ,
211 // Anthropic
212 'AWF_AUTH_ANTHROPIC_FEDERATION_RULE_ID' ,
213 'AWF_AUTH_ANTHROPIC_ORGANIZATION_ID' ,
214 'AWF_AUTH_ANTHROPIC_SERVICE_ACCOUNT_ID' ,
215 'AWF_AUTH_ANTHROPIC_WORKSPACE_ID' ,
216 'AWF_AUTH_ANTHROPIC_TOKEN_URL' ,
...
235 . . . ( config . authType && { AWF_AUTH_TYPE : config . authType } ) ,
236 . . . ( config . authProvider && { AWF_AUTH_PROVIDER : config . authProvider } ) ,
237 . . . ( config . authOidcAudience && { AWF_AUTH_OIDC_AUDIENCE : config . authOidcAudience } ) ,
238 . . . ( config . authAzureTenantId && { AWF_AUTH_AZURE_TENANT_ID : config . authAzureTenantId } ) ,
239 . . . ( config . authAzureClientId && { AWF_AUTH_AZURE_CLIENT_ID : config . authAzureClientId } ) ,
240 . . . ( config . authAzureScope && { AWF_AUTH_AZURE_SCOPE : config . authAzureScope } ) ,
241 . . . ( config . authAzureCloud && { AWF_AUTH_AZURE_CLOUD : config . authAzureCloud } ) ,
242 . . . ( config . authAwsRoleArn && { AWF_AUTH_AWS_ROLE_ARN : config . authAwsRoleArn } ) ,
243 . . . ( config . authAwsRegion && { AWF_AUTH_AWS_REGION : config . authAwsRegion } ) ,
244 . . . ( config . authAwsRoleSessionName && { AWF_AUTH_AWS_ROLE_SESSION_NAME : config . authAwsRoleSessionName } ) ,
245 . . . ( config . authGcpWorkloadIdentityProvider && { AWF_AUTH_GCP_WORKLOAD_IDENTITY_PROVIDER : config . authGcpWorkloadIdentityProvider } ) ,
246 . . . ( config . authGcpServiceAccount && { AWF_AUTH_GCP_SERVICE_ACCOUNT : config . authGcpServiceAccount } ) ,
247 . . . ( config . authGcpScope && { AWF_AUTH_GCP_SCOPE : config . authGcpScope } ) ,
248 . . . ( config . authAnthropicFederationRuleId && { AWF_AUTH_ANTHROPIC_FEDERATION_RULE_ID : config . authAnthropicFederationRuleId } ) ,
249 . . . ( config . authAnthropicOrganizationId && { AWF_AUTH_ANTHROPIC_ORGANIZATION_ID : config . authAnthropicOrganizationId } ) ,
250 . . . ( config . authAnthropicServiceAccountId && { AWF_AUTH_ANTHROPIC_SERVICE_ACCOUNT_ID : config . authAnthropicServiceAccountId } ) ,
251 . . . ( config . authAnthropicWorkspaceId && { AWF_AUTH_ANTHROPIC_WORKSPACE_ID : config . authAnthropicWorkspaceId } ) ,
Suggested Refactoring
Create a typed descriptor table for API proxy env/config fields, for example API_PROXY_ENV_FIELDS, with configKey, envVar, sensitivity, and precedence metadata. Use it in both build-config.ts and api-proxy-env-config.ts so adding or renaming an OIDC credential requires one update. Keep explicit denylist exceptions such as AWF_ANTHROPIC_TRANSFORM_FILE close to the descriptor to preserve the current security guardrail.
Affected Files
src/commands/build-config.ts — lines 176-220
src/services/api-proxy-env-config.ts — lines 193-251
Effort Estimate
Medium
Detected by Duplicate Code Detector workflow. Run date: 2026-06-27
Generated by Duplicate Code Detector · 161 AIC · ⊞ 23.1K · ◷
Duplicate Code Opportunity
Summary
WrapperConfigfrom CLI/env input, then repeated when projecting that config into the api-proxy sidecar environment.src/commands/build-config.tslines 176-220 andsrc/services/api-proxy-env-config.tslines 193-251.Evidence
src/commands/build-config.tsmaps API proxy and OIDC env vars into config fields:src/services/api-proxy-env-config.tsrepeats the same OIDC/env matrix when forwarding to the sidecar:Suggested Refactoring
Create a typed descriptor table for API proxy env/config fields, for example
API_PROXY_ENV_FIELDS, withconfigKey,envVar, sensitivity, and precedence metadata. Use it in bothbuild-config.tsandapi-proxy-env-config.tsso adding or renaming an OIDC credential requires one update. Keep explicit denylist exceptions such asAWF_ANTHROPIC_TRANSFORM_FILEclose to the descriptor to preserve the current security guardrail.Affected Files
src/commands/build-config.ts— lines 176-220src/services/api-proxy-env-config.ts— lines 193-251Effort Estimate
Medium
Detected by Duplicate Code Detector workflow. Run date: 2026-06-27