fix(cian): verify_session на curl_cffi impersonate — ban != cookies expired (Refs #768) #785
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
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#785
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/768-cian-verify-curlcffi"
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?
Что
verify_sessionпроверял валидность cian-cookies черезhttpx, который Cian банит по TLS-fingerprint → бан трактовался как «cookies expired» → ложный алерт оператору обновить куки (хотя куки валидны).Как
httpx→curl_cffi.requests.AsyncSession(impersonate="chrome120")— тот же fingerprint, что у боевого cian-скрейпа (cian.py/cian_detail.py/cian_newbuilding.py/cian_valuation.py)._classify_verify_response(status, html)(pure):403/TLS →VERIFY_BAN_SENTINEL(truthy, НЕ expired — alert re-upload подавляется);401/isAuthenticated=false→None(expired, контракт сохранён);200+auth → state dict.dict | None) — callers, проверяющиеif state is None, не ломаются; ban теперь не схлопывается в тот же None-as-expired.Тесты
11 тестов (6 unit на classifier — без I/O; 5 async на
AsyncSession-мок): ban→не-expired, 401→expired, auth→valid.pytest -k cian_session26 pass, ruff clean.Боевой cian-скрейп и cookie-storage не тронуты.
Refs #768
✅ APPROVE
cian verify_session на curl_cffi impersonate (#768). Ключевой риск — return-type change (403-ban теперь truthy
VERIFY_BAN_SENTINELбезuser-ключа вместо None) — проверил все 3 caller'а:if state is None: return; non-None путь НЕ дереференситstate(только_claim_run). На ban → продолжает run (корректно: ban был артефактом httpx-verify; backfill на curl_cffi с правильным fingerprint). Без краша, и без ложного "cookies expired" Sentry-алерта — суть фикса.state.get("user", {}).get("userId")(defensive.get(), не subscript) → sentinel даётuserId=None, без KeyError.Return-type change безопасен — потенциальный KeyError смягчён везде. Классификатор pure + покрыт (403→sentinel, 401→None, isAuth=false→None, else state);
impersonate="chrome120"как у прод-скрейперов; cookies не логируются (сохранено). 11 тестов (6 pure + 5 async mock), 26 pass, ruff clean.Advisory (non-blocking) —
test-authdebug-эндпоинт косметически репортит 403-ban как{authenticated: true, userId: null}; безвредно, можно follow-up'ом вынести reason "banned".Scope/security — cian_session.py + тест; нет secrets, нет self-extending триггера. P3.
Verdict: ✅ APPROVE (#768). Smoke → qa.