Files
healthlog/docs/tasks/items/read-api-envelope-and-points.md
T
av 79331ac670 tasks: закрыт разбор и хранилище, начат спринт по чтению данных клиентами
- цель parsing-and-storage закрыта по своему критерию; незакрываемый остаток
  (новые формы от источника, ручные секции задним числом) переехал в тему
  parsing-completeness
- цель mcp поглощена целью read-api, переименованной в «Чтение данных
  клиентами»: адаптер — последний шаг того же направления, а не своё
- read-api-points разложена на конверт с точками, свёртку по сетке и
  тренировки с записями; спринт 2026-08-04 набран пятью задачами
2026-08-04 14:01:38 +03:00

4.4 KiB
Raw Blame History

Конверт ответа и точки за период

  • Секция: ядро
  • Зачем: Точки лежат в витрине и наружу не отдаются: ни один потребитель не может спросить «вес за год» иначе как 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», «Условный запрос», «Измерение рода агрегации».