Skip to content

Add whitelist mode for command filtering (#2231)#2282

Open
jdgajjar wants to merge 1 commit into
rtk-ai:developfrom
jdgajjar:fix/2231
Open

Add whitelist mode for command filtering (#2231)#2282
jdgajjar wants to merge 1 commit into
rtk-ai:developfrom
jdgajjar:fix/2231

Conversation

@jdgajjar
Copy link
Copy Markdown

@jdgajjar jdgajjar commented Jun 5, 2026

…g (#2231)

Add support for [hooks].include_commands in config.toml, providing a whitelist-mode counterpart to the existing exclude_commands blacklist.

Behaviour

  • When include_commands is non-empty, ONLY commands that match one of the listed patterns are rewritten by RTK; all others pass through unchanged.
  • When include_commands is empty (default), behaviour is identical to the previous release — no filtering change for existing users.
  • include_commands and exclude_commands are mutually exclusive. Config::load() returns an error if both contain at least one entry, preventing silent misconfiguration.

Implementation

src/core/config.rs

  • Add include_commands: Vec field to HooksConfig (serde default = []).
  • Add HooksConfig::validate() which errors when both fields are non-empty.
  • Call validate() inside Config::load() so every code path that loads config is protected.
  • Update test_hooks_config_default_empty to assert include_commands is also empty by default.
  • New tests: deserialize, only-include OK, only-exclude OK, neither OK, both-set error, both-empty OK.

src/discover/registry.rs

  • rewrite_command() gains a new included: &[String] parameter (position 3, before transparent_prefixes). Callers pass &[] to preserve old behaviour.
  • rewrite_compound() and rewrite_segment()/rewrite_segment_inner() gain the same parameter and thread it through all recursive calls.
  • Whitelist check inside rewrite_segment_inner(): after classify_command confirms a command is supported and it is not excluded, if included is non-empty the command MUST also match included — otherwise return None (pass through).
  • Reuses compile_exclude_patterns() for include patterns: same literal- prefix and anchored-regex matching logic, zero duplication.
  • All existing transparent_prefix test call-sites updated to 4-arg form.
  • New tests: listed command rewritten, unlisted passes through, empty include = no restriction, multiple entries, compound partial rewrite, prefix-pattern with args, unsupported command not rewritten.

src/hooks/hook_cmd.rs

  • get_rewritten() and run_gemini() now destructure (excluded, included, transparent_prefixes) from config and pass included to rewrite_command().
  • Test helper rewrite_command_no_prefixes updated to 4-arg form.

src/hooks/rewrite_cmd.rs

  • run() now loads included from config and passes to registry::rewrite_command().
  • Test helper and exit_code_protocol test updated to 4-arg form.

src/main.rs

  • HookCommands::Check handler updated to load and pass include_commands.

Backward compatibility

  • All three of excluded, included, transparent_prefixes are Vec default [].
  • Old configs with only exclude_commands or neither field continue to work unchanged; validate() only errors when both are non-empty.
  • Public rewrite_command signature change is additive; no external callers exist outside this crate.

Summary

Test plan

  • cargo fmt --all && cargo clippy --all-targets && cargo test
  • Manual testing: rtk <command> output inspected

Important: All PRs must target the develop branch (not master).
See CONTRIBUTING.md for details.

rtk-ai#2231)

Add support for [hooks].include_commands in config.toml, providing a
whitelist-mode counterpart to the existing exclude_commands blacklist.

## Behaviour

- When include_commands is non-empty, ONLY commands that match one of the
  listed patterns are rewritten by RTK; all others pass through unchanged.
- When include_commands is empty (default), behaviour is identical to
  the previous release — no filtering change for existing users.
- include_commands and exclude_commands are mutually exclusive.
  Config::load() returns an error if both contain at least one entry,
  preventing silent misconfiguration.

## Implementation

### src/core/config.rs
- Add include_commands: Vec<String> field to HooksConfig (serde default = []).
- Add HooksConfig::validate() which errors when both fields are non-empty.
- Call validate() inside Config::load() so every code path that loads
  config is protected.
- Update test_hooks_config_default_empty to assert include_commands is
  also empty by default.
- New tests: deserialize, only-include OK, only-exclude OK, neither OK,
  both-set error, both-empty OK.

### src/discover/registry.rs
- rewrite_command() gains a new included: &[String] parameter (position 3,
  before transparent_prefixes). Callers pass &[] to preserve old behaviour.
- rewrite_compound() and rewrite_segment()/rewrite_segment_inner() gain the
  same parameter and thread it through all recursive calls.
- Whitelist check inside rewrite_segment_inner(): after classify_command
  confirms a command is supported and it is not excluded, if included is
  non-empty the command MUST also match included — otherwise return None
  (pass through).
- Reuses compile_exclude_patterns() for include patterns: same literal-
  prefix and anchored-regex matching logic, zero duplication.
- All existing transparent_prefix test call-sites updated to 4-arg form.
- New tests: listed command rewritten, unlisted passes through, empty
  include = no restriction, multiple entries, compound partial rewrite,
  prefix-pattern with args, unsupported command not rewritten.

### src/hooks/hook_cmd.rs
- get_rewritten() and run_gemini() now destructure (excluded, included,
  transparent_prefixes) from config and pass included to rewrite_command().
- Test helper rewrite_command_no_prefixes updated to 4-arg form.

### src/hooks/rewrite_cmd.rs
- run() now loads included from config and passes to registry::rewrite_command().
- Test helper and exit_code_protocol test updated to 4-arg form.

### src/main.rs
- HookCommands::Check handler updated to load and pass include_commands.

## Backward compatibility
- All three of excluded, included, transparent_prefixes are Vec default [].
- Old configs with only exclude_commands or neither field continue to work
  unchanged; validate() only errors when both are non-empty.
- Public rewrite_command signature change is additive; no external callers
  exist outside this crate.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Jun 5, 2026

CLA assistant check
All committers have signed the CLA.

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.

2 participants