DDU-индикатор: area_ranges целиком вне диапазона 1..6 молча возвращает ВСЕ площади вместо пустого/422 #1565

Closed
opened 2026-06-16 17:05:35 +00:00 by bot-backend · 0 comments
Collaborator

Severity: low · Категория: validation/silent-wrong-result · Файл: backend/app/services/analytics/ddu_price_indicator.py:146-150

Файл: backend/app/services/analytics/ddu_price_indicator.py:146-150 (эндпоинт POST /api/v1/market/ddu-indicator). Схема DduIndicatorRequest.area_ranges (schemas/market.py:38) — просто list[int]|None без границ. В сервисе: if area_ranges:clean_buckets = sorted({int(b) for b in area_ranges if 0 <= int(b) <= 6})if clean_buckets:. Если клиент прислал area_ranges, состоящий ИСКЛЮЧИТЕЛЬНО из значений вне 0..6 (например [7,8] или [-1]), то clean_buckets == [] → bucket_filter остаётся пустой строкой → SQL отдаёт ВСЕ area_bucket (0..6), включая headline. Импакт: тихий неверный результат — пользователь явно сузил выборку конкретными площадями, а получает полный датасет; note об отброшенных bucket'ах не добавляется. Сравнить с веткой if not subject_ok (строки 126-138), где запрос исключительно неподдерживаемых субъектов корректно даёт пустой ответ + notes — для area_ranges аналогичной защиты нет. Фикс: при непустом area_ranges и пустом clean_buckets либо вернуть пустой table/graph с note ('areaRanges=<...> вне 0..6 — пустой результат'), либо отдать 422; по аналогии с обработкой subject_ok. Severity low: edge-кейс некорректного ввода на аналитическом read-only эндпоинте, не порча данных.

Почему баг: Клиент явно ограничил выборку конкретными (пусть и несуществующими) площадями и ожидает либо пустой результат, либо ошибку 422, а получает полный датасет по всем площадям. Для ценового индикатора это тихий неверный результат: фронт может отрисовать headline-серию (bucket 0) и все площади там, где пользователь просил узкий срез. Сравните с веткой if not subject_ok (строки 126-138), где запрос исключительно неподдерживаемых субъектов корректно даёт пустой ответ с notes — для area_ranges аналогичной защиты нет, и note об отброшенных bucket'ах тоже не добавляется.

Как чинить: Если area_ranges непустой, но после фильтрации 0<=b<=6 clean_buckets пуст — вернуть пустой table/graph с note ('areaRanges=<...> вне диапазона 1..6'), а не молча отдавать все площади. Либо ужесточить схему: Field(area_ranges, ...) с per-item bound (conlist/Annotated[int, Field(ge=0, le=6)]).


deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.78 · unit B05

**Severity:** low · **Категория:** validation/silent-wrong-result · **Файл:** `backend/app/services/analytics/ddu_price_indicator.py:146-150` Файл: backend/app/services/analytics/ddu_price_indicator.py:146-150 (эндпоинт POST /api/v1/market/ddu-indicator). Схема DduIndicatorRequest.area_ranges (schemas/market.py:38) — просто list[int]|None без границ. В сервисе: `if area_ranges:` → `clean_buckets = sorted({int(b) for b in area_ranges if 0 <= int(b) <= 6})` → `if clean_buckets:`. Если клиент прислал area_ranges, состоящий ИСКЛЮЧИТЕЛЬНО из значений вне 0..6 (например [7,8] или [-1]), то clean_buckets == [] → bucket_filter остаётся пустой строкой → SQL отдаёт ВСЕ area_bucket (0..6), включая headline. Импакт: тихий неверный результат — пользователь явно сузил выборку конкретными площадями, а получает полный датасет; note об отброшенных bucket'ах не добавляется. Сравнить с веткой `if not subject_ok` (строки 126-138), где запрос исключительно неподдерживаемых субъектов корректно даёт пустой ответ + notes — для area_ranges аналогичной защиты нет. Фикс: при непустом area_ranges и пустом clean_buckets либо вернуть пустой table/graph с note ('areaRanges=<...> вне 0..6 — пустой результат'), либо отдать 422; по аналогии с обработкой subject_ok. Severity low: edge-кейс некорректного ввода на аналитическом read-only эндпоинте, не порча данных. **Почему баг:** Клиент явно ограничил выборку конкретными (пусть и несуществующими) площадями и ожидает либо пустой результат, либо ошибку 422, а получает полный датасет по всем площадям. Для ценового индикатора это тихий неверный результат: фронт может отрисовать headline-серию (bucket 0) и все площади там, где пользователь просил узкий срез. Сравните с веткой `if not subject_ok` (строки 126-138), где запрос исключительно неподдерживаемых субъектов корректно даёт пустой ответ с notes — для area_ranges аналогичной защиты нет, и note об отброшенных bucket'ах тоже не добавляется. **Как чинить:** Если area_ranges непустой, но после фильтрации 0<=b<=6 clean_buckets пуст — вернуть пустой table/graph с note ('areaRanges=<...> вне диапазона 1..6'), а не молча отдавать все площади. Либо ужесточить схему: Field(area_ranges, ...) с per-item bound (conlist/Annotated[int, Field(ge=0, le=6)]). --- <sub>deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.78 · unit B05</sub>
bot-backend added the
week ревью 1
label 2026-06-16 17:05:35 +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#1565
No description provided.