Skip to content

fix(config): unify ChannelsConfig resolution to env > settings > default#1124

Merged
ilblackdragon merged 1 commit intonearai:stagingfrom
reidliu41:feat/1119-config-source-channels
Mar 15, 2026
Merged

fix(config): unify ChannelsConfig resolution to env > settings > default#1124
ilblackdragon merged 1 commit intonearai:stagingfrom
reidliu41:feat/1119-config-source-channels

Conversation

@reidliu41
Copy link
Copy Markdown
Contributor

Summary

ChannelsConfig::resolve() ignored most ChannelSettings fields, reading
exclusively from env vars. This made config set ineffective for gateway,
HTTP, CLI, and WASM channel settings — a prerequisite blocker for #86
(hot-reload) and CLI management commands.

  • Add gateway and CLI fields to ChannelSettings with correct defaults
  • Rewrite resolve() to fall back to settings when env var is unset
  • Keep strict boolean validation via parse_bool_env for all bool fields
  • Fix GATEWAY_PORT default divergence (3001 -> 3000) in extension manager
  • Export DEFAULT_GATEWAY_PORT constant as single source of truth
  • Add 8 tests: settings fallback, env override, DB roundtrip, invalid bool rejection

Change Type

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI/Infrastructure
  • Security
  • Dependencies

Linked Issue

Part of #1119 (Phase 1: Channels pilot)

Validation

  • cargo fmt
  • cargo clippy --all --benches --tests --examples --all-features
  • Relevant tests pass:
  • Manual testing:

Security Impact

Database Impact

Blast Radius

Rollback Plan


Review track:

@github-actions github-actions bot added scope: config Configuration scope: extensions Extension management size: L 200-499 changed lines risk: medium Business logic, config, or moderate-risk modules contributor: experienced 6-19 merged PRs labels Mar 13, 2026
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the configuration resolution for various channels (HTTP, Gateway, CLI, WASM, Signal) to establish a clear precedence: environment variables, then ChannelSettings, and finally hardcoded defaults. This change addresses a critical issue where config set commands were ineffective for certain channel types, which was a blocker for implementing features like hot-reloading and CLI management commands. The update ensures consistent and predictable configuration behavior across the application.

Highlights

  • Configuration Resolution Logic: Rewrote the ChannelsConfig::resolve() function to prioritize environment variables, then fall back to ChannelSettings, and finally to default values for all channel fields.
  • New Channel Settings Fields: Added new fields for gateway and CLI configurations to ChannelSettings with appropriate default values.
  • Boolean Validation: Ensured strict boolean validation via parse_bool_env for all boolean configuration fields, preventing silent degradation from invalid values.
  • Gateway Port Unification: Fixed a divergence in the GATEWAY_PORT default (from 3001 to 3000) within the extension manager and exported DEFAULT_GATEWAY_PORT as a single source of truth.
  • Expanded Test Coverage: Added 8 new tests to cover settings fallback, environment variable overrides, database roundtrip functionality, and rejection of invalid boolean inputs.
Changelog
  • src/config/channels.rs
    • Modified the resolve function to implement the env > settings > default hierarchy for various channel configurations (HTTP, Gateway, Signal, WASM, CLI).
    • Introduced DEFAULT_GATEWAY_PORT constant.
    • Added several new unit tests to validate the new configuration resolution logic and boolean parsing.
  • src/config/mod.rs
    • Exported the new DEFAULT_GATEWAY_PORT constant.
  • src/extensions/manager.rs
    • Updated the default gateway port used in the extension manager to reference the new DEFAULT_GATEWAY_PORT constant, correcting a previous divergence.
  • src/settings.rs
    • Removed the #[derive(Default)] from ChannelSettings and implemented a custom Default trait.
    • Added new fields for gateway and CLI configuration to ChannelSettings.
    • Initialized the new gateway and CLI fields in the custom Default implementation for ChannelSettings.
Activity
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

  ChannelsConfig::resolve() ignored most ChannelSettings fields, reading
  exclusively from env vars. This made `config set` ineffective for gateway,
  HTTP, CLI, and WASM channel settings — a prerequisite blocker for nearai#86
  (hot-reload) and CLI management commands.

  - Add gateway and CLI fields to ChannelSettings with correct defaults
  - Rewrite resolve() to fall back to settings when env var is unset
  - Keep strict boolean validation via parse_bool_env for all bool fields
  - Fix GATEWAY_PORT default divergence (3001 -> 3000) in extension manager
  - Export DEFAULT_GATEWAY_PORT constant as single source of truth
  - Add 8 tests: settings fallback, env override, DB roundtrip, invalid bool rejection

  Part of nearai#1119 (Phase 1: Channels pilot)
[skip-regression-check]
@reidliu41 reidliu41 force-pushed the feat/1119-config-source-channels branch from 5ac8ffc to 3cd9487 Compare March 13, 2026 12:24
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively unifies the configuration resolution for channels to follow the env > settings > default priority, which is a great improvement for consistency and usability. The changes correctly implement this fallback logic for gateway, CLI, and WASM channel settings. The introduction of the DEFAULT_GATEWAY_PORT constant and fixing the port divergence are also valuable changes. The new tests are comprehensive and cover the new logic well.

I've added one suggestion to improve the test suite's maintainability and robustness by refactoring the duplicated environment variable cleanup logic into a shared helper function, ensuring proper SAFETY documentation for unsafe operations.

Comment thread src/config/channels.rs
Comment on lines +412 to +425
unsafe {
std::env::remove_var("GATEWAY_ENABLED");
std::env::remove_var("GATEWAY_HOST");
std::env::remove_var("GATEWAY_PORT");
std::env::remove_var("GATEWAY_AUTH_TOKEN");
std::env::remove_var("GATEWAY_USER_ID");
std::env::remove_var("HTTP_PORT");
std::env::remove_var("HTTP_HOST");
std::env::remove_var("SIGNAL_HTTP_URL");
std::env::remove_var("CLI_ENABLED");
std::env::remove_var("WASM_CHANNELS_DIR");
std::env::remove_var("WASM_CHANNELS_ENABLED");
std::env::remove_var("TELEGRAM_OWNER_ID");
}
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.

medium

This block for clearing environment variables is duplicated in several tests (resolve_gateway_from_settings, resolve_cli_enabled_from_settings, etc.). There's also an inconsistency: this block is missing HTTP_WEBHOOK_SECRET and HTTP_USER_ID, which are cleared in resolve_http_from_settings and could potentially affect other tests if not cleared.

To improve consistency and maintainability, consider extracting this logic into a single helper function that clears all relevant environment variables. This ensures a clean slate for each test.

Here's an example of what that could look like:

const TEST_ENV_VARS: &[&str] = &[
    "GATEWAY_ENABLED",
    "GATEWAY_HOST",
    "GATEWAY_PORT",
    "GATEWAY_AUTH_TOKEN",
    "GATEWAY_USER_ID",
    "HTTP_PORT",
    "HTTP_HOST",
    "HTTP_WEBHOOK_SECRET",
    "HTTP_USER_ID",
    "SIGNAL_HTTP_URL",
    "CLI_ENABLED",
    "WASM_CHANNELS_DIR",
    "WASM_CHANNELS_ENABLED",
    "TELEGRAM_OWNER_ID",
];

fn clear_all_test_vars() {
    // SAFETY: This function is called only within test contexts, which are guaranteed
    // to be single-threaded before any asynchronous runtime (like Tokio) is initialized.
    // Modifying environment variables is safe in a single-threaded context.
    unsafe {
        for var in TEST_ENV_VARS {
            std::env::remove_var(var);
        }
    }
}

Then, this block and others can be replaced with a single call to clear_all_test_vars();.

Suggested change
unsafe {
std::env::remove_var("GATEWAY_ENABLED");
std::env::remove_var("GATEWAY_HOST");
std::env::remove_var("GATEWAY_PORT");
std::env::remove_var("GATEWAY_AUTH_TOKEN");
std::env::remove_var("GATEWAY_USER_ID");
std::env::remove_var("HTTP_PORT");
std::env::remove_var("HTTP_HOST");
std::env::remove_var("SIGNAL_HTTP_URL");
std::env::remove_var("CLI_ENABLED");
std::env::remove_var("WASM_CHANNELS_DIR");
std::env::remove_var("WASM_CHANNELS_ENABLED");
std::env::remove_var("TELEGRAM_OWNER_ID");
}
unsafe {
std::env::remove_var("GATEWAY_ENABLED");
std::env::remove_var("GATEWAY_HOST");
std::env::remove_var("GATEWAY_PORT");
std::env::remove_var("GATEWAY_AUTH_TOKEN");
std::env::remove_var("GATEWAY_USER_ID");
std::env::remove_var("HTTP_PORT");
std::env::remove_var("HTTP_HOST");
std::env::remove_var("HTTP_WEBHOOK_SECRET");
std::env::remove_var("HTTP_USER_ID");
std::env::remove_var("SIGNAL_HTTP_URL");
std::env::remove_var("CLI_ENABLED");
std::env::remove_var("WASM_CHANNELS_DIR");
std::env::remove_var("WASM_CHANNELS_ENABLED");
std::env::remove_var("TELEGRAM_OWNER_ID");
}
References
  1. The use of unsafe std::env::set_var (and by extension remove_var) is permissible during application startup or in single-threaded contexts like tests, but this safety invariant must be documented in a SAFETY comment.

Copy link
Copy Markdown
Collaborator

@zmanian zmanian left a comment

Choose a reason for hiding this comment

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

Good fix with thorough tests. The env > settings > default pattern is well-implemented and consistent across all channel fields. The explicit Default impl for ChannelSettings correctly defaults gateway/cli/wasm to true. LGTM.

@G7CNF
Copy link
Copy Markdown
Contributor

G7CNF commented Mar 13, 2026

Tool-calling blocker triage: this looks merge-ready (approved + clean + green checks). Merging this should reduce config-source misrouting that can surface as false tool-calling failures.

@reidliu41
Copy link
Copy Markdown
Contributor Author

This PR is approved and CI is green — could you help merge it? Thanks!

@reidliu41 reidliu41 requested a review from zmanian March 15, 2026 01:40
@ilblackdragon ilblackdragon merged commit e74214d into nearai:staging Mar 15, 2026
13 checks passed
bkutasi pushed a commit to bkutasi/ironclaw that referenced this pull request Mar 28, 2026
…ult (nearai#1124)

ChannelsConfig::resolve() ignored most ChannelSettings fields, reading
  exclusively from env vars. This made `config set` ineffective for gateway,
  HTTP, CLI, and WASM channel settings — a prerequisite blocker for nearai#86
  (hot-reload) and CLI management commands.

  - Add gateway and CLI fields to ChannelSettings with correct defaults
  - Rewrite resolve() to fall back to settings when env var is unset
  - Keep strict boolean validation via parse_bool_env for all bool fields
  - Fix GATEWAY_PORT default divergence (3001 -> 3000) in extension manager
  - Export DEFAULT_GATEWAY_PORT constant as single source of truth
  - Add 8 tests: settings fallback, env override, DB roundtrip, invalid bool rejection

  Part of nearai#1119 (Phase 1: Channels pilot)
[skip-regression-check]
drchirag1991 pushed a commit to drchirag1991/ironclaw that referenced this pull request Apr 8, 2026
…ult (nearai#1124)

ChannelsConfig::resolve() ignored most ChannelSettings fields, reading
  exclusively from env vars. This made `config set` ineffective for gateway,
  HTTP, CLI, and WASM channel settings — a prerequisite blocker for nearai#86
  (hot-reload) and CLI management commands.

  - Add gateway and CLI fields to ChannelSettings with correct defaults
  - Rewrite resolve() to fall back to settings when env var is unset
  - Keep strict boolean validation via parse_bool_env for all bool fields
  - Fix GATEWAY_PORT default divergence (3001 -> 3000) in extension manager
  - Export DEFAULT_GATEWAY_PORT constant as single source of truth
  - Add 8 tests: settings fallback, env override, DB roundtrip, invalid bool rejection

  Part of nearai#1119 (Phase 1: Channels pilot)
[skip-regression-check]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: experienced 6-19 merged PRs risk: medium Business logic, config, or moderate-risk modules scope: config Configuration scope: extensions Extension management size: L 200-499 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants