Skip to content

Fix enforced connection fields overridden by user env vars#19

Merged
wch merged 1 commit into
mainfrom
enforced-env-override
Jul 21, 2026
Merged

Fix enforced connection fields overridden by user env vars#19
wch merged 1 commit into
mainfrom
enforced-env-override

Conversation

@wch

@wch wch commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Connection env vars (ANTHROPIC_BASE_URL, AWS_REGION, POSITAI_AUTH_HOST, etc.) were applied as a post-merge overlay that landed above the POSIT_AI_PROVIDERS_ENFORCED layer. This meant a user's shell variable could silently override an admin-pinned connection value, defeating the enforced control.

The fix converts env vars from a post-resolution overlay into a resolver-owned config source ranked below enforced but above user/host/default. All precedence now flows through the single deepMerge in resolveProviderCatalog — enforced is merged last and always wins. The bespoke applyEnvOverlay function in build-catalog.ts is removed.

Fixes #10

Changes

  • src/connection-env.ts (new) — owns CONNECTION_ENV_MAPPINGS and readEnvConnectionConfig(), extracted from build-catalog.ts.
  • src/resolve-catalog.ts — private ConnectionEnvSource / RankedConfigSource types; RANK map with env at rank 1; env source synthesized from envVars, excluded from enablement layers.
  • src/build-catalog.ts — removed applyEnvOverlay, readEnvSection, CONNECTION_ENV_MAPPINGS, and the options.envVars parameter from buildCatalog().
  • Tests — three regression tests (enforced beats env scalar, env beats user/default, sub-key granularity); updated build-catalog-custom.test.ts to the new three-argument signature.
  • Docs — README, aiConfig.md, and JSDoc updated to describe precedence as enforced > connection env > user > host > default.

Verification

// Before the fix, the env var wins — enforced is silently overridden:
resolveProviderCatalog({
  sources: [
    { kind: "enforced", config: { providers: { anthropic: { baseUrl: "https://enforced.example.com" } } } },
    { kind: "user", config: { providers: {} } },
  ],
  baseline: { defaultEnabled: true },
  envVars: { ANTHROPIC_BASE_URL: "https://env.example.com" },
});
// Before: anthropic.connection.baseUrl === "https://env.example.com"  ← bug
// After:  anthropic.connection.baseUrl === "https://enforced.example.com"  ← correct

Connection env vars (ANTHROPIC_BASE_URL, AWS_REGION, etc.) were applied as
a post-merge overlay above the enforced layer, so a user's shell variable
could override an admin-pinned value from POSIT_AI_PROVIDERS_ENFORCED.

Convert the env vars into a resolver-owned config source ranked below
enforced (rank 1) but above user/host/default (ranks 2-4). The single
deepMerge now handles all precedence — enforced is merged last and always
wins. The bespoke applyEnvOverlay in build-catalog.ts is removed.

New module connection-env.ts owns CONNECTION_ENV_MAPPINGS and the reader;
build-catalog.ts is left responsible only for turning merged config into
catalog entries.

Fixes #10
@wch
wch requested a review from melissa-barca July 20, 2026 21:50

@melissa-barca melissa-barca left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@wch
wch merged commit ddc4c9e into main Jul 21, 2026
1 check passed
@wch
wch deleted the enforced-env-override branch July 21, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enforced connection fields can be overridden by a user's environment variables

2 participants