server-monitor-manager/agents/_salvage-2026-08-18/smm-deliverables/pr-body-console-links.md
Ochenstarik 23eb3f5233 chore(agents): разбор рабочих папок с диска на 2026-08-18
Задания, отчёты и патчи, лежавшие в C:\Users\Ochenstarik\projects и в
домашней папке, перенесены в agents/. Разложено по агентам там, где имя
файла позволяло определить автора; остальное — в _salvage-2026-08-18/
и разбирается вручную.

Патчи в notes/salvage-2026-08-18/ — незакоммиченная работа из брошенных
рабочих копий: она существовала только на диске.

Тяжёлое (релизные архивы, инсталляторы, наборы данных) в репозиторий не
попало: оно лежит рядом, в Agent_projects/_archive и Agent_projects/_data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 14:19:54 +07:00

9.6 KiB
Raw Permalink Blame History

Реализовано создание и аварийное отключение сетевых связей (Links), раздельное отображение желаемого и фактического состояний, явное подтверждение направления сетевого доступа, обязательное обоснование (Reason), клиентская генерация IdempotencyKey, отображение сроков действия, а также раздел «Журнал событий» на базе потока GET /api/v1/control/events в соответствии с smm-antigravity-task-console-links-2026-08-18.md.

База

  • Базовая ветка: main @ 7c43977
  • Ветка: antigravity/console-links

Что сделано

  1. Раздельное отображение желаемого (DesiredState) и фактического (ActualState) состояний:

    • В таблице сетевых связей добавлены раздельные колонки «Желаемое» и «Фактическое».
    • Добавлен визуальный индикатор рассогласования (state-mismatch-badge: «⚠️ Не синхронизировано»), когда desiredState !== actualState.
    • Добавлено отображение LastError при его наличии в виде выделенного предупреждающего блока в ячейке состояния.
  2. Создание Link с явным подтверждением направления:

    • Добавлена кнопка «Создать Link» и модальное окно #create-link-modal с формой ввода:
      • Source Node ID (выбор из списка зарегистрированных узлов или ручной ввод);
      • Target Node ID (выбор из списка зарегистрированных узлов или ручной ввод);
      • Protocol (TCP / UDP);
      • Port (165535);
      • TTL (срок действия в минутах);
      • Reason (обязательное поле причины).
    • Реализован динамический блок подтверждения направления правила доступа #link-direction-summary, наглядно показывающий оператору одной строкой: Открытие доступа: с узла «<source>» к узлу «<target>», протокол <protocol>, порт <port>, на <ttl> мин..
    • Добавлена валидация различия источника и назначения (source !== target).
  3. Обязательное осмысленное поле Reason:

    • Проверяется заполненность причины на клиенте (непустая строка без пробелов до 256 символов) с понятным сообщением об ошибке оператору.
  4. Аварийное быстрое отключение Link:

    • В каждой строке таблицы Link добавлена заметная кнопка «Отключить» (.btn-danger), доступная без перехода на другие страницы.
    • Отключение подтверждается в один шаг и отправляет POST /api/v1/control/links/{id}/disable.
    • Если Link уже отключён, строка показывает нейтральный статус «Отключено».
  5. Клиентская генерация IdempotencyKey:

    • Ключ идемпотентности генерируется на клиенте с помощью crypto.randomUUID() при открытии формы создания или нажатии на отключение.
    • При повторной отправке той же формы (или при сбое сети) ключ сохраняется, предотвращая дублирование правил.
  6. Отображение срока жизни (Expiration):

    • Для каждого Link рассчитывается и выводится время до истечения (например, через 45 мин. (14:30)) либо отметка «Истёк» при завершении срока действия.
  7. Журнал событий (Event Journal):

    • Добавлен раздел «Журнал событий» (#events-section) с таблицей #events-table и счётчиком событий.
    • Консоль в реальном времени подключается к GET /api/v1/control/events (NDJSON-поток) и выводит поступающие события (время, тип события, субъект/узел, подробности payload).
    • При получении событий изменения топологии (link.*, agent.*) автоматически инициируется фоновое обновление данных дашборда.
  8. Текстовое отображение ошибок сервера:

    • Ошибки валидации или конфликтов сервера парсятся из Problem Details (detail, title, errors) и выводятся понятным текстом в модальном окне или глобальном баннере.
  9. Сохранение существующих эндпоинтов и архитектуры:

    • Новых эндпоинтов в Control не добавлялось; используются исключительно существующие API (GET/POST /api/v1/control/links, POST /api/v1/control/links/{id}/disable, GET /api/v1/control/events).

Отчёт о тестировании

1. Локальные тесты (PASS)

  • Сборка: dotnet build — 0 ошибок.
  • Набор тестов: dotnet test158 пройденных тестов (включая обновленный WebConsoleHtmlContainsRequiredUiElementsAndWarning и новый WebConsoleProvidesLinkManagementAndEventsJournal):
    • WebConsoleHtmlContainsRequiredUiElementsAndWarning — проверка наличия всех элементов управления Link (кнопка создания, модальное окно, поля формы, подсказка направления, таблицы и счётчики);
    • WebConsoleProvidesLinkManagementAndEventsJournal — проверка раздельных колонок Desired/Actual/LastError, карточки подтверждения направления и раздела журнала событий;
    • EmbeddedAssetsAreServedWhenDiskWebRootIsMissing — проверка отдачи обновленных встроенных HTML/CSS/JS ресурсов сборки;
    • AnonymousAccessToWebConsoleRoutesIsRejectedWithUnauthorized — анонимный доступ отклонён;
    • AgentRoleIsForbiddenFromWebConsole и AutomationRoleIsForbiddenFromWebConsole — роли Agent и Automation запрещены.

2. CI Workflows (PASS, 100% зелёные)

3. Границы изменений

  • git diff --name-only origin/main:
    • src/ServerMonitorManager.Control/wwwroot/app.js
    • src/ServerMonitorManager.Control/wwwroot/index.html
    • src/ServerMonitorManager.Control/wwwroot/style.css
    • tests/ServerMonitorManager.Control.Tests/WebConsoleTests.cs
  • Файлы deploy/**, релизные workflow и bootstrap-тесты не затрагивались.