From fe0ca3fa46996f4ead840f204d141a09c683d02f Mon Sep 17 00:00:00 2001 From: Denozordec Date: Thu, 8 Oct 2026 21:48:30 +0700 Subject: [PATCH] =?UTF-8?q?chore(test):=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=B8=D1=82=D1=8C=20=D1=80=D0=B5=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D1=83=D1=8E=20=D1=81=D0=B2=D1=8F=D0=B7=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=8C=20WireGuard=20=D0=B8=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80?= =?UTF-8?q?=D1=84=D0=B5=D0=B9=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ux-ui-external-acceptance.md | 14 +- docs/ux-ui-plan.md | 4 +- docs/ux-ui-progress.md | 16 +- docs/ux-ui-stage-12.md | 14 +- docs/ux-ui-test-server.md | 12 + .../browser-wg-real-2026-10-08.json | 101 ++++++++ .../wg-first-cleanup-recovery-2026-10-08.json | 19 ++ .../wg-real-first-attempt-2026-10-08.json | 197 +++++++++++++++ .../wg-real-lifecycle-2026-10-08.json | 233 ++++++++++++++++++ .../wg-real-server1-dark-320-2026-10-08.png | Bin 0 -> 12417 bytes .../wg-real-server1-light-320-2026-10-08.png | Bin 0 -> 12183 bytes .../wg-real-server2-dark-320-2026-10-08.png | Bin 0 -> 12652 bytes .../wg-real-server2-light-320-2026-10-08.png | Bin 0 -> 12467 bytes 13 files changed, 604 insertions(+), 6 deletions(-) create mode 100644 docs/ux-ui/acceptance/browser-wg-real-2026-10-08.json create mode 100644 docs/ux-ui/acceptance/wg-first-cleanup-recovery-2026-10-08.json create mode 100644 docs/ux-ui/acceptance/wg-real-first-attempt-2026-10-08.json create mode 100644 docs/ux-ui/acceptance/wg-real-lifecycle-2026-10-08.json create mode 100644 docs/ux-ui/screens/wg-real-server1-dark-320-2026-10-08.png create mode 100644 docs/ux-ui/screens/wg-real-server1-light-320-2026-10-08.png create mode 100644 docs/ux-ui/screens/wg-real-server2-dark-320-2026-10-08.png create mode 100644 docs/ux-ui/screens/wg-real-server2-light-320-2026-10-08.png diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index ab64a272..247ba200 100644 --- a/docs/ux-ui-external-acceptance.md +++ b/docs/ux-ui-external-acceptance.md @@ -1,6 +1,6 @@ # UX/UI: протокол внешней приёмки 12.5 -Статус на2026-10-08: backendbd3f996/frontendfd521f6, backend healthy. Мобильная GRE форма и native сохранение на обоих CHR приняты в12.5.57. Устойчивость меню GRE при live refresh на обоих CHR принята в12.5.55. GRE peer metadata и реальный lifecycle/API/UI/двусторонний Ping подтверждены в12.5.53. Browser retry/checkpoint на реальном HTTP/PG принят в границах12.5.43–45; Telegram sender responses подменены, реальная доставка не проверена. PG-1/2/3/4/5 приняты в описанных границах, PG-6 integrated для одного isolated instance, PG-7 real JWT/processcounts и browser restore passed. PG-8 real PG/native и browser unknown→history done приняты с fault injection после настоящего COMMIT. ROS-8/9 real API/SQL/native приняты в границах12.5.23; browser pair/duration change и delete приняты в12.5.24. ROS-2 authentication failure принят в12.5.25. PortalSSO, физический TCP disconnect, мультиэкземпляры и остальные ROS/Q/интеграции остаются открытыми. [Паспорт](ux-ui-test-server.md), [журнал](ux-ui-progress.md). +Статус на2026-10-08: backendbd3f996/frontendfd521f6, backend healthy. Мобильная GRE форма и native сохранение на обоих CHR приняты в12.5.57. WireGuard handshake/короткий Ping/native API/read-only UI приняты в границах12.5.58; обычное удаление интерфейса с IP ещё не проверено. Устойчивость меню GRE при live refresh на обоих CHR принята в12.5.55. GRE peer metadata и реальный lifecycle/API/UI/двусторонний Ping подтверждены в12.5.53. Browser retry/checkpoint на реальном HTTP/PG принят в границах12.5.43–45; Telegram sender responses подменены, реальная доставка не проверена. PG-1/2/3/4/5 приняты в описанных границах, PG-6 integrated для одного isolated instance, PG-7 real JWT/processcounts и browser restore passed. PG-8 real PG/native и browser unknown→history done приняты с fault injection после настоящего COMMIT. ROS-8/9 real API/SQL/native приняты в границах12.5.23; browser pair/duration change и delete приняты в12.5.24. ROS-2 authentication failure принят в12.5.25. PortalSSO, физический TCP disconnect, мультиэкземпляры и остальные ROS/Q/интеграции остаются открытыми. [Паспорт](ux-ui-test-server.md), [журнал](ux-ui-progress.md). ## Паспорт стенда @@ -417,3 +417,15 @@ DELETE200/200, own интерфейсы/IP и connected routes удалены; Скриншоты320px: [CHR1 dark](ux-ui/screens/gre-mobile-real-server1-dark-320-2026-10-08.png), [CHR1 light](ux-ui/screens/gre-mobile-real-server1-light-320-2026-10-08.png), [CHR2 dark](ux-ui/screens/gre-mobile-real-server2-dark-320-2026-10-08.png), [CHR2 light](ux-ui/screens/gre-mobile-real-server2-light-320-2026-10-08.png). CHR1 dark и CHR2 light визуально просмотрены: внутренние IP целиком видны. [Smoke](ux-ui/acceptance/deploy-browser-fd521f6-2026-10-08.json): dashboard/servers/uptime/settings/filters/alerts200,320px fit, JS/API errors0. DELETE200/200, собственные GRE/IP/connected routes удалены; выбранные GRE/IP/routes/IPv4 Firewall поля совпали с baseline, CHR1 — одно повторное чтение маршрутов через250ms. Эфемерный контейнер удалён; остались три основные Compose-службы. GRE revisions намеренно сохранены как история операций. Следующий12.5.58 — реальная собственная WireGuard пара, API/native/UI, handshake/связность, очистка и baseline; private/preshared keys не включать в публичные отчёты. Требование пользователя о настоящих VPN объектах сохраняется. Telegram/Portal/multi-instance и другие внешние ограничения остаются открытыми. Локальный коммит без push. + +## 12.5.58 — настоящая WireGuard пара, handshake и UI (2026-10-08) + +[Итоговый реальный lifecycle](ux-ui/acceptance/wg-real-lifecycle-2026-10-08.json): собственная пара mm-acceptance-wg-1791470702451 на двух CHR, UDP51879 и198.18.255.240/30 проверены на коллизии/пересечения. POST interfaces201/201 создали интерфейсы и IP; native чтение подтвердило автоматические ключи и адреса, POST peers201/201 — связь с публичным ключом другого устройства. Ключи проверялись в памяти и не записывались в публичные артефакты. Allowed адреса ограничены IP другого конца /32, persistent keepalive5s. Default routes/Firewall не менялись. Параметры и смысл last-handshake сверены с [официальной документацией MikroTik](https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard). + +На обоих peers появился native handshake и RX>0; двусторонний Ping3/3,0%loss, около54–56ms. PATCH MTU1380 и возврат1420 подтверждены native чтением. Каталог приложения совпал с адресами/peers/handshake и не содержал privateKey по умолчанию. Это короткая проверка защищённой WireGuard связности; throughput, RBAC, interrupted mutation, экспорт и import не проверены. + +[Production browser](ux-ui/acceptance/browser-wg-real-2026-10-08.json): два CHR × две темы,1280/320px без HTTP mocks. В деталях видны own peer name, Allowed IPs, endpoint, handshake и известные RX/TX; server/interface URL и вкладка peers пережили reload, page overflow отсутствует. На320px длинные имя и CIDR переносятся; исходная таблица сохраняет собственный горизонтальный scroll. Создание/изменение/удаление через UI не проверялись. JS/API errors0. Скриншоты: [CHR1 dark](ux-ui/screens/wg-real-server1-dark-320-2026-10-08.png), [CHR1 light](ux-ui/screens/wg-real-server1-light-320-2026-10-08.png), [CHR2 dark](ux-ui/screens/wg-real-server2-dark-320-2026-10-08.png), [CHR2 light](ux-ui/screens/wg-real-server2-light-320-2026-10-08.png); итоговыйCHR2 light просмотрен. Первый browser locator одновременно находил sr-only и родительскую подпись handshake, уточнение локатора дало успешный проход без изменения продукта. + +[Первый проход](ux-ui/acceptance/wg-real-first-attempt-2026-10-08.json) подтвердил связность/UI, но cleanup harness получил DELETE400: Content-Type application/json был передан без тела. Это ошибка harness, не доказательство ошибки приложения. [Восстановительная очистка](ux-ui/acceptance/wg-first-cleanup-recovery-2026-10-08.json) через правильные DELETE проверила ownership comment/name и отсутствие own interfaces/peers/IP/routes. Baseline первого прохода был только в памяти и после выхода потерян; точная сверка первого baseline не заявляется. Harness исправлен, создана новая пара и повторён полный lifecycle/browser; итоговый exit0 и все выбранные baseline поля совпали. + +В финальном cleanup собственные peers удалены API200/200, собственные IP явно удалены native API до удаления interfaces API200/200. Автоматическая очистка IP/peers при обычном удалении интерфейса НЕ проверена и остаётся следующим12.5.59. WireGuard/IP/routes/IPv4 Firewall выбранные настройки совпали с baseline; эфемерный контейнер удалён, работают только три основные Compose-службы. DB controls до/после servers2/speedHistory9/retention14/migrations9 совпали, backend healthy. WG revisions намеренно сохранены как история операций. Runtime backendbd3f996/frontendfd521f6 не менялся. Telegram/Portal/multi-instance и остальные внешние ограничения остаются открытыми. Локальный коммит без push. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 216eb6a7..0f5b7c80 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,12 +1,12 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-08: 12.5.57 развернул frontendfd521f6, backendbd3f996 healthy. Мобильная GRE форма подтверждена без HTTP mocks на новой собственной паре CHR: две темы/320/640/1280px, полный native IPv4/CIDR, Tab, меню refresh и сохранение PATCH200/200 с независимым чтением RouterOS. Ping3/3 в обе стороны; own GRE/IP удалены, выбранный baseline и DB controls совпали. Smoke6 экранов passed. Следующий12.5.58 — настоящая WireGuard пара: API/native/UI, handshake/связность и очистка собственных объектов; секреты в отчёты не включать. Этап12.5 открыт. +Актуальное продолжение 2026-10-08: 12.5.58 подтвердил настоящую WireGuard пару на обоих CHR: API/native keys association, handshake/RX, Ping3/3, MTU и UI в двух темах/1280/320px, URL interface/server/tab/reload. Итоговый harness exit0, выбранный WG/peers/IP/routes/Firewall baseline и DB controls совпали; own объекты удалены. Первый DELETE harness400 из-за JSON header без тела исправлен, recovery и повторный полный проход сохранены отдельно. Runtime backendbd3f996/frontendfd521f6 healthy. Следующий12.5.59 — удалить собственный WireGuard интерфейс с peer/IP через обычный UI/API и проверить остаточные объекты; в58 IP удалялись явно. Этап12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-08. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. ## Актуальная точка продолжения — 2026-10-08 -Этапы0–11 завершены в описанных локальных границах. Этап12 открыт. На тестовом сервере161.104.46.222 работают backendbd3f996/frontendfd521f6 и два CHR. Внешние проверки подтвердили PG backup/restore/rollback, остановку фоновой работы для одного экземпляра, API JWT/RBAC и браузерные состояния восстановления. Native TCP/UDP speed, история и UI проверены в границах журнала; доступ ко второму CHR восстановлен пользователем. Очередь Telegram проверена на реальном PG: dedupe, конкурентный claim, retry/version, ошибки сохранения и неопределённый исход; ответы отправителя подменялись, реальной доставки это не доказывает. Блоки12.5.43–45 подтвердили browser retry/checkpoint и развернули понятное пояснение HTTP500. 12.5.46 подтвердил browser JWT/RBAC очереди на реальном HTTP/PG; 12.5.47 подтвердил изоляцию checkpoint при смене двух реальных HTTP/PG источников в конфигурации local; 12.5.48 подтвердил scoped axe/клавиатуру в обеих темах и320px; 12.5.49 собрал Q-матрицу и подтвердил отсутствие настройки Telegram; 12.5.50 подтвердил GET-only инвентаризацию: VPN/BGP/OSPF пусты, роли home-router/home-router; По уточнению пользователя12.5.51 создал реальные GRE туннели и подтвердил lifecycle/связность; обнаружена потеря peer IP, 12.5.52 локально исправил сохранение peer metadata, профильные проверки passed; 12.5.53 развернул исправление и подтвердил его на реальной GRE паре/API/UI; 12.5.54 локально исправил устойчивость меню GRE, профильные проверки passed; 12.5.55 развернул frontend731803b и подтвердил устойчивость меню на реальной GRE паре; 12.5.56 локально адаптировал внутренние IP поля GRE для320px, обе темы и профильные проверки passed; 12.5.57 развернул frontendfd521f6 и подтвердил мобильную GRE форму на реальной паре CHR; следующий12.5.58 — собственная настоящая WireGuard пара с handshake/связностью и очисткой. Реальная Telegram доставка, Portal SSO, физический TCP disconnect, multi-instance и остальные профильные сетевые сценарии остаются открытыми. [Протокол](ux-ui-external-acceptance.md) и [журнал](ux-ui-stage-12.md) содержат доказательства и ограничения. +Этапы0–11 завершены в описанных локальных границах. Этап12 открыт. На тестовом сервере161.104.46.222 работают backendbd3f996/frontendfd521f6 и два CHR. Внешние проверки подтвердили PG backup/restore/rollback, остановку фоновой работы для одного экземпляра, API JWT/RBAC и браузерные состояния восстановления. Native TCP/UDP speed, история и UI проверены в границах журнала; доступ ко второму CHR восстановлен пользователем. Очередь Telegram проверена на реальном PG: dedupe, конкурентный claim, retry/version, ошибки сохранения и неопределённый исход; ответы отправителя подменялись, реальной доставки это не доказывает. Блоки12.5.43–45 подтвердили browser retry/checkpoint и развернули понятное пояснение HTTP500. 12.5.46 подтвердил browser JWT/RBAC очереди на реальном HTTP/PG; 12.5.47 подтвердил изоляцию checkpoint при смене двух реальных HTTP/PG источников в конфигурации local; 12.5.48 подтвердил scoped axe/клавиатуру в обеих темах и320px; 12.5.49 собрал Q-матрицу и подтвердил отсутствие настройки Telegram; 12.5.50 подтвердил GET-only инвентаризацию: VPN/BGP/OSPF пусты, роли home-router/home-router; По уточнению пользователя12.5.51 создал реальные GRE туннели и подтвердил lifecycle/связность; обнаружена потеря peer IP, 12.5.52 локально исправил сохранение peer metadata, профильные проверки passed; 12.5.53 развернул исправление и подтвердил его на реальной GRE паре/API/UI; 12.5.54 локально исправил устойчивость меню GRE, профильные проверки passed; 12.5.55 развернул frontend731803b и подтвердил устойчивость меню на реальной GRE паре; 12.5.56 локально адаптировал внутренние IP поля GRE для320px, обе темы и профильные проверки passed; 12.5.57 развернул frontendfd521f6 и подтвердил мобильную GRE форму на реальной паре CHR; 12.5.58 подтвердил настоящую WireGuard пару, handshake/Ping/native/UI и финальную очистку; следующий12.5.59 — обычное удаление WireGuard интерфейса с peer/IP через UI/API, проверка оставшихся объектов. Реальная Telegram доставка, Portal SSO, физический TCP disconnect, multi-instance и остальные профильные сетевые сценарии остаются открытыми. [Протокол](ux-ui-external-acceptance.md) и [журнал](ux-ui-stage-12.md) содержат доказательства и ограничения. Выполненные внешние сценарии не заменяют приёмку оставшихся интеграций и условий эксплуатации. Датированные продолжения ниже — история; точный следующий шаг указан в начале [журнала](ux-ui-progress.md). diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index d9300930..6f70cf43 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-08: 12.5.57 развернул frontendfd521f6, backendbd3f996 healthy. Мобильная GRE форма подтверждена без HTTP mocks на новой собственной паре CHR: две темы/320/640/1280px, полный native IPv4/CIDR, Tab, меню refresh и сохранение PATCH200/200 с независимым чтением RouterOS. Ping3/3 в обе стороны; own GRE/IP удалены, выбранный baseline и DB controls совпали. Smoke6 экранов passed. Следующий12.5.58 — настоящая WireGuard пара: API/native/UI, handshake/связность и очистка собственных объектов; секреты в отчёты не включать. Этап12.5 открыт. +Актуальное продолжение 2026-10-08: 12.5.58 подтвердил настоящую WireGuard пару на обоих CHR: API/native keys association, handshake/RX, Ping3/3, MTU и UI в двух темах/1280/320px, URL interface/server/tab/reload. Итоговый harness exit0, выбранный WG/peers/IP/routes/Firewall baseline и DB controls совпали; own объекты удалены. Первый DELETE harness400 из-за JSON header без тела исправлен, recovery и повторный полный проход сохранены отдельно. Runtime backendbd3f996/frontendfd521f6 healthy. Следующий12.5.59 — удалить собственный WireGuard интерфейс с peer/IP через обычный UI/API и проверить остаточные объекты; в58 IP удалялись явно. Этап12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -34,7 +34,19 @@ | 10 | Маршрутизация, диагностика, карта и терминал | Завершён в границах локальной приёмки 2026-10-01; блоки 10.1–10.71, внешние ограничения в 10.71 | | 11А | Пользователи, контейнеры, сертификаты и резервные копии | Завершён в границах локальной приёмки 2026-10-01; 11А.1–11А.33, внешние ограничения в 11А.33 | | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | -| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–57 и ограничения ниже. Runtime backendbd3f996/frontendfd521f6. | +| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–58 и ограничения ниже. Runtime backendbd3f996/frontendfd521f6. | + +## 12.5.58 — настоящая WireGuard пара, handshake и UI (2026-10-08) + +[Итоговый реальный lifecycle](ux-ui/acceptance/wg-real-lifecycle-2026-10-08.json): собственная пара mm-acceptance-wg-1791470702451 на двух CHR, UDP51879 и198.18.255.240/30 проверены на коллизии/пересечения. POST interfaces201/201 создали интерфейсы и IP; native чтение подтвердило автоматические ключи и адреса, POST peers201/201 — связь с публичным ключом другого устройства. Ключи проверялись в памяти и не записывались в публичные артефакты. Allowed адреса ограничены IP другого конца /32, persistent keepalive5s. Default routes/Firewall не менялись. Параметры и смысл last-handshake сверены с [официальной документацией MikroTik](https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard). + +На обоих peers появился native handshake и RX>0; двусторонний Ping3/3,0%loss, около54–56ms. PATCH MTU1380 и возврат1420 подтверждены native чтением. Каталог приложения совпал с адресами/peers/handshake и не содержал privateKey по умолчанию. Это короткая проверка защищённой WireGuard связности; throughput, RBAC, interrupted mutation, экспорт и import не проверены. + +[Production browser](ux-ui/acceptance/browser-wg-real-2026-10-08.json): два CHR × две темы,1280/320px без HTTP mocks. В деталях видны own peer name, Allowed IPs, endpoint, handshake и известные RX/TX; server/interface URL и вкладка peers пережили reload, page overflow отсутствует. На320px длинные имя и CIDR переносятся; исходная таблица сохраняет собственный горизонтальный scroll. Создание/изменение/удаление через UI не проверялись. JS/API errors0. Скриншоты: [CHR1 dark](ux-ui/screens/wg-real-server1-dark-320-2026-10-08.png), [CHR1 light](ux-ui/screens/wg-real-server1-light-320-2026-10-08.png), [CHR2 dark](ux-ui/screens/wg-real-server2-dark-320-2026-10-08.png), [CHR2 light](ux-ui/screens/wg-real-server2-light-320-2026-10-08.png); итоговыйCHR2 light просмотрен. Первый browser locator одновременно находил sr-only и родительскую подпись handshake, уточнение локатора дало успешный проход без изменения продукта. + +[Первый проход](ux-ui/acceptance/wg-real-first-attempt-2026-10-08.json) подтвердил связность/UI, но cleanup harness получил DELETE400: Content-Type application/json был передан без тела. Это ошибка harness, не доказательство ошибки приложения. [Восстановительная очистка](ux-ui/acceptance/wg-first-cleanup-recovery-2026-10-08.json) через правильные DELETE проверила ownership comment/name и отсутствие own interfaces/peers/IP/routes. Baseline первого прохода был только в памяти и после выхода потерян; точная сверка первого baseline не заявляется. Harness исправлен, создана новая пара и повторён полный lifecycle/browser; итоговый exit0 и все выбранные baseline поля совпали. + +В финальном cleanup собственные peers удалены API200/200, собственные IP явно удалены native API до удаления interfaces API200/200. Автоматическая очистка IP/peers при обычном удалении интерфейса НЕ проверена и остаётся следующим12.5.59. WireGuard/IP/routes/IPv4 Firewall выбранные настройки совпали с baseline; эфемерный контейнер удалён, работают только три основные Compose-службы. DB controls до/после servers2/speedHistory9/retention14/migrations9 совпали, backend healthy. WG revisions намеренно сохранены как история операций. Runtime backendbd3f996/frontendfd521f6 не менялся. Telegram/Portal/multi-instance и остальные внешние ограничения остаются открытыми. Локальный коммит без push. ## 12.5.57 — развёртывание мобильной формы и реальная GRE приёмка (2026-10-08) diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index d5818ce8..b9f5ca14 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1,6 +1,6 @@ # Этап 12: итоговая приёмка UX/UI -Актуальное продолжение 2026-10-08: 12.5.57 развернул frontendfd521f6, backendbd3f996 healthy. Мобильная GRE форма подтверждена без HTTP mocks на новой собственной паре CHR: две темы/320/640/1280px, полный native IPv4/CIDR, Tab, меню refresh и сохранение PATCH200/200 с независимым чтением RouterOS. Ping3/3 в обе стороны; own GRE/IP удалены, выбранный baseline и DB controls совпали. Smoke6 экранов passed. Следующий12.5.58 — настоящая WireGuard пара: API/native/UI, handshake/связность и очистка собственных объектов; секреты в отчёты не включать. Этап12.5 открыт. +Актуальное продолжение 2026-10-08: 12.5.58 подтвердил настоящую WireGuard пару на обоих CHR: API/native keys association, handshake/RX, Ping3/3, MTU и UI в двух темах/1280/320px, URL interface/server/tab/reload. Итоговый harness exit0, выбранный WG/peers/IP/routes/Firewall baseline и DB controls совпали; own объекты удалены. Первый DELETE harness400 из-за JSON header без тела исправлен, recovery и повторный полный проход сохранены отдельно. Runtime backendbd3f996/frontendfd521f6 healthy. Следующий12.5.59 — удалить собственный WireGuard интерфейс с peer/IP через обычный UI/API и проверить остаточные объекты; в58 IP удалялись явно. Этап12.5 открыт. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -1582,3 +1582,15 @@ DELETE200/200, own интерфейсы/IP и connected routes удалены; Скриншоты320px: [CHR1 dark](ux-ui/screens/gre-mobile-real-server1-dark-320-2026-10-08.png), [CHR1 light](ux-ui/screens/gre-mobile-real-server1-light-320-2026-10-08.png), [CHR2 dark](ux-ui/screens/gre-mobile-real-server2-dark-320-2026-10-08.png), [CHR2 light](ux-ui/screens/gre-mobile-real-server2-light-320-2026-10-08.png). CHR1 dark и CHR2 light визуально просмотрены: внутренние IP целиком видны. [Smoke](ux-ui/acceptance/deploy-browser-fd521f6-2026-10-08.json): dashboard/servers/uptime/settings/filters/alerts200,320px fit, JS/API errors0. DELETE200/200, собственные GRE/IP/connected routes удалены; выбранные GRE/IP/routes/IPv4 Firewall поля совпали с baseline, CHR1 — одно повторное чтение маршрутов через250ms. Эфемерный контейнер удалён; остались три основные Compose-службы. GRE revisions намеренно сохранены как история операций. Следующий12.5.58 — реальная собственная WireGuard пара, API/native/UI, handshake/связность, очистка и baseline; private/preshared keys не включать в публичные отчёты. Требование пользователя о настоящих VPN объектах сохраняется. Telegram/Portal/multi-instance и другие внешние ограничения остаются открытыми. Локальный коммит без push. + +## 12.5.58 — настоящая WireGuard пара, handshake и UI (2026-10-08) + +[Итоговый реальный lifecycle](ux-ui/acceptance/wg-real-lifecycle-2026-10-08.json): собственная пара mm-acceptance-wg-1791470702451 на двух CHR, UDP51879 и198.18.255.240/30 проверены на коллизии/пересечения. POST interfaces201/201 создали интерфейсы и IP; native чтение подтвердило автоматические ключи и адреса, POST peers201/201 — связь с публичным ключом другого устройства. Ключи проверялись в памяти и не записывались в публичные артефакты. Allowed адреса ограничены IP другого конца /32, persistent keepalive5s. Default routes/Firewall не менялись. Параметры и смысл last-handshake сверены с [официальной документацией MikroTik](https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard). + +На обоих peers появился native handshake и RX>0; двусторонний Ping3/3,0%loss, около54–56ms. PATCH MTU1380 и возврат1420 подтверждены native чтением. Каталог приложения совпал с адресами/peers/handshake и не содержал privateKey по умолчанию. Это короткая проверка защищённой WireGuard связности; throughput, RBAC, interrupted mutation, экспорт и import не проверены. + +[Production browser](ux-ui/acceptance/browser-wg-real-2026-10-08.json): два CHR × две темы,1280/320px без HTTP mocks. В деталях видны own peer name, Allowed IPs, endpoint, handshake и известные RX/TX; server/interface URL и вкладка peers пережили reload, page overflow отсутствует. На320px длинные имя и CIDR переносятся; исходная таблица сохраняет собственный горизонтальный scroll. Создание/изменение/удаление через UI не проверялись. JS/API errors0. Скриншоты: [CHR1 dark](ux-ui/screens/wg-real-server1-dark-320-2026-10-08.png), [CHR1 light](ux-ui/screens/wg-real-server1-light-320-2026-10-08.png), [CHR2 dark](ux-ui/screens/wg-real-server2-dark-320-2026-10-08.png), [CHR2 light](ux-ui/screens/wg-real-server2-light-320-2026-10-08.png); итоговыйCHR2 light просмотрен. Первый browser locator одновременно находил sr-only и родительскую подпись handshake, уточнение локатора дало успешный проход без изменения продукта. + +[Первый проход](ux-ui/acceptance/wg-real-first-attempt-2026-10-08.json) подтвердил связность/UI, но cleanup harness получил DELETE400: Content-Type application/json был передан без тела. Это ошибка harness, не доказательство ошибки приложения. [Восстановительная очистка](ux-ui/acceptance/wg-first-cleanup-recovery-2026-10-08.json) через правильные DELETE проверила ownership comment/name и отсутствие own interfaces/peers/IP/routes. Baseline первого прохода был только в памяти и после выхода потерян; точная сверка первого baseline не заявляется. Harness исправлен, создана новая пара и повторён полный lifecycle/browser; итоговый exit0 и все выбранные baseline поля совпали. + +В финальном cleanup собственные peers удалены API200/200, собственные IP явно удалены native API до удаления interfaces API200/200. Автоматическая очистка IP/peers при обычном удалении интерфейса НЕ проверена и остаётся следующим12.5.59. WireGuard/IP/routes/IPv4 Firewall выбранные настройки совпали с baseline; эфемерный контейнер удалён, работают только три основные Compose-службы. DB controls до/после servers2/speedHistory9/retention14/migrations9 совпали, backend healthy. WG revisions намеренно сохранены как история операций. Runtime backendbd3f996/frontendfd521f6 не менялся. Telegram/Portal/multi-instance и остальные внешние ограничения остаются открытыми. Локальный коммит без push. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index c7d1a90d..6cd65367 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -425,3 +425,15 @@ DELETE200/200, own интерфейсы/IP и connected routes удалены; Скриншоты320px: [CHR1 dark](ux-ui/screens/gre-mobile-real-server1-dark-320-2026-10-08.png), [CHR1 light](ux-ui/screens/gre-mobile-real-server1-light-320-2026-10-08.png), [CHR2 dark](ux-ui/screens/gre-mobile-real-server2-dark-320-2026-10-08.png), [CHR2 light](ux-ui/screens/gre-mobile-real-server2-light-320-2026-10-08.png). CHR1 dark и CHR2 light визуально просмотрены: внутренние IP целиком видны. [Smoke](ux-ui/acceptance/deploy-browser-fd521f6-2026-10-08.json): dashboard/servers/uptime/settings/filters/alerts200,320px fit, JS/API errors0. DELETE200/200, собственные GRE/IP/connected routes удалены; выбранные GRE/IP/routes/IPv4 Firewall поля совпали с baseline, CHR1 — одно повторное чтение маршрутов через250ms. Эфемерный контейнер удалён; остались три основные Compose-службы. GRE revisions намеренно сохранены как история операций. Следующий12.5.58 — реальная собственная WireGuard пара, API/native/UI, handshake/связность, очистка и baseline; private/preshared keys не включать в публичные отчёты. Требование пользователя о настоящих VPN объектах сохраняется. Telegram/Portal/multi-instance и другие внешние ограничения остаются открытыми. Локальный коммит без push. + +## 12.5.58 — настоящая WireGuard пара, handshake и UI (2026-10-08) + +[Итоговый реальный lifecycle](ux-ui/acceptance/wg-real-lifecycle-2026-10-08.json): собственная пара mm-acceptance-wg-1791470702451 на двух CHR, UDP51879 и198.18.255.240/30 проверены на коллизии/пересечения. POST interfaces201/201 создали интерфейсы и IP; native чтение подтвердило автоматические ключи и адреса, POST peers201/201 — связь с публичным ключом другого устройства. Ключи проверялись в памяти и не записывались в публичные артефакты. Allowed адреса ограничены IP другого конца /32, persistent keepalive5s. Default routes/Firewall не менялись. Параметры и смысл last-handshake сверены с [официальной документацией MikroTik](https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard). + +На обоих peers появился native handshake и RX>0; двусторонний Ping3/3,0%loss, около54–56ms. PATCH MTU1380 и возврат1420 подтверждены native чтением. Каталог приложения совпал с адресами/peers/handshake и не содержал privateKey по умолчанию. Это короткая проверка защищённой WireGuard связности; throughput, RBAC, interrupted mutation, экспорт и import не проверены. + +[Production browser](ux-ui/acceptance/browser-wg-real-2026-10-08.json): два CHR × две темы,1280/320px без HTTP mocks. В деталях видны own peer name, Allowed IPs, endpoint, handshake и известные RX/TX; server/interface URL и вкладка peers пережили reload, page overflow отсутствует. На320px длинные имя и CIDR переносятся; исходная таблица сохраняет собственный горизонтальный scroll. Создание/изменение/удаление через UI не проверялись. JS/API errors0. Скриншоты: [CHR1 dark](ux-ui/screens/wg-real-server1-dark-320-2026-10-08.png), [CHR1 light](ux-ui/screens/wg-real-server1-light-320-2026-10-08.png), [CHR2 dark](ux-ui/screens/wg-real-server2-dark-320-2026-10-08.png), [CHR2 light](ux-ui/screens/wg-real-server2-light-320-2026-10-08.png); итоговыйCHR2 light просмотрен. Первый browser locator одновременно находил sr-only и родительскую подпись handshake, уточнение локатора дало успешный проход без изменения продукта. + +[Первый проход](ux-ui/acceptance/wg-real-first-attempt-2026-10-08.json) подтвердил связность/UI, но cleanup harness получил DELETE400: Content-Type application/json был передан без тела. Это ошибка harness, не доказательство ошибки приложения. [Восстановительная очистка](ux-ui/acceptance/wg-first-cleanup-recovery-2026-10-08.json) через правильные DELETE проверила ownership comment/name и отсутствие own interfaces/peers/IP/routes. Baseline первого прохода был только в памяти и после выхода потерян; точная сверка первого baseline не заявляется. Harness исправлен, создана новая пара и повторён полный lifecycle/browser; итоговый exit0 и все выбранные baseline поля совпали. + +В финальном cleanup собственные peers удалены API200/200, собственные IP явно удалены native API до удаления interfaces API200/200. Автоматическая очистка IP/peers при обычном удалении интерфейса НЕ проверена и остаётся следующим12.5.59. WireGuard/IP/routes/IPv4 Firewall выбранные настройки совпали с baseline; эфемерный контейнер удалён, работают только три основные Compose-службы. DB controls до/после servers2/speedHistory9/retention14/migrations9 совпали, backend healthy. WG revisions намеренно сохранены как история операций. Runtime backendbd3f996/frontendfd521f6 не менялся. Telegram/Portal/multi-instance и остальные внешние ограничения остаются открытыми. Локальный коммит без push. diff --git a/docs/ux-ui/acceptance/browser-wg-real-2026-10-08.json b/docs/ux-ui/acceptance/browser-wg-real-2026-10-08.json new file mode 100644 index 00000000..69b59839 --- /dev/null +++ b/docs/ux-ui/acceptance/browser-wg-real-2026-10-08.json @@ -0,0 +1,101 @@ +{ + "date": "2026-10-08", + "backendSource": "bd3f996", + "frontendSource": "fd521f6", + "name": "mm-acceptance-wg-1791470702451", + "httpMocks": false, + "actualCreatedWireguard": true, + "cases": [ + { + "serverId": 1, + "theme": "dark", + "widths": [ + { + "width": 1280, + "noPageOverflow": true, + "peerDetailsReadable": true + }, + { + "width": 320, + "noPageOverflow": true, + "peerDetailsReadable": true + } + ], + "interfaceContextPreserved": true, + "peersTabReload": true, + "nativeAllowedIpsAndEndpoint": true, + "handshakeVisible": true, + "countersKnown": true + }, + { + "serverId": 1, + "theme": "light", + "widths": [ + { + "width": 1280, + "noPageOverflow": true, + "peerDetailsReadable": true + }, + { + "width": 320, + "noPageOverflow": true, + "peerDetailsReadable": true + } + ], + "interfaceContextPreserved": true, + "peersTabReload": true, + "nativeAllowedIpsAndEndpoint": true, + "handshakeVisible": true, + "countersKnown": true + }, + { + "serverId": 2, + "theme": "dark", + "widths": [ + { + "width": 1280, + "noPageOverflow": true, + "peerDetailsReadable": true + }, + { + "width": 320, + "noPageOverflow": true, + "peerDetailsReadable": true + } + ], + "interfaceContextPreserved": true, + "peersTabReload": true, + "nativeAllowedIpsAndEndpoint": true, + "handshakeVisible": true, + "countersKnown": true + }, + { + "serverId": 2, + "theme": "light", + "widths": [ + { + "width": 1280, + "noPageOverflow": true, + "peerDetailsReadable": true + }, + { + "width": 320, + "noPageOverflow": true, + "peerDetailsReadable": true + } + ], + "interfaceContextPreserved": true, + "peersTabReload": true, + "nativeAllowedIpsAndEndpoint": true, + "handshakeVisible": true, + "countersKnown": true + } + ], + "pageErrors": [], + "badApiResponses": [], + "limits": [ + "Real API-created own pair; UI read/context/details verified, no UI create/export/delete tested", + "Keys omitted from report; screenshot shows own peer name instead of public key", + "Handshake age changes during polling; tested as present, not a fixed timestamp" + ] +} diff --git a/docs/ux-ui/acceptance/wg-first-cleanup-recovery-2026-10-08.json b/docs/ux-ui/acceptance/wg-first-cleanup-recovery-2026-10-08.json new file mode 100644 index 00000000..53706f4f --- /dev/null +++ b/docs/ux-ui/acceptance/wg-first-cleanup-recovery-2026-10-08.json @@ -0,0 +1,19 @@ +{ + "date": "2026-10-08", + "name": "mm-acceptance-wg-1791470457304", + "results": [ + { + "serverId": 1, + "ownInterfacePeerIpRouteAbsent": true + }, + { + "serverId": 2, + "ownInterfacePeerIpRouteAbsent": true + } + ], + "keysOmitted": true, + "limits": [ + "Recovery verified own objects absent; original in-memory baseline was lost after harness exit", + "Full selected baseline will be checked by a fresh complete run" + ] +} diff --git a/docs/ux-ui/acceptance/wg-real-first-attempt-2026-10-08.json b/docs/ux-ui/acceptance/wg-real-first-attempt-2026-10-08.json new file mode 100644 index 00000000..9598c890 --- /dev/null +++ b/docs/ux-ui/acceptance/wg-real-first-attempt-2026-10-08.json @@ -0,0 +1,197 @@ +{ + "date": "2026-10-08", + "backendSource": "bd3f996", + "frontendSource": "fd521f6", + "name": "mm-acceptance-wg-1791470457304", + "subnet": "198.18.255.240/30", + "listenPort": 51879, + "realRouterOs": true, + "changes": [ + { + "method": "POST", + "path": "/api/wireguard/interfaces", + "status": 201 + }, + { + "method": "POST", + "path": "/api/wireguard/interfaces", + "status": 201 + }, + { + "method": "POST", + "path": "/api/wireguard/peers", + "status": 201 + }, + { + "method": "POST", + "path": "/api/wireguard/peers", + "status": 201 + }, + { + "method": "PATCH", + "path": "/api/wireguard/interfaces/1/*5", + "status": 200 + }, + { + "method": "PATCH", + "path": "/api/wireguard/interfaces/1/*5", + "status": 200 + }, + { + "method": "GET", + "path": "/api/wireguard", + "status": 200 + }, + { + "method": "DELETE", + "path": "/api/wireguard/peers/1/*1", + "status": 400 + }, + { + "method": "DELETE", + "path": "/api/wireguard/peers/2/*1", + "status": 400 + } + ], + "pings": [ + { + "serverId": 1, + "target": "198.18.255.242", + "interface": "mm-acceptance-wg-1791470457304", + "received": 3, + "rows": [ + { + "sent": "1", + "received": "1", + "packet-loss": "0", + "time": "54ms733us", + "avg-rtt": "54ms733us" + }, + { + "sent": "2", + "received": "2", + "packet-loss": "0", + "time": "55ms573us", + "avg-rtt": "55ms153us" + }, + { + "sent": "3", + "received": "3", + "packet-loss": "0", + "time": "55ms260us", + "avg-rtt": "55ms188us" + } + ] + }, + { + "serverId": 2, + "target": "198.18.255.241", + "interface": "mm-acceptance-wg-1791470457304", + "received": 3, + "rows": [ + { + "sent": "1", + "received": "1", + "packet-loss": "0", + "time": "55ms569us", + "avg-rtt": "55ms569us" + }, + { + "sent": "2", + "received": "2", + "packet-loss": "0", + "time": "55ms190us", + "avg-rtt": "55ms379us" + }, + { + "sent": "3", + "received": "3", + "packet-loss": "0", + "time": "54ms747us", + "avg-rtt": "55ms168us" + } + ] + } + ], + "cleanup": [ + { + "serverId": 1, + "error": "Application request rejected, status 400" + }, + { + "serverId": 2, + "error": "Application request rejected, status 400" + } + ], + "nativeKeyGenerationConfirmed": true, + "connectedState": [ + { + "serverId": 1, + "interface": { + "rosId": "*5", + "appId": "1:*5", + "name": "mm-acceptance-wg-1791470457304", + "listenPort": "51879", + "mtu": "1420", + "running": "true", + "disabled": "false", + "userComment": "Temporary UX acceptance mm-acceptance-wg-1791470457304" + }, + "addresses": [ + "198.18.255.241/30" + ], + "peers": [ + { + "rosId": "*1", + "name": "mm-acceptance-wg-1791470457304-peer", + "allowedAddresses": "198.18.255.242/32", + "endpoint": "104.165.244.7:51879", + "handshake": "1s", + "rx": "180", + "tx": "272", + "disabled": "false", + "userComment": "Temporary UX acceptance mm-acceptance-wg-1791470457304" + } + ] + }, + { + "serverId": 2, + "interface": { + "rosId": "*A", + "appId": "2:*A", + "name": "mm-acceptance-wg-1791470457304", + "listenPort": "51879", + "mtu": "1420", + "running": "true", + "disabled": "false", + "userComment": "Temporary UX acceptance mm-acceptance-wg-1791470457304" + }, + "addresses": [ + "198.18.255.242/30" + ], + "peers": [ + { + "rosId": "*1", + "name": "mm-acceptance-wg-1791470457304-peer", + "allowedAddresses": "198.18.255.241/32", + "endpoint": "194.226.121.150:51879", + "handshake": "1s", + "rx": "124", + "tx": "180", + "disabled": "false", + "userComment": "Temporary UX acceptance mm-acceptance-wg-1791470457304" + } + ] + } + ], + "handshakeConfirmed": true, + "bidirectionalPingPassed": true, + "catalogMatchesNative": true, + "limits": [ + "Only own WireGuard interface/peer/IP and connected route changed; no default routes/firewall changes", + "Own IP addresses explicitly deleted via native API before interface deletion; automatic address cleanup was not tested", + "Private/public/preshared keys omitted from report; native generation and peer association checked in memory", + "Handshake and short ICMP connectivity, not throughput, RBAC or interrupted mutation", + "WireGuard audit revisions intentionally retained" + ] +} diff --git a/docs/ux-ui/acceptance/wg-real-lifecycle-2026-10-08.json b/docs/ux-ui/acceptance/wg-real-lifecycle-2026-10-08.json new file mode 100644 index 00000000..164c1650 --- /dev/null +++ b/docs/ux-ui/acceptance/wg-real-lifecycle-2026-10-08.json @@ -0,0 +1,233 @@ +{ + "date": "2026-10-08", + "backendSource": "bd3f996", + "frontendSource": "fd521f6", + "name": "mm-acceptance-wg-1791470702451", + "subnet": "198.18.255.240/30", + "listenPort": 51879, + "realRouterOs": true, + "changes": [ + { + "method": "POST", + "path": "/api/wireguard/interfaces", + "status": 201 + }, + { + "method": "POST", + "path": "/api/wireguard/interfaces", + "status": 201 + }, + { + "method": "POST", + "path": "/api/wireguard/peers", + "status": 201 + }, + { + "method": "POST", + "path": "/api/wireguard/peers", + "status": 201 + }, + { + "method": "PATCH", + "path": "/api/wireguard/interfaces/1/*6", + "status": 200 + }, + { + "method": "PATCH", + "path": "/api/wireguard/interfaces/1/*6", + "status": 200 + }, + { + "method": "GET", + "path": "/api/wireguard", + "status": 200 + }, + { + "method": "DELETE", + "path": "/api/wireguard/peers/1/*2", + "status": 200 + }, + { + "method": "DELETE", + "path": "/api/wireguard/interfaces/1/*6", + "status": 200 + }, + { + "method": "DELETE", + "path": "/api/wireguard/peers/2/*2", + "status": 200 + }, + { + "method": "DELETE", + "path": "/api/wireguard/interfaces/2/*B", + "status": 200 + } + ], + "pings": [ + { + "serverId": 1, + "target": "198.18.255.242", + "interface": "mm-acceptance-wg-1791470702451", + "received": 3, + "rows": [ + { + "sent": "1", + "received": "1", + "packet-loss": "0", + "time": "54ms795us", + "avg-rtt": "54ms795us" + }, + { + "sent": "2", + "received": "2", + "packet-loss": "0", + "time": "55ms61us", + "avg-rtt": "54ms928us" + }, + { + "sent": "3", + "received": "3", + "packet-loss": "0", + "time": "54ms865us", + "avg-rtt": "54ms907us" + } + ] + }, + { + "serverId": 2, + "target": "198.18.255.241", + "interface": "mm-acceptance-wg-1791470702451", + "received": 3, + "rows": [ + { + "sent": "1", + "received": "1", + "packet-loss": "0", + "time": "54ms790us", + "avg-rtt": "54ms790us" + }, + { + "sent": "2", + "received": "2", + "packet-loss": "0", + "time": "55ms69us", + "avg-rtt": "54ms929us" + }, + { + "sent": "3", + "received": "3", + "packet-loss": "0", + "time": "55ms78us", + "avg-rtt": "54ms979us" + } + ] + } + ], + "cleanup": [ + { + "serverId": 1, + "/interface/wireguard": true, + "/interface/wireguard/peers": true, + "/ip/address": true, + "/ip/route": true, + "/ip/firewall/filter": true, + "/ip/firewall/nat": true, + "/ip/firewall/mangle": true + }, + { + "serverId": 2, + "/interface/wireguard": true, + "/interface/wireguard/peers": true, + "/ip/address": true, + "/ip/route": true, + "/ip/firewall/filter": true, + "/ip/firewall/nat": true, + "/ip/firewall/mangle": true + } + ], + "nativeKeyGenerationConfirmed": true, + "connectedState": [ + { + "serverId": 1, + "interface": { + "rosId": "*6", + "appId": "1:*6", + "name": "mm-acceptance-wg-1791470702451", + "listenPort": "51879", + "mtu": "1420", + "running": "true", + "disabled": "false", + "userComment": "Temporary UX acceptance mm-acceptance-wg-1791470702451" + }, + "addresses": [ + "198.18.255.241/30" + ], + "peers": [ + { + "rosId": "*2", + "name": "mm-acceptance-wg-1791470702451-peer", + "allowedAddresses": "198.18.255.242/32", + "endpoint": "104.165.244.7:51879", + "handshake": "2s", + "rx": "272", + "tx": "452", + "disabled": "false", + "userComment": "Temporary UX acceptance mm-acceptance-wg-1791470702451" + } + ] + }, + { + "serverId": 2, + "interface": { + "rosId": "*B", + "appId": "2:*B", + "name": "mm-acceptance-wg-1791470702451", + "listenPort": "51879", + "mtu": "1420", + "running": "true", + "disabled": "false", + "userComment": "Temporary UX acceptance mm-acceptance-wg-1791470702451" + }, + "addresses": [ + "198.18.255.242/30" + ], + "peers": [ + { + "rosId": "*2", + "name": "mm-acceptance-wg-1791470702451-peer", + "allowedAddresses": "198.18.255.241/32", + "endpoint": "194.226.121.150:51879", + "handshake": "2s", + "rx": "304", + "tx": "304", + "disabled": "false", + "userComment": "Temporary UX acceptance mm-acceptance-wg-1791470702451" + } + ] + } + ], + "handshakeConfirmed": true, + "bidirectionalPingPassed": true, + "catalogMatchesNative": true, + "limits": [ + "Only own WireGuard interface/peer/IP and connected route changed; no default routes/firewall changes", + "Own IP addresses explicitly deleted via native API before interface deletion; automatic address cleanup was not tested", + "Private/public/preshared keys omitted from report; native generation and peer association checked in memory", + "Handshake and short ICMP connectivity, not throughput, RBAC or interrupted mutation", + "WireGuard audit revisions intentionally retained" + ], + "controlBefore": { + "servers": 2, + "speedHistory": 9, + "retentionDays": 14, + "migrations": 9 + }, + "controlAfter": { + "servers": 2, + "speedHistory": 9, + "retentionDays": 14, + "migrations": 9 + }, + "controlsUnchanged": true, + "backendHealthy": true +} diff --git a/docs/ux-ui/screens/wg-real-server1-dark-320-2026-10-08.png b/docs/ux-ui/screens/wg-real-server1-dark-320-2026-10-08.png new file mode 100644 index 0000000000000000000000000000000000000000..cb6b7812633f404798b9a643142abc2d8592a9d0 GIT binary patch literal 12417 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�syDq_?6$}D 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

literal 0 HcmV?d00001 diff --git a/docs/ux-ui/screens/wg-real-server1-light-320-2026-10-08.png b/docs/ux-ui/screens/wg-real-server1-light-320-2026-10-08.png new file mode 100644 index 0000000000000000000000000000000000000000..5c648e674e8dd94c1c43d6007e525ff90dc3fd3f GIT binary patch literal 12183 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 literal 0 HcmV?d00001 diff --git a/docs/ux-ui/screens/wg-real-server2-dark-320-2026-10-08.png b/docs/ux-ui/screens/wg-real-server2-dark-320-2026-10-08.png new file mode 100644 index 0000000000000000000000000000000000000000..ec4d59242c896582c32440a51a7b015dac7d9d59 GIT binary patch literal 12652 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 MN?Ed8-1yi30T*avivR!s literal 0 HcmV?d00001 diff --git a/docs/ux-ui/screens/wg-real-server2-light-320-2026-10-08.png b/docs/ux-ui/screens/wg-real-server2-light-320-2026-10-08.png new file mode 100644 index 0000000000000000000000000000000000000000..e1da5418c51845bbea48dddb28671c94a2bbdc1f GIT binary patch literal 12467 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 CE+@kP literal 0 HcmV?d00001