Skip to content

fix(gateway): expand config env templates before auth bridging and model resolution - #35444

Open
Dusk1e wants to merge 1 commit into
NousResearch:mainfrom
Dusk1e:fix/gateway-config-env-variable-template-expansion
Open

fix(gateway): expand config env templates before auth bridging and model resolution#35444
Dusk1e wants to merge 1 commit into
NousResearch:mainfrom
Dusk1e:fix/gateway-config-env-variable-template-expansion

Conversation

@Dusk1e

@Dusk1e Dusk1e commented May 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix gateway-side ${VAR} config expansion drift so gateway runtime and auth/env bridging behave the same way as the main config loader.

Before this change, some gateway paths read raw config.yaml values without expanding ${ENV_VAR} templates first. That caused real mismatches such as:

  • model: ${GW_MODEL} working in some config paths but not in gateway model resolution
  • telegram.allow_from: ${TG_ALLOWED_USER} being bridged into TELEGRAM_ALLOWED_USERS as the literal string ${TG_ALLOWED_USER} instead of the resolved user ID

This PR makes gateway config handling consistent with the documented config expansion behavior.

Fix

  • Expand ${VAR} templates in gateway.config.load_gateway_config() immediately after loading config.yaml, before YAML values are mapped into gateway config fields or bridged into env vars.
  • Update gateway.run._resolve_gateway_model() to read from expanded gateway runtime config when loading from disk.
  • Also expand templates when _resolve_gateway_model() is given a config dict directly, so raw config callers do not bypass expansion.

Testing

Added regression coverage for both broken paths:

  • tests/gateway/test_runtime_config_env_expansion.py
    • verifies _resolve_gateway_model() expands ${GW_MODEL} from config.yaml
    • verifies direct config-dict input also expands
  • tests/gateway/test_config.py
    • verifies telegram.allow_from: ${TG_ALLOWED_USER} is expanded before bridging into TELEGRAM_ALLOWED_USERS

Test Results

Passed:

  • tests/gateway/test_runtime_config_env_expansion.py
  • tests/gateway/test_config.py
  • tests/test_empty_model_fallback.py
  • tests/gateway/test_api_server_toolset.py
  • tests/gateway/test_api_server.py
  • tests/gateway/test_telegram_group_gating.py

Observed results:

  • 73/73 tests passed in the targeted regression set
  • 207/207 tests passed in the broader gateway/api_server/Telegram gating set

@Dusk1e Dusk1e changed the title fix(gateway): expand environment variable templates during runtime co… fix(gateway): expand config env templates before auth bridging and model resolution May 30, 2026
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery area/config Config system, migrations, profiles labels May 30, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Same class of bug as #21275 and merged #30842 — gateway paths reading raw YAML without _expand_env_vars(). This PR targets load_gateway_config() (auth bridging) and _resolve_gateway_model(), which were not covered by the #30842 fix. Also related to open #21029, #20980, #25005 (fallback env expansion).

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Summary

Verdict: Approved

Overall

Solid fix for a subtle but impactful config expansion bug. The gateway was reading raw ${VAR} templates in some code paths while other paths had expansion applied — causing runtime mismatches that are hard to debug.

What's Good

  • Root cause identification: The gap between config.yaml → expanded values in some paths vs. raw templates in others is well-documented
  • Comprehensive fix: Covers both the load_gateway_config() path and the _resolve_gateway_model() direct-dict path
  • Regression tests: Both test cases directly verify the broken scenarios
  • Clean blast radius: LOW — only adds env var expansion where it was missing
  • Good test isolation: Uses tmp_path/monkeypatch fixtures, no global state contamination

Suggestion (Non-blocking)

Consider adding a docstring to _expand_env_vars in hermes_cli/config.py (if not already present) noting it's also called from gateway/config.py, so future refactors don't accidentally break the gateway path.


Reviewed by Hermes Agent

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused regression coverage. The premise remains valid on current main: gateway/config.py:1009 loads raw YAML and gateway/config.py:1217 bridges raw allow_from; gateway/run.py:2404 likewise passes raw _load_gateway_config() output to _resolve_gateway_model(). The existing related commit 2362cc4688364ca8d03924ab1f64e9bb2f5f0cb3 introduced _load_gateway_runtime_config() at gateway/run.py:2377-2394 for other runtime readers, but did not cover either of these paths.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026

@GottZ GottZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This was generated by AI during triage.

Summary

Two PRs address or reference this gateway configuration complex. #35444 directly fixes the reported raw-YAML environment-template gap in model resolution and Telegram auth bridging, while #46181 uses expanded runtime configuration as part of a much broader prompt-refresh change that does not fix those two missing paths.

Related pull requests

  • #35444 related — (+37/-1) — merge: The focused diff expands config.yaml before GatewayConfig mapping/auth bridging and routes model resolution through expanded runtime config, with direct regression tests for ${GW_MODEL} and ${TG_ALLOWED_USER}; the contributor keep_open review confirms both raw-YAML paths remain unfixed on current main.
  • #46181 [closed] related — (+210/-11) — keep closed, not a duplicate: This remains relevant as a contrasting broader prompt-policy implementation built around runtime config loading, but it neither adds #35444's load_gateway_config expansion nor its auth-bridging fix. Despite the keep_open review on #46181, its own blocking contributor analysis identifies per-turn prompt replacement/cache rebuilding as violating the byte-stable per-conversation prompt invariant, activates a CLI-only display.personality setting in the gateway, and notes incomplete case-insensitive lookup; the later closure therefore matches the documented design constraints.

Suggested consolidation

Merge #35444 as the focused fix for the two verified raw-config paths. Keep #46181 closed because its broader live prompt-refresh design conflicts with documented gateway invariants and does not substitute for #35444; no PR should be closed as a duplicate in this complex.

Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 20 kB of PR diffs, 4 kB of issue/PR text, 5 kB of discussion (6 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants