refactor: extract early-return security gates from call_tool_guarded (cc 185) - #772
Merged
Merged
Conversation
call_tool_guarded (cognitive complexity 185) chained several independent early-return security gates inline. Extract the three self-contained ones — role+policy tool-access, egress DLP, and workflow allow-list — into guard_role_and_policy / guard_egress / guard_workflow helpers returning Option<CallToolResult>. The dispatcher calls them in the exact same order (each still short-circuits via return Ok on Some). guard_name/guard_args stay inline since they are reused by the later permission-inheritance gate. Behaviour is unchanged; the risky dispatch + post-processing section is untouched.
yvgude
approved these changes
Jul 9, 2026
yvgude
left a comment
Owner
There was a problem hiding this comment.
Reviewed the call_tool_guarded security gate extraction.
Verified:
- Three guards extracted with correct
Option<CallToolResult>return type:guard_role_and_policy(sync) — role + context-policy-packguard_egress(sync) — egress / output DLPguard_workflow(async, needs&self.workflow) — workflow allow-list
- Gate ordering preserved: role → ctx_call resolution → egress → workflow (same short-circuit semantics)
- Verbatim move —
return Ok(x)→return Some(x), trailingNone ctx_callinner-tool resolution correctly stays inline (shared with permission-inheritance gate)- Dispatch + post-processing intentionally untouched (deferred to follow-up)
- Clippy fixes in
rules_inject/content.rs,chatgpt_ws.rs,signing.rsare all minor and correct - LEAN-CTX.md refresh is cosmetic
Security-critical path — gate order and short-circuit behavior are the key invariants. Both are preserved.
Approved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #771.
call_tool_guarded(rust/src/server/call_tool.rs) has cognitive complexity 185 — the worst hotspot in the repo — and is ~1000 lines. It chains several independent early-return security gates inline before dispatch.This extracts the three self-contained gates into helpers returning
Option<CallToolResult>:guard_role_and_policy— role + context-policy-pack tool-access gatingguard_egress— egress / output DLP on agent writes & actionsguard_workflow— workflow allow-list gatingThe dispatcher now calls them in the exact same order, each still short-circuiting via
return Ok(blocked)onSome.guard_name/guard_argsare intentionally kept inline because they are reused by the later permission-inheritance gate.Scope: this is a conservative, security-preserving reduction of the prelude only. The risky dispatch + post-processing section (panic-catch, elicitation, finalize) is deliberately left untouched for a separate follow-up.
Test plan
cargo build --libcargo test --lib -- server::call_tool-> 7 passedcargo test --lib -- workflow role_guard policy_guard egress-> 31 passedcargo fmt --checkcargo clippy --lib --all-features -- -D warningsclean forcall_tool.rs(only remaining error is the unrelated pre-existingrules_overhead.rs:143lint onmain, fixed by fix: silence clippy::map_unwrap_or in rules_overhead (unblocks Clippy CI) #767)Notes for reviewers
return Ok(x)->return Some(x), trailingNone).