Fix #648: recognize root conftest.py and mv/git mv of test files - #689
Fix #648: recognize root conftest.py and mv/git mv of test files#689Som0111 wants to merge 9 commits into
Conversation
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LhtSnEnaAomWSH9obWMVAF
|
Thanks @Som0111, the |
|
Thanks @fu351 for catching that — you're right, the paths.py mv-source extraction was wired into _evaluate_one's full path-candidate list, so it was running through every blocking check instead of just the test-file check. I've reverted that entire branch: removed _shell_mv_source(), _shell_command_text(), and the mv-source extraction in ProtectedPathRule.evaluate(), and reverted _is_delete_or_rename() back to its original 2-arg signature. Kept the conftest.py glob addition and is_test_file() since commands.py depends on the latter. commands.py's mv/git mv detection is untouched — confirmed it already handles the test-file-move case correctly on its own. Added a regression test confirming mv /tmp/downloaded.txt ./notes.txt and mv ../scratch/a.py ./a.py are no longer blocked. All tests + ruff pass. Ready for another look whenever you get a chance. |
|
Merged via a landing branch, thanks @Som0111! Dropping the paths.py mv-source wiring was the right call, moving a file into the repo from outside canonicalizes outside the root and was false-positiving as a traversal block, and the commands.py mv/git-mv detection catches a test-file move on its own without it. The regression test you added pinning that mv /tmp/downloaded.txt ./notes.txt passes is what I wanted to see before this went in. Nothing in your code changed on the landing: main now needs branches up to date and refuses merge commits, so I cherry-picked your commits onto main under your name (landing PR #695, now 3d7e5b8) and merged that, which closed #648. If you want the next one, #647 (level-5) is the same idea for the other verb, rm and git rm of a test still pass with no check. |
Pull Request
Slice
What this PR does
conftest.pytoTEST_FILE_GLOBSinsrc/doberman/engine/rules/paths.pyso a repo-rootconftest.pyis recognized as a test file (previously onlytests/conftest.pymatched viatests/**).is_test_file()(public helper, mirrors the existing cross-module reuse pattern) socommands.pycan reuse the same glob table._shell_mv_source()/_shell_command_text()to recognize a plainmv SRC DST/git mv SRC DSTshell payload and extract its source operand._is_delete_or_rename()now also returnsTruewhen the evaluated path is exactly that shell-mv source (backward compatible, new param is optional).ProtectedPathRule.evaluate()extracts the mv source from raw arguments and adds it as an extra path candidate, so it flows through the existing blocked/sensitive/test-file checks._mv_rename_source()insrc/doberman/engine/rules/commands.py(same shape recognition, keyed on the real git verb via the existing_git_leading_globals)._segment_verdict()now AUTHs (ReasonCode.test_file_removal) when a segment'smv/git mvsource canonicalizes to a test-file path, reusingpaths.is_test_file()+doberman.canonical.canonicalize().docs/LIMITATIONS.mdto reflect the narrower (plain two-operand-shape-only) fix, replacing the two paragraphs that documented these gaps.Tests added (run in CI)
tests/unit/test_rule_paths.py::test_root_conftest_delete_requires_authtests/unit/test_rule_commands.py::test_mv_or_git_mv_of_test_file_requires_auth(parametrized:mvandgit mv)Changelog
changelog.d/648.fixed.mdfragment added: "Root-levelconftest.pyandmv/git mvof a test file now correctly raise AUTH instead of passing silently."Public-release safety (doberman-core only)
Security checklist
ReasonCode.test_file_removal)Edge cases covered / Deviations from plan / Risks introduced
mv SRC DST/git mv SRC DSTshapes are recognized; more complex shell constructs (globs,xargs, multi-filemv, quoting edge cases) are out of scope per the issue's "Out of scope" note and are not covered.docs/LIMITATIONS.md.