test(tradein/auth): правило про синхронную сверку — сторожем, а не комментарием (#2715) #2735

Merged
bot-backend merged 2 commits from test/2715-verify-password-call-site-guard into main 2026-08-06 14:35:33 +00:00
Showing only changes of commit 3a7dbd4dda - Show all commits

View file

@ -20,6 +20,13 @@
которую `grep 'verify_password('` не поймал бы вовсе то есть ровно ту, ради
которой сторож и написан.
ЧЕГО СТОРОЖ НЕ ВИДИТ, и это записано тут, а не подразумевается: строкового
доступа (`getattr(mod, "verify_password")`) и обхода модуля целиком (прямой
`bcrypt.checkpw`). От НАМЕРЕННОГО обхода он не защищает и не может только от
нечаянного, а нечаянный и есть частый случай. Обе непойманные формы закреплены
исполняемо (`test_detector_blind_spots_are_known`), чтобы «не ловим» было
проверенным фактом, а не обещанием в тексте.
Без БД и без сети только чтение файлов.
"""
@ -68,8 +75,28 @@ def test_detector_actually_detects() -> None:
assert not _references_verify_password("# verify_password тут только в комментарии")
def test_detector_blind_spots_are_known() -> None:
"""Слепые зоны — зафиксированы, а не забыты.
Обе формы обходят сторож НАМЕРЕННЫМ усилием: строковый доступ к атрибуту и
обход модуля целиком. Ловить их AST'ом можно было бы только ценой ложняков
(любой `getattr` с любой строкой, любой вызов bcrypt), а цена ложняка
требование выключить сторож. Тест держит это знание исполняемым: захочет
однажды детектор их ловить покраснеет здесь и заставит осознанно
переписать и этот тест, и текст модуля.
"""
assert not _references_verify_password('fn = getattr(password_mod, "verify_password")')
assert not _references_verify_password("bcrypt.checkpw(plain.encode(), hashed.encode())")
def test_sync_verify_password_is_called_from_one_place_only() -> None:
"""В `app/` синхронную сверку не поминает никто, кроме её собственного модуля."""
# Область сканирования жива. `rglob` по несуществующему каталогу не падает —
# отдаёт пусто, нарушителей ноль, сторож зелен НАВСЕГДА. Достаточно
# переложить этот файл в подкаталог tests/ (их уже восемь, и прецедент
# такого сторожа лежит именно в подкаталоге), чтобы `parents[1]` уехал.
assert _OWNER.exists(), f"область сканирования съехала: {_APP_DIR}"
offenders = [
str(path.relative_to(_BACKEND_ROOT))
for path in sorted(_APP_DIR.rglob("*.py"))