diff --git a/agents/antigravity/inbox/2026-08-20-console-node-metrics.md b/agents/antigravity/inbox/2026-08-20-console-node-metrics.md new file mode 100644 index 0000000..091c1de --- /dev/null +++ b/agents/antigravity/inbox/2026-08-20-console-node-metrics.md @@ -0,0 +1,110 @@ +# Метрики и короткая история узлов в веб-консоли + +- **Кому:** `antigravity` +- **Дата:** 2026-08-20 +- **От кого:** главный агент (`claude`), по задаче владельца «консоль надо + сделать так же, как и Windows-программа» +- **Ветка:** `antigravity/console-node-metrics` +- **Файл отчёта:** `../done/2026-08-20-console-node-metrics.md` + +## Зачем + +Windows-клиент на странице «Серверы» показывает по каждому серверу CPU, +память, диск, задержку, состояние здоровья и статус +(`Pages/ServersPage.xaml`: `CpuText`, `MemoryText`, `DiskText`, +`LatencyText`, `HealthText`, `Status`). Веб-консоль не показывает ничего из +этого: в ней есть только имя узла, состояние, версия агента, время +heartbeat и остаток срока сертификата. + +Это первая из нескольких задач по сближению консоли с Windows-клиентом. +Здесь закрывается ровно метрики и короткая история — остальное перечислено +ниже и в эту задачу не входит. + +## Установленный факт, от которого отталкиваемся + +Данные **уже есть на Hub**, показывать нечем. + +`ControlStore` содержит таблицу (`ControlStore.cs:81`): + +```sql +CREATE TABLE IF NOT EXISTS metric_samples ( + sequence INTEGER PRIMARY KEY AUTOINCREMENT, + node_id TEXT NOT NULL REFERENCES agents(node_id) ON DELETE CASCADE, + recorded_at TEXT NOT NULL, + payload_json TEXT NOT NULL +); +CREATE INDEX IF NOT EXISTS ix_metric_samples_node_time + ON metric_samples(node_id, recorded_at DESC); +``` + +Наполняется она из heartbeat агента, чистится по `MetricRetentionHours` +(по умолчанию 168 часов). При этом в группе `/api/v1/control` **нет ни +одного маршрута для метрик** — я перечитал все `control.Map*` в +`Program.cs`. То есть оператор физически не может их получить. + +## Что нужно сделать + +1. **Добавить в Control чтение метрик под ролью Operator.** Как минимум + последний срез по каждому узлу и история по одному узлу за period. + Форму запроса, имена полей и ограничение на объём выбираешь сам и + обосновываешь в отчёте. Обязательные требования: маршрут в группе + `control` (то есть `RequireAuthorization("Operator")`), ограничение + количества возвращаемых точек, и никакого доступа к чужим данным по + роли Agent или Automation. +2. **Показать это в консоли** в разделе узлов: текущие CPU, память, диск и + задержка рядом с узлом, плюс короткая история — так же, как её + показывает Windows-клиент. +3. **`payload_json` — данные из внешнего источника.** Он приходит от + агента. Разбирать его в консоли только через уже имеющийся + `escapeHtml`, как это сделано с payload событий; ни одной вставки в + `innerHTML` без экранирования. Отсутствующие или битые поля не должны + ронять таблицу узлов. + +## Границы — что переносить нельзя + +**SSH-терминал и приватные ключи в веб-консоль не переносятся.** Это не +вопрос трудоёмкости, а заявленное свойство продукта: README обещает +«opens direct SSH terminals without sending a private terminal key to the +Hub», а ключ мониторинга и сертификат оператора защищены DPAPI и лежат +только на Windows-машине. Страница Sessions остаётся у Windows-клиента. + +Также не входит в эту задачу и делается отдельно: страница Settings, +группы и теги серверов, alert rules и журнал уведомлений (последние два +пункта в `docs/roadmap.md` числятся невыполненными и для Windows-клиента). + +Не трогать: `deploy/**`, релизные workflow, Desktop, схему существующих +таблиц (добавление индексов допустимо и обосновывается). + +## Как проверить результат + +- новый маршрут закрыт ролью: запрос без токена → 401, под ролью Agent и + Automation → 403, под Operator → 200. Три теста, вывод в отчёт; +- ограничение объёма истории проверено тестом: запрос заведомо большего + количества точек возвращает не больше предела; +- битый или неполный `payload_json` не роняет ни маршрут, ни отрисовку — + тест на каждую сторону; +- `dotnet test` целиком зелёный, с выводом; +- прогоны CI на PR — ссылками. + +## Связь с другими заданиями + +Эта задача пересекается с двумя уже выданными и делать её нужно **после** +них, иначе правки лягут друг на друга в одном файле: + +- `2026-08-19-console-behaviour-tests.md` — поведенческие тесты консоли. + Новая функциональность обязана прийти с такими тестами сразу, а не + проверками строк в HTML; +- `2026-08-19-console-events-throttle.md` — троттлинг обновления дашборда. + Метрики увеличат объём каждого обновления, поэтому без троттлинга + усиление нагрузки станет заметнее. + +Если считаешь, что порядок должен быть другим, — скажи в отчёте и обоснуй, +это решение приму. + +## Контекст и ограничения + +Проверено чтением кода и запуском Control локально на пустой базе: узлов +ноль, метрик ноль. Как выглядят настоящие `payload_json` от живого агента, +я не видел — на живом Hub не проверял. Прежде чем фиксировать контракт +ответа, посмотри фактическую форму payload в коде агента, а не в моём +описании.