httpapi: форма провода читающих маршрутов объявлена транспортом

- доменные типы internal/catalog лишились json-тегов и MarshalJSON; типы
  metricWire/layerWire/aggregationWire и перевод catalogWire живут в транспорте,
  тело отказа тоже получило объявленный тип — байты ответа не изменились
- заведён сторож: обход графа типов ответа утверждает, что домен не доезжает до
  сериализации, плюс требование json-тега на полях транспортных структур и
  заведомо красные случаи к обоим правилам
- решение с ценой обеих сторон записано в architecture.md и ADR; шаг lint в
  гейте получил свой кеш — общий на машину красил прогон находками из чужого
  worktree
This commit is contained in:
av
2026-08-04 16:18:05 +03:00
parent bd832337df
commit a834d10415
19 changed files with 1721 additions and 53 deletions
+20
View File
@@ -67,6 +67,26 @@
экспортированные функции, обходит лишь записи, достижимые из словаря: с
неплоской таблицей она остаётся зелёной (воспроизведено). Такие утверждения
живут во внутреннем тесте пакета и перебирают саму структуру.
- **Публичная форма ответа закрепляется байтами целого тела, и каждая различимая
форма — своим литералом.** Разбор проглатывает молча ровно то, что клиент
видит первым: `nil`-срез уезжает как `null`, отсутствующий ключ неотличим от
ключа с нулём, а разыменованный `*time.Time` даёт правдоподобную дату
`0001-01-01` вместо `null`. Тест, сличающий разобранные структуры или
подстроки, зелен в каждом из этих случаев — проверка «в ответе есть
`"first_hour"`» проходит и на нулевой дате. Различимых форм у ответа обычно
больше одной (пустая коллекция, измеренное значение, неизмеренное), и литерал
нужен каждой: одна закреплённая форма оставляет остальные без сторожа именно
там, где ручной перевод и ошибается. Литерал при этом **детектор изменения**,
а не источник истины контракта — правишь литерал, значит правишь контракт, и
рядом обязана лежать правка спеки.
- **Проверка, доказывающая ОТСУТСТВИЕ, несёт рядом заведомо красный случай.**
«Доменного типа в графе ответа нет», «значения точки в логе нет», «записи в
таблице нет» — все они зелены и будучи сломанными: протухшая константа,
пропущенная позиция обхода, перепутанное сравнение выглядят снаружи как
«искомого нет». Это обобщение двух правил ниже (отрицательный контроль для
правил порядка; утверждение о таблице-константе обходит саму таблицу): у
проверки на отсутствие обязан быть предъявленный вход, на котором она
краснеет.
- **Тест «в логе нет значения» проверяет запись без служебных полей, а не сырой
буфер.** Метка времени содержит доли секунды, поэтому искомая подстрока
находится в ней сама: проверка на «5.1» краснела примерно раз на сотню