Ревью: `rglob` по несуществующему каталогу не падает — отдаёт пусто, нарушителей
ноль, тест зелёный навсегда. Достаточно переложить файл в подкаталог tests/
(их восемь, и прецедент такого сторожа лежит именно в подкаталоге), чтобы
`parents[1]` уехал и сторож замолчал. Ровно тот класс, от которого детектор уже
защищён (test_detector_actually_detects), а область — нет. Одна строка:
`_OWNER.exists()` в теле теста; проверено мутацией области — краснеет.
Плюс слепые зоны названы и закреплены исполняемо: строковый доступ
`getattr(mod, "verify_password")` и прямой `bcrypt.checkpw` в обход модуля
сторож НЕ ловит. От намеренного обхода он не защищает и не может — только от
нечаянного. Было требованием ревью назвать это в коде, а не подразумевать.
Refs #2715
Пункт 3 хвоста #2715. Правило «из async def зови ТОЛЬКО verify_password_bounded»
жило в docstring app/core/password.py, а синхронная verify_password оставалась
публичной и импортируемой. Одной строчки asyncio.to_thread(verify_password, …)
в будущем коде хватит, чтобы получить вынос в поток вообще без учёта слотов:
внешне быстро, а потолок перебора (#2665) и доля на ключ (#2714) тихо исчезают.
Сторож по AST, а не по grep: verify_password поминается в комментариях и
docstring'ах (auth.py, config.py) — текстовый поиск краснел бы на них, а форму
без скобок (to_thread(verify_password, …)) — ровно ту, ради которой всё и
пишется — не поймал бы вовсе.
Сам детектор проверен на себе (test_detector_actually_detects): пустой детектор
прошёл бы все файлы и выглядел бы рабочим сторожем. Проверено мутацией: импорт
verify_password в app/api/v1/team.py красит тест.
Прецедент такого сторожа: backend/tests/sql/test_auth_sql_migrations.py.
Refs #2715