Каталог DOM.РФ в beat: вместо обещания «вернуть после cooldown» — факт о блокировке StormWall и тест, который не даст включить молча #3566
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3566
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/ptica-domrf-waf-probe"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
#2443 — каталог DOM.РФ выключен из-за блокировки, а не «до cooldown»
Что было
У двух закомментированных beat-записей,
scrape-kn-catalog-objects-weeklyиscrape-kn-catalog-flats-weekly, стоял комментарий «Возврат после cooldown 24-48h (проверить через targeted test)». Он же и сейчас лежит в живом контейнере:docker exec gendesign-beat-1 grep -n cooldown /app/app/workers/beat_schedule.pyна 17.09 выдаёт строки 353 и 369.То же обещание таймера оператор видел в отказе ручных эндпоинтов каталога (
POST /api/v1/admin/scrape/kn-catalog-objectsи/kn-catalog-flats): HTTP 400 советовал передатьi_understand_waf_risk=true, «если WAF cooldown прошёл». Проверено на проде 17.09, только чтение: вgendesign-backend-1у_WAF_COOLDOWN_GUARD_MSGнет упоминания #3307, а слово cooldown есть.Почему это неправда
Точечный тест, о котором просила задача, провели трижды: 20.08, 27.08 и 01.09 (в комментариях здесь и в #3307).
job_settings.scrape_knстоитenabled=f, в description записана честная причина «RE-DISABLED 2026-09-01 ПО ФАКТУ ЗОНДОВ… StormWall…».У записей каталога флага в job_settings нет: они просто закомментированы в коде. Поэтому решение по ним жило только в комментарии с обещанием таймера — ровно то, против чего задача и была заведена.
Что сделано
backend/app/workers/beat_schedule.py: оба комментария теперь называют факт (зонды, StormWall, 403) и условие включения: прокси плюс kn-прогон, принятый по числу строк (#3307). Больше никакого «по таймеру».backend/tests/workers/test_beat_schedule_domrf_catalog.py: тест собирает beat-расписание и проверяет по значению, что ни одна из двух задач (tasks.scrape_kn_catalog_objects…,tasks.scrape_kn_catalog_flats…) в него не попала. Сверка идёт поtask, а не по ключу, так что переименованный ключ проверку не обойдёт. Контроль в тесте убеждается, что статическая часть расписания действительно построилась, иначе пустое расписание давало бы зелёный результат само по себе. Когда кто-то включит запись, тест упадёт с текстом, который отправляет в #3307.backend/app/api/v1/admin_scrape.py: текст отказа guard'а переписан и константа переименована в_DOMRF_BLOCK_GUARD_MSG. Теперь отказ говорит, что наш.дом.рф за StormWall отдаёт «Доступ заблокирован [403]», что ожидание блокировку не снимает и что флаг ставится только при сборе через прокси и принятом kn-прогоне (#3307). Докстринги обоих эндпоинтов тоже больше не называют guard «WAF cooldown». Из докстринга objects-эндпоинта убрано «Beat schedule: Tuesday 04:00 UTC»: запись выключена, а расписание было в МСК.scrape_kn_catalog_flats.py(«WAF-cooldown на VPS IP; включается вручную после проверки targeted-тестом», «Beat отключён (WAF cooldown)») иscrape_kn_catalog_objects.py(«Beat schedule: вторник 04:00 UTC») говорят то же, что beat-комментарий.frontend/src/lib/api-types.tsперегенерирован так же, как это делает CI-гейтopenapi-codegen-check(дампapp.openapi()→openapi-typescript→ локальный prettier). Разница только в двух докстрингах эндпоинтов.backend/tests/api/v1/test_admin_scrape_kn_catalog_waf_guard.py: оба теста отказа проверяют, чтоdetailответа 400 называет #3307 и не содержит cooldown. Оператор решает по этому тексту, поэтому текст здесь и есть проверяемое значение.Поведение guard'а не менялось: без
i_understand_waf_risk=trueответ по-прежнему 400, задача не ставится. Запросов к наш.дом.рф не делал ни с прода, ни локально.Что НЕ сделано (поэтому без Closes)
scrape_knвсё ещё начинается с «Скрейпинг КН (ЦИАН)» (сидdata/sql/81_job_settings.sql:89, на проде то же). Для правки нужна миграция вdata/sql/, а номер миграции на эту работу не выдавали. Оставлено отдельным шагом.config.py,stealth.py,domrf_catalog*.py,pravo_gov66_client.py,okn_egrkn_client.pyи в описании поляi_understand_waf_risk. Таймера и совета подождать там нет, это рассказ о майском эпизоде, поэтому не трогал.fixes/Fix_Night_Checkpoints_Wrong_Instruments_Aug28.md(«история опровергает посылку #2443…») иaudits/Project_Status_Revision_0901.md(StormWall, #3307, #2443 ждёт решения по прокси). Проверено 17.09.Правки по ревью
Каждую находку сначала проверил сам.
grep -n cooldown backend/app/workers/beat_schedule.pyвыдаёт 67 и 349: новый комментарий сам цитирует старую посылку «hard-ban, cooldown 24-48h». Раздел «Приёмка на проде» переписан. Главный маркер теперьgrep -c StormWall(на проде 17.09 даёт 0, в ветке 2). Второй маркерgrep -c "Возврат после"(на проде 2, в ветке 0): он есть только в старой версии и пропадает в новой. Ожидание по cooldown исправлено на 67 и 349. Код это не задевало.admin_scrape.py, «Beat schedule: Tuesday 04:00 UTC»). Её в ревью не было, исправил заодно.scrape_runsв gendesign нет. Верно. Прод 17.09, только чтение:to_regclass('public.scrape_runs')пусто,v_scrape_runs_unifiedиkn_scrape_runsесть. Заметка ниже поправлена.Тесты
cd backend && uv run python -m pytest tests/workers/test_beat_schedule_domrf_catalog.py tests/api/v1/test_admin_scrape_kn_catalog_waf_guard.py -q: 6 passed, rc=0.uv run python -m pytest tests/ -q -p no:cacheprovider: 5033 passed, 84 skipped, 4 failed, rc=1. Все 4 падения относятся кtests/ops/test_2203_backup_trailer_grep_dashdash.py. Это известная проблема BSD mktemp на macOS, к этой правке она отношения не имеет. Сьют гонялся до мержа origin/main. Мерж принёс толькоtradein-mvp/backend/data/sql/308_…sql(#3567), backend ПТИЦА он не трогает. После мержа два целевых файла снова дали 6 passed, rc=0,ruff checkrc=0, а маркеры приёмки на дереве ветки совпали с ожидаемыми (StormWall 2, «Возврат после» 0, cooldown 67 и 349, guardTrue True False).uv run ruff check app tests: All checks passed, rc=0.ruff format --checkпо 4 изменённым py-файлам: already formatted, rc=0.api-types.tsменяются только два докстринга (18 строк). Значит, до правки файл совпадал со схемой, а теперь закоммичен в перегенерированном виде.Фальсификация
Beat (первый коммит). Вернул в
beat_schedule.pyзапись для квартир каталога под переименованным ключомkn-flats-renamed(исходник предварительно скопирован в scratchpad). Прогон покраснел:После этого исходник восстановил,
diff -qрасхождений не нашёл, тест снова зелёный.Guard (коммит по ревью). Исправленный
admin_scrape.pyскопировал в scratchpad и дважды его ломал.Мутация A: хвост отказа вернул к старому совету «…передай i_understand_waf_risk=true, если WAF cooldown прошёл (targeted smoke-test)». Результат:
Мутация B проверяла, что вторая проверка живая сама по себе: #3307 оставил, добавил «…(#3307) или WAF cooldown прошёл.». Результат:
После каждой мутации исходник восстановлен,
diff -qс копией пустой (rc=0), тесты снова зелёные.Этот же тестовый файл на исходном тексте из main (до правки
admin_scrape.py) даёт2 failed, 3 passed, rc=1.Приёмка на проде (после деплоя, не раньше 17.09.2026)
Значения «сейчас» сняты 17.09.2026 с
poincare, только чтение.ssh poincare "docker exec gendesign-beat-1 grep -c StormWall /app/app/workers/beat_schedule.py"должна дать 2. Сейчас 0.docker exec gendesign-beat-1 grep -c "Возврат после" /app/app/workers/beat_schedule.pyдолжна дать 0. Сейчас 2.docker exec gendesign-beat-1 grep -n cooldown /app/app/workers/beat_schedule.pyдолжна найти 67 и 349. 67 — историческая строка про инцидент env-fallback, 349 — новый комментарий, который цитирует опровергнутую посылку. Сейчас 67, 353, 369. Если main до мержа поменяет начало файла, номера сдвинутся, поэтому решают счётчики выше.docker exec gendesign-backend-1 python -c "import app.api.v1.admin_scrape as a; m=getattr(a,'_DOMRF_BLOCK_GUARD_MSG',None) or a._WAF_COOLDOWN_GUARD_MSG; print(hasattr(a,'_DOMRF_BLOCK_GUARD_MSG'), '3307' in m, 'cooldown' in m.lower())"должна напечататьTrue True False. Сейчас печатаетFalse False True.scrape_kn_catalog.Деплой
Деплой пересоздаёт backend, worker и beat. В коде меняются только комментарии, докстринги и текст отказа guard'а. Frontend тоже пересоберётся, потому что изменился
frontend/src/lib/api-types.ts, но там поменялись только комментарии. Миграций нет.Пересоздание worker прерывает работающие Celery-задачи. Перед деплоем проверить:
SELECT count(*) FROM v_scrape_runs_unified WHERE status='running'(таблицыscrape_runsв gendesign нет; kn-прогоны лежат вkn_scrape_runs). 17.09 вv_scrape_runs_unifiedстрок со статусом running не было.Refs #2443, #3307, #2442
🤖 Generated with Claude Code