BUG-026: Store name PATCH/POST → 500 при длине >255 символов

Описание

POST /api/v1/admin/stores и PATCH /api/v1/admin/stores/{id} падают в 500 INTERNAL_ERROR без понятной ошибки, если поле name длиннее 255 символов (например, 516 символов + emoji).

По REST-конвенции (см. api-design.md) и по контракту API.md невалидные данные обязаны возвращаться как 400 VALIDATION_ERROR с details:[{field, message}]. Сейчас сервер падает в catch-all-handler GlobalExceptionHandler.handleGeneral и отдаёт generic 500, что не даёт UI отобразить ошибку под полем формы.

Симптом найден на проде test-base/findings.md как F91 (session-2026-05-12, Critical).

Шаги воспроизведения

  1. Под admin@erp.local зайти в админку https://admin.nirbi.ru/admin/stores
  2. Открыть карточку любой ТТ → «Редактировать»
  3. В поле «Название» вставить строку 516 символов + emoji (фронт maxLength={255} обходится через DevTools / programmatic Playwright evaluate() или прямым API-вызовом)
  4. Нажать «Сохранить»

Ожидаемое поведение

  • Сервер возвращает 400 VALIDATION_ERROR с details: [{"field":"name","message":"name must not exceed 255 characters"}]
  • UI на фронте получает payload и показывает ошибку рядом с полем «Название» (errors.name в EditPage.tsx:199 уже умеет рендерить)

Фактическое поведение

  • Сервер возвращает 500 INTERNAL_ERROR с body {"error":{"code":"INTERNAL_ERROR","message":"Internal server error"}}
  • UI показывает только провал «Сохранение…» без понятного сообщения

Корневая причина

  1. dto/request/UpdateStoreRequest.java:18 — поле name без @Size (без @NotBlank)
  2. dto/request/CreateStoreRequest.java:21@NotBlank есть, @Size нет
  3. БД: stores.name varchar(255) (миграция 001-create-stores.xml:19)
  4. Цепочка отказа: DTO не валидирует длину → JPA пишет в PG → PG: value too long for type character varying(255)DataIntegrityViolationException → нет специального handler’а → catch-all Exception.class → 500

Контроллер PublicStoreController:69 уже использует @Valid — достаточно добавить аннотацию на DTO без правок контроллера.

Затронутые сервисы

  • Store Service — добавить @Size(max=255) на name в UpdateStoreRequest и CreateStoreRequest
  • Admin Franchise (web) — без изменений. EditPage.tsx:198 и CreatePage.tsx:156 уже имеют maxLength={255} на инпуте, фронт защищён через HTML

Спека требует уточнения

03-Services/Store Service/API.md секции POST /stores и PATCH /stores/{id} не указывают максимальную длину name. Это implicit-знание из БД-схемы. Добавить explicit max length 255 в Request Body описание.

Out of scope (отдельные finding’и)

Тот же класс багов потенциально есть на других строковых полях, но не в скоупе F91/BUG-026:

ПолеБДDTO @SizeФронт maxLength
phonevarchar(20)
cityvarchar(100)255 (расходится с БД)
emailvarchar(255)
timezonevarchar(50)

При длинных значениях этих полей backend упадёт в 500 по той же схеме. Заводятся отдельными finding’ами по мере подтверждения.

Ссылки