ChatAskRequest.history: max_length=20 даёт hard-422 на длинном диалоге вместо задокументированного усечения (контракт-vs-поведение) #1572

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

Severity: low · Категория: contract / doc-mismatch · Файл: backend/app/schemas/chat.py:85-89

Файл backend/app/schemas/chat.py:85-89 — поле history объявлено как Field(default=None, max_length=_HISTORY_MAX_TURNS, ...) с _HISTORY_MAX_TURNS=20 (line 22). В Pydantic v2 max_length на списке — это валидационный потолок: запрос с 21+ ходами отклоняется 422 ('List should have at most 20 items') ещё ДО входа в хендлер ask (api/v1/chat.py:53). Однако docstring модуля (chat.py:6-7) и описание поля (line 88) обещают 'кэпируем последние N ходов', т.е. graceful-усечение хвоста. Усечения нигде нет: orchestrator.py:127 делает del db, history, история в Step 2 не форвардится и нигде не обрезается. Импакт сейчас минимален: history полностью не используется (Step 1 детерминированный; Step 2 явно её дропает), поэтому функциональной регрессии нет — это латентный риск 422 на длинных сессиях при включении Step-2 LLM-форвардинга истории + расхождение с уже опубликованным фронту контрактом. Фикс: либо заменить max_length на мягкое усечение в валидаторе/хендлере (payload.history = payload.history[-_HISTORY_MAX_TURNS:]), либо привести docstring/описание поля к реальному жёсткому поведению (отдаём 422, а не усекаем).

Почему баг: Поведение расходится с задокументированным контрактом: длинный диалог фронта получает hard-422 «List should have at most 20 items» вместо graceful-усечения старых ходов. Для Step 1 импакт минимален (история не используется), но контракт уже отдаётся фронту, и при включении Step-2 LLM длинная сессия будет ломаться 422 вместо ожидаемого «берём последние 20».

Как чинить: Либо привести код к контракту — снять max_length и усекать в хендлере payload.history[-_HISTORY_MAX_TURNS:] перед передачей в оркестратор; либо привести контракт к коду — переписать docstring/description на «принимаем не более N ходов, иначе 422» (не «последние N»).


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

**Severity:** low · **Категория:** contract / doc-mismatch · **Файл:** `backend/app/schemas/chat.py:85-89` Файл backend/app/schemas/chat.py:85-89 — поле history объявлено как `Field(default=None, max_length=_HISTORY_MAX_TURNS, ...)` с _HISTORY_MAX_TURNS=20 (line 22). В Pydantic v2 max_length на списке — это валидационный потолок: запрос с 21+ ходами отклоняется 422 ('List should have at most 20 items') ещё ДО входа в хендлер ask (api/v1/chat.py:53). Однако docstring модуля (chat.py:6-7) и описание поля (line 88) обещают 'кэпируем последние N ходов', т.е. graceful-усечение хвоста. Усечения нигде нет: orchestrator.py:127 делает `del db, history`, история в Step 2 не форвардится и нигде не обрезается. Импакт сейчас минимален: history полностью не используется (Step 1 детерминированный; Step 2 явно её дропает), поэтому функциональной регрессии нет — это латентный риск 422 на длинных сессиях при включении Step-2 LLM-форвардинга истории + расхождение с уже опубликованным фронту контрактом. Фикс: либо заменить max_length на мягкое усечение в валидаторе/хендлере (`payload.history = payload.history[-_HISTORY_MAX_TURNS:]`), либо привести docstring/описание поля к реальному жёсткому поведению (отдаём 422, а не усекаем). **Почему баг:** Поведение расходится с задокументированным контрактом: длинный диалог фронта получает hard-422 «List should have at most 20 items» вместо graceful-усечения старых ходов. Для Step 1 импакт минимален (история не используется), но контракт уже отдаётся фронту, и при включении Step-2 LLM длинная сессия будет ломаться 422 вместо ожидаемого «берём последние 20». **Как чинить:** Либо привести код к контракту — снять `max_length` и усекать в хендлере `payload.history[-_HISTORY_MAX_TURNS:]` перед передачей в оркестратор; либо привести контракт к коду — переписать docstring/description на «принимаем не более N ходов, иначе 422» (не «последние N»). --- <sub>deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.78 · unit B09</sub>
bot-backend added the
week ревью 1
label 2026-06-16 17:06:28 +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#1572
No description provided.