[low] TradeInEstimateInput допускает floor > total_floors (нет cross-field валидации) #1389

Closed
opened 2026-06-14 18:10:16 +00:00 by bot-backend · 0 comments
Collaborator

Описание

floor и total_floors ограничены независимо ge=1/le=100, но нет валидатора floor <= total_floors. Запрос floor=50, total_floors=3 (квартира на 50-м этаже 3-этажного дома) принимается. Значение течёт в estimator и в PDF-экспорт (trade_in_pdf.py рендерит «Этаж: {floor} из {total_floors}» → «50 из 3»), создавая физически невозможную запись и потенциально перекашивая floor-position коррекцию цены (penalty первого/последнего этажа).

Корень

Отсутствует инвариант ввода (cross-field validator). Невалидная пара принимается, персистится в trade_in_estimates (INSERT строки 221-262) и попадает в клиентский PDF (trade_in_pdf.py:195).

Evidence

trade_in.py:18-20:

floor: int = Field(ge=1, le=100)
total_floors: int = Field(ge=1, le=100)
# нет @model_validator на floor <= total_floors

При floor=50, total_floors=3 ни ветка floor == 1, ни floor == total_floors в _floor_factor (trade_in.py:167) не срабатывает — last-floor discount молча пропускается.

Suggested fix

Добавить @model_validator(mode="after"), бросающий ValueError при floor > total_floors (напр. 'этаж не может превышать число этажей в доме').

Обоснование severity (low)

Estimator — явно Phase 1 mock (PDF footer «mock-данные (Phase 1 MVP)»), искажение цены затрагивает только иллюстративный вывод. Но дефект реален: невалидный инвариант принимается, персистится и попадает в PDF. Confidence 0.97.


week ревью 1 · multi-agent аудит 2026-06-14 · severity=low · category=logic

Затронутые файлы:

  • /Users/anton/Птица/gendesign/backend/app/schemas/trade_in.py
## Описание `floor` и `total_floors` ограничены независимо `ge=1/le=100`, но нет валидатора `floor <= total_floors`. Запрос `floor=50, total_floors=3` (квартира на 50-м этаже 3-этажного дома) принимается. Значение течёт в estimator и в PDF-экспорт (trade_in_pdf.py рендерит «Этаж: {floor} из {total_floors}» → «50 из 3»), создавая физически невозможную запись и потенциально перекашивая floor-position коррекцию цены (penalty первого/последнего этажа). ## Корень Отсутствует инвариант ввода (cross-field validator). Невалидная пара принимается, персистится в `trade_in_estimates` (INSERT строки 221-262) и попадает в клиентский PDF (trade_in_pdf.py:195). ## Evidence `trade_in.py:18-20`: ```python floor: int = Field(ge=1, le=100) total_floors: int = Field(ge=1, le=100) # нет @model_validator на floor <= total_floors ``` При floor=50, total_floors=3 ни ветка `floor == 1`, ни `floor == total_floors` в `_floor_factor` (trade_in.py:167) не срабатывает — last-floor discount молча пропускается. ## Suggested fix Добавить `@model_validator(mode="after")`, бросающий ValueError при `floor > total_floors` (напр. 'этаж не может превышать число этажей в доме'). ## Обоснование severity (low) Estimator — явно Phase 1 mock (PDF footer «mock-данные (Phase 1 MVP)»), искажение цены затрагивает только иллюстративный вывод. Но дефект реален: невалидный инвариант принимается, персистится и попадает в PDF. Confidence 0.97. --- _week ревью 1 · multi-agent аудит 2026-06-14 · severity=**low** · category=`logic`_ Затронутые файлы: - `/Users/anton/Птица/gendesign/backend/app/schemas/trade_in.py`
bot-backend added the
week ревью 1
label 2026-06-14 18:10:16 +00:00
bot-backend added the
scope/backend
label 2026-06-15 11:01:57 +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#1389
No description provided.