Skip to content

feat(pipeline): reference parity for exclude_paths, client resolution, config wiring and the response pass - #81

Merged
rennf93 merged 4 commits into
masterfrom
feat/parity-exclusion-wiring
Oct 15, 2026
Merged

rennf93 merged 4 commits into
masterfrom
feat/parity-exclusion-wiring

Conversation

@rennf93

@rennf93 rennf93 commented Oct 15, 2026

Copy link
Copy Markdown
Member

Closes #80

This brings tower-guard-rs to parity with the Python reference. It needs the engine API from Guard-Core/guard-core-rs#143, so CI stays red until that merges. Merge order: guard-core-rs#143, then this PR, then axum-guard-rs (it composes this crate), with actix and rocket in any order.

  • exclude_paths uses the engine matcher and a scoped pipeline: an excluded request still runs the ban check, the global IP, country and cloud rules and the rate limit, then gets the scoped response pass (metrics, security headers, CORS, modifier; no return rules). GuardExclusionScoped is the request marker.
  • The client resolves through the configured trusted proxies, depth and X-Forwarded-For (with_client_policy), with the IPv4-mapped canonicalization and the 403 Client address could not be determined for a peer-less request under fail_secure. Builder layers keep fail_secure = false; from_security_config installs the config's policy.
  • from_security_config goes through the engine's shared Wiring, so every config field reaches a stage, store or hook. from_security_config_with takes the injected telemetry agent, agent_stats reports it, metrics and the event bus come from the config, and spawn_dynamic_rules starts the poll loop.
  • The response pass hands return rules the body when a rule needs it, runs the modifier without a processor (once when a processor carries it), and a route that bypasses all checks calls the downstream and applies only the modifier.
  • Two defects found along the way: the HTTPS stage compared the Host header against the trusted proxies instead of the connecting peer, and the IP gate decision was read before the gate ran so whitelisted IPs did not skip the geo, cloud and user-agent stages.
  • Docs: the README status-route and WebSocket contradictions, the stale notes and the CHANGELOG.

Breaking notes: GuardConfigError gains Cloud, Redis and Geo variants, agent_stats is no longer const, a layer built from a SecurityConfig rejects a request with no peer address, and country rules without a handler or token fail closed. Not applied (no runtime in this crate): route_resolution_strict, body_read_timeout, log_format, custom_log_file. The CORS preflight still answers before the pipeline, unlike the reference.

Gates run locally: check, fmt, clippy, the engine probe build, tests (173 unit, 49 integration, 38 parity), docs with -D warnings, and the 100% line coverage gate.

@github-actions github-actions Bot added documentation Docs, README, governance files tests Test suite changes dependencies Cargo.toml or Cargo.lock area: lib Touches src/ (tower::Layer / tower::Service adapter — currently a single-file lib stub) labels Oct 15, 2026
@rennf93
rennf93 merged commit 5c77eed into master Oct 15, 2026
11 of 15 checks passed
@rennf93
rennf93 deleted the feat/parity-exclusion-wiring branch October 15, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: lib Touches src/ (tower::Layer / tower::Service adapter — currently a single-file lib stub) dependencies Cargo.toml or Cargo.lock documentation Docs, README, governance files tests Test suite changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reference parity: scoped exclude_paths, client resolution, full config wiring and response pass

1 participant