refactor(gateway): split policy_engine::scope into per-responsibility modules - #27
Open
marcorivm wants to merge 1 commit into
Open
refactor(gateway): split policy_engine::scope into per-responsibility modules#27marcorivm wants to merge 1 commit into
marcorivm wants to merge 1 commit into
Conversation
… modules `scope.rs` had grown to 1,195 lines covering parsing, path safety, two provider extractors and 31 tests. Split it by responsibility, keeping `scope.rs` as the entry point (the `pub(crate)` surface, `ScopeVerdict`, and the closed provider dispatch) with the parts beside it: scope/session_policy.rs stored session_policy -> ResourceScope scope/path_safety.rs dot-segment rejection (shared by both extractors) scope/github.rs repository extractor + exact matcher scope/dropbox.rs folder extractor + nesting matcher scope/test_support.rs the one test fixture used by two test modules Pure move: every non-test and test code line is identical to the original modulo `use` statements and `pub(super)` visibility (verified by normalized diff). No trait, registry or generic abstraction was introduced — the provider dispatch stays a literal two-arm `match` so the closed allowlist remains visible in one place, and the repo (exact) and folder (prefix-nesting) matchers stay separate. Public API unchanged: `apply_resource_scope` and `needs_body` keep their signatures, so `policy_engine.rs`, `gateway/forward.rs` and `gateway/websocket.rs` are untouched. All 31 scope tests (585 crate-wide) pass; clippy -D warnings and fmt clean. Claude-Session: https://claude.ai/code/session_01VfmDPUTkYRs6NFpN89ezpM
marcorivm
force-pushed
the
refactor/scope-modules
branch
from
August 8, 2026 19:35
ccf3b91 to
95ba251
Compare
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Splits the 1,195-line
policy_engine/scope.rsmonolith introduced in #17. Pure reorganisation — no behaviour change.Layout
Follows the repo's existing
foo.rs+foo/convention.scope.rspub(crate)surface,ScopeVerdict,evaluate_scope. The only place that decides which provider handles a request.scope/session_policy.rsscope/path_safety.rsscope/github.rsscope/dropbox.rsscope/test_support.rs1,195 → 1,269 lines; the +74 is entirely module docs and
usestatements. Largest file is now 471.This is a move, not a rewrite — verified mechanically
I normalised both sides (strip blanks, comments,
use/modlines, visibility keywords), sorted, and diffed old against the concatenation of new:Zero logical lines were removed or altered. Not one expression, condition, or assertion changed. Tests moved between files; no assertion was touched.
The five invariants, re-checked
Indeterminatereturn site moved verbatim;apply_resource_scopestill maps bothOutOfScopeandIndeterminatetoBlocked.None(// empty list = all) — both arms intact, comment attached.percent_decode_str(...).decode_utf8_lossy(), with the "the forwarding layer collapses these afterwards" reasoning kept next to it.match (provider, scope)with_ => Indeterminate. Grepped fortrait/dyn/Box<: none.is_non_resource_rpc— same fourmatches!literals plusends_with("/continue"), verbatim.Restraint — what was deliberately NOT abstracted
This mattered as much as the split:
trait ResourceProvider, registry, or dispatch table. Two providers behind an explicitmatchis right at this size, and a trait would obscure invariant 4.repo_in_scopeis exact equality after lowercasing;folder_in_scopeis a segment-boundary prefix match with a root case. Superficially similar, semantically different — merging them would be a bug factory.ListShapestayed private rather than being promoted to a shared string-list utility; it has one caller.github_repo_refandis_non_resource_rpc— one expression, two provider modules, and hoisting it would create a cross-provider dependency worth less than the two lines saved.Only two things were genuinely deduplicated:
has_traversal/is_dot_segment(already shared, now with an obvious home) and one test fixture.Public API
Untouched.
apply_resource_scopeandneeds_bodykeeppub(crate)and their exact signatures.policy_engine.rs:42,forward.rsandwebsocket.rscompile unmodified — the diff against the base touches only the six scope files.Why it's stacked here rather than folded into #17
scope.rsis touched by exactly one commit in the whole stack (#17's own), and upstream v1.45.0 doesn't touch it — so this rebased onto the tip conflict-free, and #17–#26 stay exactly as reviewed. It also keeps "is this logic correct?" and "is this file organised well?" as two separate reads.Verification