# Конверт ответа и точки за период - **Секция:** ядро - **Зачем:** Точки лежат в витрине и наружу не отдаются: ни один потребитель не может спросить «вес за год» иначе как sqlite3 на хосте - **Теги:** goal:read-api Потребитель получает значения метрики за период одним запросом `?from&to`, и из ответа видно, что именно ему отдали: слой, род свёртки и границу окна, в котором род измерен. Первая из трёх частей, на которые разложена `read-api-points`. Здесь решается **конверт** — форма, которую унаследуют все остальные маршруты чтения и оба транспорта. **Форма провода решается здесь, один раз.** Сегодня типы `internal/catalog` сами несут json-теги, а транспорт владеет только обёрткой: переименование поля в домене меняет публичный контракт без касания `httpapi`, и держит это один байтовый тест непустого ответа. Либо объявить в `architecture.md`, что типы чтения и есть форма провода для всех транспортов (HTTP и MCP отдают её байт в байт), либо завести DTO в транспорте. Выбрать надо **до** того, как образец скопируют соседние задачи. **Машинерия условного запроса готова — её берут, а не пишут заново.** `store.VersionedRead` держит правило «версией, снятой после чтения, не подписывать»; `httpapi` умеет `If-None-Match` и `304`. Новое здесь одно: метка обязана нести **область действия** — у точек ответ есть функция параметров запроса, поэтому `etag(scope, version)` требует их канонизированной формы, иначе `304` ответит на другой набор данных. Детали — `docs/architecture.md`, «Условный запрос». **Клиент обязан видеть границы окна измерения.** Род метрики измерен по 48 самым свежим **общим** часам, а не по последним 48 часам календаря: выключенная минутная автоматизация HAE останавливает пополнение множества общих часов, и окно замирает, продолжая объявлять род. Единственный след — `last_hour` в ответе; конверт обязан его нести. ## Критерии приёмки - «вес за год» отвечается одним запросом без доступа к файлу базы — оракул: запрос к поднятому сервису на живом архиве - в ответе всегда видны `layer`, `aggregation` и `last_hour` — оракул: тест на форме ответа - повторный запрос с `If-None-Match` даёт `304`, а тот же запрос с другими параметрами — `200` с другим телом — оракул: тест на паре запросов с разной областью действия метки - форма провода объявлена в `docs/architecture.md` — доменные типы или DTO, — и соседние маршруты ссылаются на это решение, а не повторяют выбор — оракул: глазами по разделу ## Рамки Схема не трогается, данные только читаются, сервис перезапускается. Против `./data` — только `task up` / `task run`. Связано: `docs/architecture.md` → «Read API», «Условный запрос», «Измерение рода агрегации».