# Bug #001 — Product.Name с NULL-byte вызывает 500 (без ответа)

**Severity:** Medium  
**Component:** `POST /api/catalog/products` (и любой другой endpoint, принимающий строку, которая попадает в TEXT/VARCHAR-колонку Postgres)  
**Found:** Sprint 23 (adversarial bug-hunt), 2026-06-08

## Воспроизведение

```bash
curl -X POST -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
  -d '{"name":"Hello World","unitOfMeasureId":"…","productGroupId":"…",
       "vat":0,"vatEnabled":true,
       "barcodes":[{"code":"NB-1","type":0,"isPrimary":true}],
       "prices":[{"priceTypeId":"…","amount":500,"currencyId":"…"}]}' \
  https://test.admin.food-market.kz/api/catalog/products
```

**Ответ:** HTTP 500 с пустым body.

## Ожидание

400 с понятным сообщением: «В поле Name недопустимые символы (NUL)».

## Причина

PostgreSQL TEXT/VARCHAR не допускает `\x00` — Npgsql выбрасывает `PostgresException 22021 (character not in repertoire)`. В контроллере ловится только `DbUpdateException`-в обёртке по `IX_*_Article` — все остальные uncaught → middleware возвращает 500.

## Фикс

Добавить в `ProductInputValidator` (и `CounterpartyInputValidator`) проверку «нет NUL-байт в строковых полях». Для широкого охвата — отдельный `MustNotContainControlChars()` extension на `StringValidator`.

Альтернатива: глобальный JSON-middleware, который reject'ит strings c `\x00`. Менее точно (теряем контекст поля), но защищает все endpoint'ы автоматом.

Выбран **первый вариант** — точечно в FluentValidation.

## Retest

После фикса: `POST /api/catalog/products` с `\x00` в name → **400** с сообщением «Поле Name не должно содержать управляющих символов.».
