# Protobuf/gRPC: правила транспортных контрактов

Цель: стабильные gRPC контракты между сервисами. `.proto` — источник правды **транспорта**, а не доменных моделей.

## Разделение “домен vs транспорт”
- Доменные модели живут в `internal/domain/types/*`.
- Транспортные DTO живут в `proto/` (gRPC) и в `specs/openapi/**` (HTTP/OpenAPI только для gateway-поверхностей).
- Маппинг делается на границе через `internal/domain/casters/*` (transport <-> domain).

## Правила `.proto`
- `.proto` — единственный источник правды для gRPC API внутренних сервисов.
- Версионирование: package содержит версию (`myproduct.v1`); breaking changes -> `v2` (или формальный план миграции).
- В live-кластере breaking change в `.proto` допустим только если все потребители обновляются в
  согласованном срезе и нет live rolling gap. Если такой гарантии нет, сначала добавляется новое
  поле/операция с новым номером, затем потребители переводятся на неё, и только потом старый
  контракт удаляется отдельным срезом.
- Объём `v1`:
  - если доменный API-контракт уже согласован, `.proto` для стабильного `v1` должен покрывать весь согласованный gRPC-объём домена;
  - частичный `.proto` нельзя называть стабильным `v1`; он должен быть явно оформлен как предварительный контракт с описанием ограничений;
  - стабильный `.proto` может появиться раньше полной реализации, но документ поставки обязан фиксировать, какие методы уже реализованы, а какие закрываются бэклогом до появления потребителей.
- Presence в proto3:
  - Если для scalar/enums важно отличать “не передано” от “передано значение по умолчанию”, поле объявляем как `optional`.
  - Это обеспечивает pointer-поля в Go (`*int32/*bool/...`) и корректную семантику частичных апдейтов/фильтров.
- Совместимость:
  - не переиспользовать номера полей;
  - не менять семантику существующих полей;
  - добавлять новые поля только с новыми номерами и так, чтобы старые клиенты продолжали работать;
  - удаление — через цикл `deprecate -> migrate -> remove`.
- Документация: все публичные сообщения/поля имеют комментарии (назначение, единицы измерения, ограничения).

## Ошибки в gRPC
- gRPC методы должны возвращать корректные `codes.*` по семантике:
  - not found -> `NotFound`
  - validation -> `InvalidArgument`
  - conflict -> `AlreadyExists`/`FailedPrecondition` (выбрать и зафиксировать правило)
  - temporary unavailable -> `Unavailable`
- Нельзя “всё превращать” в `Unknown/Internal` без маппинга доменной семантики (см. `docs/design-guidelines/go/error_handling.md`).
