[Fable 5][P2] _ACTIVE_STATUSES — английские значения против русского словаря site_status: POST /competitors всегда отдаёт is_active=false, active_count=0 #1213

Closed
opened 2026-06-13 04:49:44 +00:00 by bot-backend · 0 comments
Collaborator

Из армейского ревью Claude Fable 5 (2026-06-11)

Confirmed by 2/2 адверсариальных верификатора, severity P2 (correctness), confidence 0.7.

Файл

backend/app/services/site_finder/competitors.py:61

Evidence (цитата кода)

# site_status значения, считающиеся «активными»
_ACTIVE_STATUSES = frozenset({"sales", "construction"})
...
        site_status = r["site_status"]
        is_active = site_status in _ACTIVE_STATUSES if site_status else False

Why bug

domrf_kn_objects.site_status хранит русские значения 'Строящиеся'/'Сданные' (partial index в data/sql/66_indexes_recommend.sql, prod-аудит в 105_add_sales_started_flag.sql, фильтры analytics_queries.py:1430, фронтовые проверки MarketTab/CompetitorTable). Английский frozenset не совпадает никогда → у всех Competitor из POST /parcels/{cad}/competitors is_active=false и CompetitorsSummary.active_count=0 при любых данных — типизированный контракт систематически врёт.

Suggested fix

_ACTIVE_STATUSES = frozenset({"Строящиеся"}) или нормализовать и матчить оба словаря; заодно заполнять Competitor.site_status/ready_dt из SQL-строки (сейчас всегда None).

Verify notes

  • [real/P2] Трасса: POST /parcels/{cad}/competitors → _COMPETITORS_SQL отдаёт site_status сырым из domrf_kn_objects. Реальные значения русские: scraper пишет siteStatus дом.рф без перевода; прод-фильтры и partial index используют 'Строящиеся'. 'Строящиеся' ∉ {"sales","construction"} → is_active=False у всех конкурентов, active_count=0 всегда. Английские значения есть только в самом frozenset и unit-моках (тесты кодируют баг). P2: контракт систематически врёт, но velocity/форсайт-числа не затронуты.
  • [real/P2] Защиты нет: SQL отдаёт o.site_status как есть, ingest (domrf_kn.py:316) пишет сырой siteStatus ДОМ.РФ. Прод-значения русские: аудит 105_add_sales_started_flag.sql ('Строящиеся', 1322 шт.), partial index 66, фильтры analytics_queries, фронт MarketTab/CompetitorTable. 'sales'/'construction' есть лишь в моках test_parcel_competitors.py. Эндпоинт всегда отдаёт is_active=false, active_count=0. Смягчение: внутренние консьюмеры is_active не читают → P2, не выше.

Provenance

  • Finders: schemas-models
  • Confidence: 0.7
  • Originally batched at: main@d796027
## Из армейского ревью Claude Fable 5 (2026-06-11) Confirmed by 2/2 адверсариальных верификатора, severity **P2** (correctness), confidence 0.7. ## Файл [`backend/app/services/site_finder/competitors.py:61`](backend/app/services/site_finder/competitors.py:61) ## Evidence (цитата кода) ``` # site_status значения, считающиеся «активными» _ACTIVE_STATUSES = frozenset({"sales", "construction"}) ... site_status = r["site_status"] is_active = site_status in _ACTIVE_STATUSES if site_status else False ``` ## Why bug domrf_kn_objects.site_status хранит русские значения 'Строящиеся'/'Сданные' (partial index в data/sql/66_indexes_recommend.sql, prod-аудит в 105_add_sales_started_flag.sql, фильтры analytics_queries.py:1430, фронтовые проверки MarketTab/CompetitorTable). Английский frozenset не совпадает никогда → у всех Competitor из POST /parcels/{cad}/competitors is_active=false и CompetitorsSummary.active_count=0 при любых данных — типизированный контракт систематически врёт. ## Suggested fix _ACTIVE_STATUSES = frozenset({"Строящиеся"}) или нормализовать и матчить оба словаря; заодно заполнять Competitor.site_status/ready_dt из SQL-строки (сейчас всегда None). ## Verify notes - [real/P2] Трасса: POST /parcels/{cad}/competitors → _COMPETITORS_SQL отдаёт site_status сырым из domrf_kn_objects. Реальные значения русские: scraper пишет siteStatus дом.рф без перевода; прод-фильтры и partial index используют 'Строящиеся'. 'Строящиеся' ∉ {"sales","construction"} → is_active=False у всех конкурентов, active_count=0 всегда. Английские значения есть только в самом frozenset и unit-моках (тесты кодируют баг). P2: контракт систематически врёт, но velocity/форсайт-числа не затронуты. - [real/P2] Защиты нет: SQL отдаёт o.site_status как есть, ingest (domrf_kn.py:316) пишет сырой siteStatus ДОМ.РФ. Прод-значения русские: аудит 105_add_sales_started_flag.sql ('Строящиеся', 1322 шт.), partial index 66, фильтры analytics_queries, фронт MarketTab/CompetitorTable. 'sales'/'construction' есть лишь в моках test_parcel_competitors.py. Эндпоинт всегда отдаёт is_active=false, active_count=0. Смягчение: внутренние консьюмеры is_active не читают → P2, не выше. ## Provenance - Finders: `schemas-models` - Confidence: 0.7 - Originally batched at: main@d796027
bot-backend added the
Fable 5 ревью
label 2026-06-13 04:49:44 +00:00
Sign in to join this conversation.
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#1213
No description provided.