fix(tradein): drop non-EKB avito detail coords on ingest (audit #1871 P2) #1879

Merged
bot-backend merged 1 commit from audit/1871-p2-avito-coord into main 2026-06-23 09:34:14 +00:00
Collaborator

Summary

Audit-issue #1871 🟠 P2 — Avito coord-filter. Prod-verified 2026-06-23: 406 active avito-листингов с координатами Питер/Тюмень/Уфа просочились в ЕКБ-датасет (ложные аналоги через Tier A address-match оценщика). Дыра — avito_detail.parse_detail_html писал data-map-lat/lon без bbox-валидации (geocoder фильтрует везде, avito_detail — нет).

Изменения (4 файла, +184/-2)

  • geocoder.py — DRY-хелпер is_within_ekb_bbox(lat, lon, bbox) + is_within_ekb_bbox_wide(); константы EKB_BBOX_TIGHT (56.65-56.95/60.40-60.85, = старые inline-числа) + EKB_BBOX_WIDE (56.6-57.1/60.3-60.9). 2 inline tight-проверки → хелпер (поведение identical).
  • avito_detail.py — guard в parse_detail_html: после извлечения lat/lon, если вне wide-bbox → reset None + logger.warning. COALESCE NULL не затирает прежнее хорошее значение; листинг падает в geocode-cron.
  • 2 теста — bbox-хелпер (ЕКБ True, Питер/Тюмень/Уфа False, inclusive, WIDE⊇TIGHT инвариант) + guard end-to-end.

WIDE строго содержит TIGHT — guard физически не режет ничего, что geocoder сам бы пропустил.

Scope-границы

  • NULL lat (14935, geocode-cron backlog) — отдельная проблема (недобор, не засорение), не в scope.
  • One-time cleanup существующих 406 — отдельно (prod data mutation, database-expert). Предлагаемый SQL в коммите.
  • estimator.py / SERP avito.py — не тронуты (отдельный PR для dedup+split).

Test plan

  • ruff clean (мои файлы); bbox + guard тесты passed; 235 passed в gate-фильтре
  • code-reviewer APPROVE (lat/lon swap проверен)
  • post-deploy: новые не-ЕКБ avito coords не пишутся (logger.warning в логах)
  • решить one-time cleanup 406 (отдельно)

Deploy: deploy-tradein.yml.

Refs #1871

🤖 Generated with Claude Code

## Summary Audit-issue #1871 🟠 P2 — Avito coord-filter. **Prod-verified 2026-06-23:** 406 active avito-листингов с координатами Питер/Тюмень/Уфа просочились в ЕКБ-датасет (ложные аналоги через Tier A address-match оценщика). Дыра — `avito_detail.parse_detail_html` писал `data-map-lat/lon` без bbox-валидации (geocoder фильтрует везде, avito_detail — нет). ## Изменения (4 файла, +184/-2) - **geocoder.py** — DRY-хелпер `is_within_ekb_bbox(lat, lon, bbox)` + `is_within_ekb_bbox_wide()`; константы `EKB_BBOX_TIGHT` (56.65-56.95/60.40-60.85, = старые inline-числа) + `EKB_BBOX_WIDE` (56.6-57.1/60.3-60.9). 2 inline tight-проверки → хелпер (поведение identical). - **avito_detail.py** — guard в `parse_detail_html`: после извлечения lat/lon, если вне wide-bbox → reset None + `logger.warning`. COALESCE NULL не затирает прежнее хорошее значение; листинг падает в geocode-cron. - **2 теста** — bbox-хелпер (ЕКБ True, Питер/Тюмень/Уфа False, inclusive, **WIDE⊇TIGHT** инвариант) + guard end-to-end. WIDE строго содержит TIGHT — guard физически не режет ничего, что geocoder сам бы пропустил. ## Scope-границы - **NULL lat** (14935, geocode-cron backlog) — отдельная проблема (недобор, не засорение), не в scope. - **One-time cleanup** существующих 406 — отдельно (prod data mutation, database-expert). Предлагаемый SQL в коммите. - estimator.py / SERP avito.py — не тронуты (отдельный PR для dedup+split). ## Test plan - [x] ruff clean (мои файлы); bbox + guard тесты passed; 235 passed в gate-фильтре - [x] code-reviewer ✅ APPROVE (lat/lon swap проверен) - [ ] post-deploy: новые не-ЕКБ avito coords не пишутся (logger.warning в логах) - [ ] решить one-time cleanup 406 (отдельно) Deploy: `deploy-tradein.yml`. Refs #1871 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bot-backend added 1 commit 2026-06-23 09:33:34 +00:00
fix(tradein): drop non-EKB avito detail coords on ingest (audit #1871 P2)
All checks were successful
CI / changes (pull_request) Successful in 5s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
04550bc94f
avito_detail.parse_detail_html писал data-map-lat/lon прямо в listings
UPDATE COALESCE без bbox-валидации — в отличие от geocoder.py, который
фильтрует везде. Итог: 406 active avito-листингов с координатами
Питер/Тюмень/Уфа просочились в ЕКБ-датасет (ложные аналоги через Tier A
address-match оценщика). Prod-verified 2026-06-23.

- geocoder: DRY-хелпер is_within_ekb_bbox(lat, lon, bbox) + именованные
  EKB_BBOX_TIGHT (geocoder-фильтр, числа не изменены) и EKB_BBOX_WIDE
  (ingest-guard); 2 inline tight-проверки → хелпер (поведение identical).
- avito_detail: после извлечения lat/lon → reset None + logger.warning
  если вне wide-bbox; листинг падает в geocode-cron путь (COALESCE NULL
  не затирает прежнее хорошее значение).
- tests: bbox-хелпер (ЕКБ True, Питер/Тюмень/Уфа False, inclusive,
  WIDE⊇TIGHT инвариант) + parse_detail_html guard end-to-end.

WIDE строго содержит TIGHT — guard физически не режет ничего, что
geocoder сам бы пропустил. NULL lat (14935, geocode backlog) — отдельная
проблема, не в scope. One-time cleanup существующих 406 — отдельно
(database-expert, prod data mutation).

Refs #1871
bot-backend merged commit 50b57788ee into main 2026-06-23 09:34:14 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1879
No description provided.