## Why Точки лежат в витрине и наружу не отдаются: «вес за год» достаётся только `sqlite3` на хосте. Каталог уже отвечает, **что** есть, — но ни один из трёх потребителей не может получить сами значения. Ответ обязан быть самоописательным. Метрика лежит сразу в нескольких слоях подробности, а род её свёртки не объявлен источником, а **измерен** окном в 48 самых свежих **общих** часов — окном, которое замирает при выключенной минутной автоматизации HAE и продолжает объявлять род. Клиент, не видящий ни слоя, ни границы этого окна, принимает решение по числу, происхождения которого не знает. ## What Changes - Новый читающий маршрут `GET /api/v1/metrics/{name}?from&to&layer` — все точки метрики за период, одним запросом, без доступа к файлу базы. - Конверт ответа объявляет **фактические** параметры выдачи: `metric`, `from`, `to`, `layer`, `bucket`, `aggregation` (род, его применимость к отданному ряду и граница окна измерения), `points`. Поля присутствуют всегда — клиент не выводит их наличием или отсутствием. - Слой выбирается правилом, а не молча: параметр `layer` задаёт разрез явно, без него берётся слой с наибольшим охватом **точек** внутри запрошенного периода, при равенстве — самый мелкий. Смены слоя внутри одного ответа не бывает. - Род свёртки в конверте — тот же измеренный `catalog.Style`, что у каталога, и измеряется он тем же правилом и тем же окном. Род неизвестен — так и сказано словом `unknown`, а не молчанием. Рядом едет применимость: `cumulative` на нижнем слое HAE объявляется неприменимым, иначе конверт приглашает потребителя сложить интерполяцию и завысить втрое. - Свёртка в этом изменении **не выполняется**: `bucket` всегда `null`, а присутствие параметра `bucket` в запросе отвергается `400`, а не игнорируется молча. - Ответ снимается **одной транзакцией чтения**, а метка ответа включает канонизированную форму запроса **и горизонт измерения** — иначе соседняя задача условного запроса подтвердит `304` на сменившемся роде. - Форма провода — по образцу каталога (ADR `ADR-2026-08-04-forma-provoda-prinadlezhit-transportu`): типы `*Wire` в `internal/httpapi`, перевод присваиванием, строка в таблице образцов `wire_internal_test.go`. Схема базы не трогается: обе выборки отвечают по существующим ключу и покрывающему индексу `bucket_catalog`. ## Capabilities ### New Capabilities - `points`: точки метрики за период — форма запроса и его разбор, правило выбора слоя, состав конверта ответа, объявление измеренного рода вместе с границей окна измерения, дословность значений точки. ### Modified Capabilities - `read-api`: добавляются два общих правила читающих маршрутов — сериализация ответа не экранирует содержимое (иначе `&` внутри дословно сохранённой точки уезжает как `&`) и ответ чтения помечается непригодным для разделяемого кеша. Оба механизма общие (`writeJSON`, `setReadHeaders`), и решать их заново на каждом маршруте — тот же второй способ. `catalog` (правило измерения рода) применяется новым маршрутом без изменения его требований. ## Impact - `internal/httpapi` — маршрут, разбор параметров, форма провода точек, выключение HTML-экранирования в общем `writeJSON`. - `internal/points` (новый) — use-case «точки метрики за период»: выбор слоя, сборка ряда, измерение рода и метка ответа по одной метрике. - `internal/store` — один вход чтения ряда (`ReadSeries`) в одной транзакции: охваты слоёв в периоде, точки выбранного слоя, объекты окна измерения. - `docs/architecture.md` — разделы «Read API» (форма ответа, правило выбора слоя) и таблица компонентов. - Потребители: HTTP-клиенты; следом этот же конверт копируют свёртка по сетке, условный запрос по точкам, тренировки, записи и MCP.