# Antigravity: управление Links и журнал событий в веб-консоли ## Репозиторий - https://github.com/ochenstarik-ui/server-monitor-manager - База: `main` @ `7c43977` - Ветка: `antigravity/console-links` - `main` защищён: PR обязателен, обязательны статусы `build-and-test` и `build`, force-push запрещён - один PR — одна тема; описание PR заполняется **после** завершения CI - отчёт — раздел в описании PR; отдельным файлом отчёт не является ## Задача Консоль сейчас показывает узлы и Links и выдаёт коды регистрации. Создать Link или отключить его из неё нельзя. Links — это главная функция продукта: направленный доступ от одного узла к другому по протоколу и порту, с ограниченным сроком жизни и возможностью мгновенно отозвать. Пока их нельзя ни выдать, ни отозвать из интерфейса, продуктом в его основном назначении пользоваться невозможно — только руками через API с клиентским сертификатом. **Новых эндпоинтов не требуется, все нужные уже есть.** Работа целиком в консоли. ## Что использовать | Действие | Эндпоинт | |---|---| | Список | `GET /api/v1/control/links` | | Создать | `POST /api/v1/control/links` | | Отключить | `POST /api/v1/control/links/{id}/disable` | | Журнал | `GET /api/v1/control/events` | Тело создания — `LinkPolicyCreateRequest`: `SourceNodeId`, `TargetNodeId`, `Protocol`, `Port`, `TtlMinutes`, `Reason`, `IdempotencyKey`. Отключение — `LinkPolicyDisableRequest` с `IdempotencyKey`. ## Требования **1. Показывать желаемое и фактическое раздельно.** `LinkPolicy` содержит `DesiredState`, `ActualState` и `LastError`. Расхождение между желаемым и фактическим — не деталь реализации, а суть системы: правило может быть заказано, но ещё не применено на узле, или примениться с ошибкой. Схлопывать оба поля в один значок «активно» нельзя. Расхождение должно быть заметно само, без вчитывания, и `LastError` показывается, когда он есть. **2. Создание — с явным подтверждением направления.** Link открывает сетевой доступ. Перед отправкой показать человеку одной строкой, что именно произойдёт: «с узла A к узлу B, протокол, порт, на N минут». Направленность — свойство модели, и перепутанные местами источник и цель дают работающее правило, открывающее доступ не туда. **3. `Reason` обязателен и осмысленный.** Он идёт в журнал и остаётся единственным следом того, зачем доступ открывали. Пустое поле или пробел не принимать. **4. Отключение — быстрое и заметное.** Это аварийный рычаг: когда он нужен, его ищут в спешке. Действие доступно из строки списка, без перехода на другую страницу, и подтверждается одним шагом. **5. `IdempotencyKey` генерируется на клиенте** и не повторяется между разными операциями. При повторной отправке той же формы, например по второму нажатию кнопки или после потери связи, ключ остаётся прежним, чтобы не создать два правила вместо одного. **6. Срок жизни виден.** Для каждого Link показать, когда он истекает, а не только `TtlMinutes`, заданный при создании. **7. Журнал событий.** Отдельный раздел со списком из `GET /events`: что произошло, с каким узлом, когда. Достаточно чтения, фильтры не требуются. **8. Ошибки сервера показывать текстом.** Если создание отклонено проверкой, оператор должен увидеть причину, а не молчаливое ничего. ## Чего не делать - не добавлять эндпоинты в Control: всё нужное существует; - не трогать выдачу кодов регистрации и вход по паролю — они уже работают; - не добавлять операций, которых нет в списке выше: удаление узлов, перезапуск служб, правка сертификатов в консоль пока не входят. ## Границы Codex ведёт `deploy/**`, релизный пайплайн и проверку релиза. **Не трогать:** `deploy/**`, `.github/workflows/**`, `tests/bootstrap/**`, `tests/release-verification/**`. Ваша область: `src/ServerMonitorManager.Control/wwwroot/**`, `tests/ServerMonitorManager.Control.Tests/**`. Правки в `src/ServerMonitorManager.Control/Program.cs` допустимы, только если без них не обойтись, — опишите зачем. ## Тесты Существующие проверки консоли должны продолжать проходить: анонимный доступ отклонён, роли `Agent` и `Automation` запрещены, ассеты отдаются из ресурсов сборки при отсутствии `wwwroot` на диске. Добавить проверку, что разметка консоли содержит элементы управления Links и раздел журнала, — по образцу существующего `WebConsoleHtmlContainsRequiredUiElementsAndWarning`. ## Критерий приёмки - из консоли можно создать Link и отключить его; - желаемое и фактическое состояние показаны раздельно, `LastError` виден при наличии; - перед созданием показано направление, порт и срок одной понятной строкой; - `Reason` обязателен, пустой не принимается; - `IdempotencyKey` генерируется клиентом и устойчив к повторной отправке; - виден момент истечения каждого Link; - есть раздел журнала событий; - ошибки сервера показываются текстом; - новых эндпоинтов в Control не появилось; - PR, CI зелёный, PR не смержен до зелёного.