From 0c5d7d3207d791d1b4ae8e840d3040845a14b25e Mon Sep 17 00:00:00 2001 From: Denozordec Date: Tue, 13 Oct 2026 22:01:46 +0700 Subject: [PATCH] =?UTF-8?q?fix(network):=20=D0=B2=D1=8B=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20IPv6-=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D1=83?= =?UTF-8?q?=20=D0=B2=20=D1=8D=D0=BA=D1=81=D0=BF=D0=BE=D1=80=D1=82=D0=B5=20?= =?UTF-8?q?GRE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ux-ui-external-acceptance.md | 6 +- docs/ux-ui-plan.md | 2 +- docs/ux-ui-progress.md | 16 ++++- docs/ux-ui-remaining-acceptance.md | 12 ++-- docs/ux-ui-stage-12.md | 17 ++++- docs/ux-ui-test-server.md | 6 +- ...re213-connectivity-recheck-2026-10-13.json | 1 + .../gre213-deployment-2026-10-13.json | 20 ++++++ .../acceptance/gre213-e2e-2026-10-13.json | 15 ++++ .../gre213-native-live-2026-10-13.json | 72 +++++++++++++++++++ .../acceptance/gre213-profile-2026-10-13.json | 12 ++++ docs/ux-ui/acceptance/source213-result.json | 10 +++ lib/gre-export.test.ts | 4 ++ lib/gre-export.ts | 6 +- tests/e2e/gre-ipv6-export.spec.ts | 15 ++++ 15 files changed, 204 insertions(+), 10 deletions(-) create mode 100644 docs/ux-ui/acceptance/gre213-connectivity-recheck-2026-10-13.json create mode 100644 docs/ux-ui/acceptance/gre213-deployment-2026-10-13.json create mode 100644 docs/ux-ui/acceptance/gre213-e2e-2026-10-13.json create mode 100644 docs/ux-ui/acceptance/gre213-native-live-2026-10-13.json create mode 100644 docs/ux-ui/acceptance/gre213-profile-2026-10-13.json create mode 100644 docs/ux-ui/acceptance/source213-result.json create mode 100644 tests/e2e/gre-ipv6-export.spec.ts diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index f8a20e2e..102d4809 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-13: блок 212 завершён. GRE с PSK по умолчанию отключает FastPath; явный конфликт получает400. Форма и экспорт учитывают совместимость и недопустимый keepalive. SQL/API18, E2E10 и live GRE/Filters UI4 прошли; два собственных интерфейса удалены. Backend/frontend ux-gre212; source478/527 и compiled1048 совпали. Auth-исправление211 сохранено. Следующий213 — выбор IPv4/IPv6-команды в GRE экспорте. Этап12.5 открыт. +Актуальное продолжение 2026-10-13: блок 213 завершён. GRE экспорт выбирает IPv4/IPv6 family; статический IPv6 fragment содержит advertise=no и явные границы. Unit/backend IPv6, E2E6 и live UI4 прошли; два собственных GRE/ULA и Portal reader удалены. Backend ux-gre212, frontend ux-gre213/source527 matched. Оба CHR доступны; пароли совпадают с предоставленными. Следующий214 — ошибки legacy OSPF/BFD API вместо успешных пустых данных. Этап12.5 открыт. IPsec78: реальный PSK responder established, mode-config198.18.78.10 и online=true подтверждены API; точные собственные объекты удалены. Сертификатный/DN online, late failure и history restore остаются открытыми. [Отчёт](ux-ui/acceptance/ipsec-mode-config-2026-10-09.json), [журнал](ux-ui-progress.md). @@ -2575,3 +2575,7 @@ Production compiled SQL/API29 на собственной ограниченно ## 12.5.212 — GRE PSK/FastPath (2026-10-13) Результат, проверки и ограничения: [полная запись212](ux-ui-progress.md#125212--совместимость-gre-pskfastpath-и-шаблоны-экспорта-2026-10-13). Runtime ux-gre212, SQL/API18, E2E10, native/UI и cleanup подтверждены; auth211 сохранён. + +## 12.5.213 — GRE IPv6 export (2026-10-13) + +Статический внутренний ULA и IPv6 fragment проверены на двух CHR и четырёх live UI. Backend ux-gre212, frontend ux-gre213; собственные интерфейсы/адреса/user удалены. Подробности и ограничения: [блок213 в журнале](ux-ui-progress.md). Public IPv6 и произвольный RSC import не приняты. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 04ec6e8b..ba1f6ded 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,6 +1,6 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-13: блок 212 завершён. GRE с PSK по умолчанию отключает FastPath; явный конфликт получает400. Форма и экспорт учитывают совместимость и недопустимый keepalive. SQL/API18, E2E10 и live GRE/Filters UI4 прошли; два собственных интерфейса удалены. Backend/frontend ux-gre212; source478/527 и compiled1048 совпали. Auth-исправление211 сохранено. Следующий213 — выбор IPv4/IPv6-команды в GRE экспорте. Этап12.5 открыт. +Актуальное продолжение 2026-10-13: блок 213 завершён. GRE экспорт выбирает IPv4/IPv6 family; статический IPv6 fragment содержит advertise=no и явные границы. Unit/backend IPv6, E2E6 и live UI4 прошли; два собственных GRE/ULA и Portal reader удалены. Backend ux-gre212, frontend ux-gre213/source527 matched. Оба CHR доступны; пароли совпадают с предоставленными. Следующий214 — ошибки legacy OSPF/BFD API вместо успешных пустых данных. Этап12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-13. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index 5306ad59..cb67efe5 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-13: блок 212 завершён. GRE с PSK по умолчанию отключает FastPath; явный конфликт получает400. Форма и экспорт учитывают совместимость и недопустимый keepalive. SQL/API18, E2E10 и live GRE/Filters UI4 прошли; два собственных интерфейса удалены. Backend/frontend ux-gre212; source478/527 и compiled1048 совпали. Auth-исправление211 сохранено. Следующий213 — выбор IPv4/IPv6-команды в GRE экспорте. Этап12.5 открыт. +Актуальное продолжение 2026-10-13: блок 213 завершён. GRE экспорт выбирает IPv4/IPv6 family; статический IPv6 fragment содержит advertise=no и явные границы. Unit/backend IPv6, E2E6 и live UI4 прошли; два собственных GRE/ULA и Portal reader удалены. Backend ux-gre212, frontend ux-gre213/source527 matched. Оба CHR доступны; пароли совпадают с предоставленными. Следующий214 — ошибки legacy OSPF/BFD API вместо успешных пустых данных. Этап12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -38,6 +38,20 @@ | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | | 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–196 и ограничения ниже. Runtime backend/frontend ux-peak196. | +## 12.5.213 — IPv6 в фрагменте экспорта GRE (2026-10-13) + +Генератор всегда использовал /ip/address/add, хотя приложение уже поддерживает статический внутренний IPv6. Теперь family выбирается по адресу: IPv4 сохраняет прежнюю команду; IPv6 получает /ipv6/address/add и advertise=no. Комментарий уточняет: это новый статический адрес без объявления префикса; pool/EUI-64 и остальные адреса не включены. Это фрагмент, не полное восстановление параметров произвольного native адреса. Escaping и шаблоны213/212 сохранены; ReUI primitives не менялись. + +Проверки: GRE export unit и прежний backend gre-ipv6.test прошли; TypeScript и ESLint без ошибок. E2E6 — IPv6 family, скрытый PSK и несовместимый экспорт на1440/320. Frontend ux-gre213 развёрнут, source527 совпал; backend ux-gre212 не перезапускался и остался healthy. + +Live: приложение создало по собственному отключённому GRE со статическим внутренним ULA на обоих CHR. Native /ipv6/address подтвердил CIDR/interface/advertise=false; API сохранил адрес. Reader/admin ×1440/320 — четыре UI-кейса без mocks, writes и page errors, правильная IPv6-команда и границы фрагмента. Затем оба интерфейса, оба статических адреса и Portal reader удалены, отсутствие проверено. Encoded anonymous GET401 сохранился. Нет утверждения об исполнении RSC, публичном/внешнем IPv6 или data plane. + +Первый запуск завершился общим assert401 без привязки к слою; до создания интерфейсов, temporary user очищен. Перепроверка дала шесть REST200 на обоих CHR, приложение GET200/failures=[]; сохранённые пароли совпадают с предоставленными. Причина первого401 не установлена. В повторный helper добавлены контекстные сообщения, цельный live-сценарий прошёл. Секреты не сохранялись/не выводились; пароли не менялись. + +Протоколы: [профили](ux-ui/acceptance/gre213-profile-2026-10-13.json), [E2E6](ux-ui/acceptance/gre213-e2e-2026-10-13.json), [connectivity recheck](ux-ui/acceptance/gre213-connectivity-recheck-2026-10-13.json), [native/UI/cleanup](ux-ui/acceptance/gre213-native-live-2026-10-13.json), [source](ux-ui/acceptance/source213-result.json), [deployment](ux-ui/acceptance/gre213-deployment-2026-10-13.json). + +Следующий214: legacy /ospf/neighbors, /ospf/interfaces, /ospf/instances, /ospf/all и /bfd/sessions сейчас скрывают rejected native reads как200/empty. Поиск не нашёл активных frontend-потребителей этих путей; основной OSPF catalog уже сообщает failures. Сохранить успешные legacy envelopes и явно сообщать частичный/полный отказ; проверить собственные SQL/HTTP fixtures без искусственного отключения CHR. + ## 12.5.212 — совместимость GRE PSK/FastPath и шаблоны экспорта (2026-10-13) POST с PSK и опущенным allowFastPath теперь создаёт GRE с FastPath=false. При явном PSK+FastPath=true возвращается400 до native requests; PATCH учитывает уже настроенный PSK и не пишет несовместимое состояние. Включение PSK через PATCH без FastPath отключает его; изменения другого поля сохраняют прочие настройки. Форма показывает FastPath выключенным и недоступным при IPsec, отправляет false. Global IPsec peer/policy/proposal не меняются. diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index f8813fd5..b111face 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,10 +1,10 @@ # Оставшаяся внешняя приёмка — 2026-10-13 -Актуальное продолжение 2026-10-13: блок 212 завершён. GRE с PSK по умолчанию отключает FastPath; явный конфликт получает400. Форма и экспорт учитывают совместимость и недопустимый keepalive. SQL/API18, E2E10 и live GRE/Filters UI4 прошли; два собственных интерфейса удалены. Backend/frontend ux-gre212; source478/527 и compiled1048 совпали. Auth-исправление211 сохранено. Следующий213 — выбор IPv4/IPv6-команды в GRE экспорте. Этап12.5 открыт. +Актуальное продолжение 2026-10-13: блок 213 завершён. GRE экспорт выбирает IPv4/IPv6 family; статический IPv6 fragment содержит advertise=no и явные границы. Unit/backend IPv6, E2E6 и live UI4 прошли; два собственных GRE/ULA и Portal reader удалены. Backend ux-gre212, frontend ux-gre213/source527 matched. Оба CHR доступны; пароли совпадают с предоставленными. Следующий214 — ошибки legacy OSPF/BFD API вместо успешных пустых данных. Этап12.5 открыт. -Это актуальная матрица после 12.5.212. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.213. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. -Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend/frontend `ux-gre212`; production lab с195 использует AUTH_REQUIRED=true и Portal1.3.1. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. +Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-gre212`, frontend `ux-gre213`; production lab с195 использует AUTH_REQUIRED=true и Portal1.3.1. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. | Раздел | Подтверждено | Осталось / условие завершения | | --- | --- | --- | @@ -26,7 +26,7 @@ ## Следующая последовательность — 2026-10-13 -1. **213 — GRE IPv6 export:** команда локального IPv6 вместо /ip/address/add; собственные ULA и профильные UI/экспорт проверки. +1. **214 — legacy OSPF/BFD read errors:** пять GET endpoints скрывают native failures; сохранить success envelopes, различить empty/partial/all-failed/disabled contexts в own SQL/HTTP fixtures. 2. **Профильный контроль:** для новых изменений выполнять затронутые SQL/API/UI проверки. Общая регрессия192 выполнена; не повторять её без изменений общей основы или нового основания. 3. **Внешние зависимости:** Portal issuer/login/revoke, Telegram bot/chat/разрешённое сообщение, клиентские ОС, независимые WAN/public IPv6 и scale/multi-instance — отдельные группы по таблице выше. Ограничения текущего стенда не превращать в обещание приёмки всех конфигураций. @@ -1493,3 +1493,7 @@ Production compiled SQL/API29 на собственной ограниченно ## 12.5.212 — GRE PSK/FastPath (2026-10-13) Результат, проверки и ограничения: [полная запись212](ux-ui-progress.md#125212--совместимость-gre-pskfastpath-и-шаблоны-экспорта-2026-10-13). Runtime ux-gre212, SQL/API18, E2E10, native/UI и cleanup подтверждены; auth211 сохранён. + +## 12.5.213 — GRE IPv6 export (2026-10-13) + +Статический внутренний ULA и IPv6 fragment проверены на двух CHR и четырёх live UI. Backend ux-gre212, frontend ux-gre213; собственные интерфейсы/адреса/user удалены. Подробности и ограничения: [блок213 в журнале](ux-ui-progress.md). Public IPv6 и произвольный RSC import не приняты. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 556a50ec..c5f01de9 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1,6 +1,6 @@ # Этап 12: итоговая приёмка UX/UI -Актуальное продолжение 2026-10-13: блок 212 завершён. GRE с PSK по умолчанию отключает FastPath; явный конфликт получает400. Форма и экспорт учитывают совместимость и недопустимый keepalive. SQL/API18, E2E10 и live GRE/Filters UI4 прошли; два собственных интерфейса удалены. Backend/frontend ux-gre212; source478/527 и compiled1048 совпали. Auth-исправление211 сохранено. Следующий213 — выбор IPv4/IPv6-команды в GRE экспорте. Этап12.5 открыт. +Актуальное продолжение 2026-10-13: блок 213 завершён. GRE экспорт выбирает IPv4/IPv6 family; статический IPv6 fragment содержит advertise=no и явные границы. Unit/backend IPv6, E2E6 и live UI4 прошли; два собственных GRE/ULA и Portal reader удалены. Backend ux-gre212, frontend ux-gre213/source527 matched. Оба CHR доступны; пароли совпадают с предоставленными. Следующий214 — ошибки legacy OSPF/BFD API вместо успешных пустых данных. Этап12.5 открыт. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -3895,3 +3895,18 @@ Live: по одному собственному отключённому GRE с Следующий213: GRE exporter всегда использует /ip/address/add, даже для уже поддерживаемого приложением внутреннего IPv6. Исправить family и проверить собственные ULA без обещания public IPv6/terminal import. + +## 12.5.213 — IPv6 в фрагменте экспорта GRE (2026-10-13) + +Генератор всегда использовал /ip/address/add, хотя приложение уже поддерживает статический внутренний IPv6. Теперь family выбирается по адресу: IPv4 сохраняет прежнюю команду; IPv6 получает /ipv6/address/add и advertise=no. Комментарий уточняет: это новый статический адрес без объявления префикса; pool/EUI-64 и остальные адреса не включены. Это фрагмент, не полное восстановление параметров произвольного native адреса. Escaping и шаблоны213/212 сохранены; ReUI primitives не менялись. + +Проверки: GRE export unit и прежний backend gre-ipv6.test прошли; TypeScript и ESLint без ошибок. E2E6 — IPv6 family, скрытый PSK и несовместимый экспорт на1440/320. Frontend ux-gre213 развёрнут, source527 совпал; backend ux-gre212 не перезапускался и остался healthy. + +Live: приложение создало по собственному отключённому GRE со статическим внутренним ULA на обоих CHR. Native /ipv6/address подтвердил CIDR/interface/advertise=false; API сохранил адрес. Reader/admin ×1440/320 — четыре UI-кейса без mocks, writes и page errors, правильная IPv6-команда и границы фрагмента. Затем оба интерфейса, оба статических адреса и Portal reader удалены, отсутствие проверено. Encoded anonymous GET401 сохранился. Нет утверждения об исполнении RSC, публичном/внешнем IPv6 или data plane. + +Первый запуск завершился общим assert401 без привязки к слою; до создания интерфейсов, temporary user очищен. Перепроверка дала шесть REST200 на обоих CHR, приложение GET200/failures=[]; сохранённые пароли совпадают с предоставленными. Причина первого401 не установлена. В повторный helper добавлены контекстные сообщения, цельный live-сценарий прошёл. Секреты не сохранялись/не выводились; пароли не менялись. + +Протоколы: [профили](ux-ui/acceptance/gre213-profile-2026-10-13.json), [E2E6](ux-ui/acceptance/gre213-e2e-2026-10-13.json), [connectivity recheck](ux-ui/acceptance/gre213-connectivity-recheck-2026-10-13.json), [native/UI/cleanup](ux-ui/acceptance/gre213-native-live-2026-10-13.json), [source](ux-ui/acceptance/source213-result.json), [deployment](ux-ui/acceptance/gre213-deployment-2026-10-13.json). + +Следующий214: legacy /ospf/neighbors, /ospf/interfaces, /ospf/instances, /ospf/all и /bfd/sessions сейчас скрывают rejected native reads как200/empty. Поиск не нашёл активных frontend-потребителей этих путей; основной OSPF catalog уже сообщает failures. Сохранить успешные legacy envelopes и явно сообщать частичный/полный отказ; проверить собственные SQL/HTTP fixtures без искусственного отключения CHR. + diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index 0bc82a64..e71edc7d 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -1,6 +1,6 @@ # Тестовый сервер UX/UI — 2026-10-10 -Актуальное продолжение 2026-10-13: блок 212 завершён. GRE с PSK по умолчанию отключает FastPath; явный конфликт получает400. Форма и экспорт учитывают совместимость и недопустимый keepalive. SQL/API18, E2E10 и live GRE/Filters UI4 прошли; два собственных интерфейса удалены. Backend/frontend ux-gre212; source478/527 и compiled1048 совпали. Auth-исправление211 сохранено. Следующий213 — выбор IPv4/IPv6-команды в GRE экспорте. Этап12.5 открыт. +Актуальное продолжение 2026-10-13: блок 213 завершён. GRE экспорт выбирает IPv4/IPv6 family; статический IPv6 fragment содержит advertise=no и явные границы. Unit/backend IPv6, E2E6 и live UI4 прошли; два собственных GRE/ULA и Portal reader удалены. Backend ux-gre212, frontend ux-gre213/source527 matched. Оба CHR доступны; пароли совпадают с предоставленными. Следующий214 — ошибки legacy OSPF/BFD API вместо успешных пустых данных. Этап12.5 открыт. | Параметр | Проверенное состояние | | --- | --- | @@ -2306,3 +2306,7 @@ Production compiled SQL/API29 на собственной ограниченно ## 12.5.212 — GRE PSK/FastPath (2026-10-13) Результат, проверки и ограничения: [полная запись212](ux-ui-progress.md#125212--совместимость-gre-pskfastpath-и-шаблоны-экспорта-2026-10-13). Runtime ux-gre212, SQL/API18, E2E10, native/UI и cleanup подтверждены; auth211 сохранён. + +## 12.5.213 — GRE IPv6 export (2026-10-13) + +Статический внутренний ULA и IPv6 fragment проверены на двух CHR и четырёх live UI. Backend ux-gre212, frontend ux-gre213; собственные интерфейсы/адреса/user удалены. Подробности и ограничения: [блок213 в журнале](ux-ui-progress.md). Public IPv6 и произвольный RSC import не приняты. diff --git a/docs/ux-ui/acceptance/gre213-connectivity-recheck-2026-10-13.json b/docs/ux-ui/acceptance/gre213-connectivity-recheck-2026-10-13.json new file mode 100644 index 00000000..405ed5c4 --- /dev/null +++ b/docs/ux-ui/acceptance/gre213-connectivity-recheck-2026-10-13.json @@ -0,0 +1 @@ +{"direct":[{"host":"194.226.121.150","path":"/system/resource","status":200},{"host":"194.226.121.150","path":"/interface/gre","status":200},{"host":"194.226.121.150","path":"/ipv6/address","status":200},{"host":"104.165.244.7","path":"/system/resource","status":200},{"host":"104.165.244.7","path":"/interface/gre","status":200},{"host":"104.165.244.7","path":"/ipv6/address","status":200}],"app":[{"host":"194.226.121.150","id":1,"port":80,"useSsl":false,"username":"admin","storedPasswordPresent":true,"storedMatchesProvided":true,"status":200,"failures":[]},{"host":"104.165.244.7","id":2,"port":80,"useSsl":false,"username":"admin","storedPasswordPresent":true,"storedMatchesProvided":true,"status":200,"failures":[]}]} \ No newline at end of file diff --git a/docs/ux-ui/acceptance/gre213-deployment-2026-10-13.json b/docs/ux-ui/acceptance/gre213-deployment-2026-10-13.json new file mode 100644 index 00000000..fdf1e7a9 --- /dev/null +++ b/docs/ux-ui/acceptance/gre213-deployment-2026-10-13.json @@ -0,0 +1,20 @@ +{ + "date": "2026-10-13", + "block": "12.5.213", + "frontendSourceMatched": 527, + "backendChanged": false, + "services": { + "backend": { + "image": "mmapp-test/backend:ux-gre212", + "imageId": "sha256:15b4c11614737ff12d4a4d40ed585324dabcace1f96342f0e966266125b78a1b", + "running": true, + "health": "healthy" + }, + "frontend": { + "image": "mmapp-test/frontend:ux-gre213", + "imageId": "sha256:01100214ca8f66e2a581b9181d1fe85d374dbfe3a1e377531ef062a8ef0b3d8e", + "running": true, + "health": null + } + } +} \ No newline at end of file diff --git a/docs/ux-ui/acceptance/gre213-e2e-2026-10-13.json b/docs/ux-ui/acceptance/gre213-e2e-2026-10-13.json new file mode 100644 index 00000000..5862320f --- /dev/null +++ b/docs/ux-ui/acceptance/gre213-e2e-2026-10-13.json @@ -0,0 +1,15 @@ +{ + "date": "2026-10-13", + "block": "12.5.213", + "uniqueCases": 6, + "stats": { + "startTime": "2026-10-13T14:43:25.817Z", + "duration": 14960.735, + "expected": 6, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "apiMocked": true, + "scope": "IPv6 family and existing export templates on 1440/320" +} diff --git a/docs/ux-ui/acceptance/gre213-native-live-2026-10-13.json b/docs/ux-ui/acceptance/gre213-native-live-2026-10-13.json new file mode 100644 index 00000000..4da33298 --- /dev/null +++ b/docs/ux-ui/acceptance/gre213-native-live-2026-10-13.json @@ -0,0 +1,72 @@ +{ + "date": "2026-10-13", + "block": "12.5.213", + "backend": "ux-gre212", + "frontend": "ux-gre213", + "cases": [ + { + "host": "194.226.121.150", + "applicationCreateStatus": 201, + "ownedDisabledGre": true, + "localInnerIp": "fd00:213:427d::1/64", + "nativeFamily": "ipv6/address", + "advertise": false, + "publicOuterIpv6": false, + "dataPlaneTest": false + }, + { + "host": "104.165.244.7", + "applicationCreateStatus": 201, + "ownedDisabledGre": true, + "localInnerIp": "fd00:213:427d::2/64", + "nativeFamily": "ipv6/address", + "advertise": false, + "publicOuterIpv6": false, + "dataPlaneTest": false + } + ], + "uiCases": [ + { + "width": 1440, + "role": "reader", + "actualNativeData": true, + "ipv6ExportFamily": true, + "staticFragmentScopeVisible": true, + "mutationRequests": 0, + "pageErrors": 0 + }, + { + "width": 1440, + "role": "admin", + "actualNativeData": true, + "ipv6ExportFamily": true, + "staticFragmentScopeVisible": true, + "mutationRequests": 0, + "pageErrors": 0 + }, + { + "width": 320, + "role": "reader", + "actualNativeData": true, + "ipv6ExportFamily": true, + "staticFragmentScopeVisible": true, + "mutationRequests": 0, + "pageErrors": 0 + }, + { + "width": 320, + "role": "admin", + "actualNativeData": true, + "ipv6ExportFamily": true, + "staticFragmentScopeVisible": true, + "mutationRequests": 0, + "pageErrors": 0 + } + ], + "apiMocks": false, + "realPortalJWT": true, + "encodedAnonymousAuthStatus": 401, + "cleanupCompleted": true, + "scope": "Static inner ULA GRE projection/export fragment matches native IPv6 family; no RSC execution, outer/public IPv6 or data-plane claim", + "ownedPortalUserRemoved": true +} diff --git a/docs/ux-ui/acceptance/gre213-profile-2026-10-13.json b/docs/ux-ui/acceptance/gre213-profile-2026-10-13.json new file mode 100644 index 00000000..afd39220 --- /dev/null +++ b/docs/ux-ui/acceptance/gre213-profile-2026-10-13.json @@ -0,0 +1,12 @@ +{ + "date": "2026-10-13", + "block": "12.5.213", + "commands": [ + "npx tsx lib/gre-export.test.ts", + "npx tsx backend/src/services/gre-ipv6.test.ts" + ], + "passed": true, + "frontendTypecheckPassed": true, + "eslintErrors": 0, + "scope": "IPv6 family/static fragment and existing backend IPv6 compatibility; no backend changes" +} diff --git a/docs/ux-ui/acceptance/source213-result.json b/docs/ux-ui/acceptance/source213-result.json new file mode 100644 index 00000000..a2d97157 --- /dev/null +++ b/docs/ux-ui/acceptance/source213-result.json @@ -0,0 +1,10 @@ +{ + "date": "2026-10-13", + "block": "12.5.213", + "kinds": [ + { + "kind": "frontend", + "matched": 527 + } + ] +} \ No newline at end of file diff --git a/lib/gre-export.test.ts b/lib/gre-export.test.ts index 15f316aa..772a39c3 100644 --- a/lib/gre-export.test.ts +++ b/lib/gre-export.test.ts @@ -28,3 +28,7 @@ console.log('gre-export: hidden configured PSK produces an explicitly labelled t const incompatible = generateGreRsc({ ...tunnel, allowFastPath: true }, {}) assert.ok(incompatible.includes("allow-fast-path=")) assert.ok(incompatible.includes("IPsec несовместим с FastPath")) +const ipv6 = generateGreRsc({ ...tunnel, ipsec: null, localInnerIp: "fd00:213::1/64" }, {}) +assert.ok(ipv6.includes('/ipv6/address/add address="fd00:213::1/64" interface=' + quoteRosString(tunnel.name) + " advertise=no")) +assert.ok(!ipv6.includes("/ip/address/add")) +assert.ok(ipv6.includes("pool/EUI-64 и остальные адреса не включены")) diff --git a/lib/gre-export.ts b/lib/gre-export.ts index 93320b41..9bd33286 100644 --- a/lib/gre-export.ts +++ b/lib/gre-export.ts @@ -33,7 +33,11 @@ export function generateGreRsc(t: GreTunnel, servers: Record): s args.push("ipsec-secret=" + quoteRosString(t.ipsec.secret || "")) } lines.push("/interface/gre/add " + args.join(" ")) - if (t.localInnerIp) lines.push("/ip/address/add address=" + quoteRosString(t.localInnerIp) + " interface=" + quoteRosString(t.name)) + if (t.localInnerIp) { + const ipv6 = t.localInnerIp.includes(":") + if (ipv6) lines.push("# IPv6: новый статический адрес без объявления префикса; pool/EUI-64 и остальные адреса не включены") + lines.push((ipv6 ? "/ipv6/address/add" : "/ip/address/add") + " address=" + quoteRosString(t.localInnerIp) + " interface=" + quoteRosString(t.name) + (ipv6 ? " advertise=no" : "")) + } if (t.ipsec) lines.push("# Peer/policy создаёт RouterOS по ipsec-secret; ручные объекты IPsec не экспортируются") if (t.ipsec && t.allowFastPath) lines.push("# В снимке включён FastPath: для GRE с IPsec документация RouterOS требует allow-fast-path=no") return lines.join("\n") + "\n" diff --git a/tests/e2e/gre-ipv6-export.spec.ts b/tests/e2e/gre-ipv6-export.spec.ts new file mode 100644 index 00000000..3f9a391d --- /dev/null +++ b/tests/e2e/gre-ipv6-export.spec.ts @@ -0,0 +1,15 @@ +import {test,expect} from '@playwright/test' +for(const width of [1440,320])test(`GRE: GRE экспортирует внутренний IPv6 в правильном семействе ${width}`,async({page})=>{ + let writes=0 + const token=[Buffer.from('{}').toString('base64url'),Buffer.from(JSON.stringify({sub:'own213',apps:['mm'],permissions:['mm:dashboard:read','mm:servers:read','mm:network:read'],exp:Math.floor(Date.now()/1000)+600})).toString('base64url'),'fixture'].join('.') + await page.addInitScript(t=>localStorage.setItem('mmapp_token',t),token) + const tunnel={id:'*1',serverId:'1',name:'own213-gre',localAddress:'192.0.2.1',remoteAddress:'192.0.2.2',localInnerIp:'fd00:213::1/64',remoteInnerIp:'10.209.0.2/30',poolId:'live',ipsec:{secret:''},mtu:1476,keepaliveInterval:10,keepaliveRetries:3,dscp:'inherit',clampTcpMss:true,allowFastPath:false,comment:'',enabled:true,status:'up'} + await page.route('**/health',r=>r.fulfill({json:{ok:true}})) + await page.route('**/api/**',r=>{if(r.request().method()!=='GET')writes++;const p=new URL(r.request().url()).pathname;return r.fulfill({json:p==='/api/auth/config'?{required:true}:p==='/api/servers'?[{id:1,name:'Own209 router',host:'192.0.2.1',enabled:true,country:'RU'}]:p==='/api/gre/tunnels'?{tunnels:[tunnel]}:{}})}) + await page.setViewportSize({width,height:1000});await page.goto('/gre?server=1') + const row=page.getByRole('row').filter({hasText:'own213-gre'});await expect(row).toContainText('IPsec');await expect(row).not.toContainText('Открытый') + await expect(page.getByRole('button',{name:'Добавить туннель',exact:true})).toBeDisabled() + await page.getByRole('button',{name:'Просмотр кода: own213-gre',exact:true}).click() + const sheet=page.getByRole('dialog');await expect(sheet).toContainText('Шаблон: ключ IPsec скрыт');await expect(sheet.locator('pre')).toContainText('');await expect(sheet.locator('pre')).not.toContainText('ipsec-secret=""');await expect(sheet.locator('pre')).toContainText('/ipv6/address/add address="fd00:213::1/64"');await expect(sheet.locator('pre')).toContainText('advertise=no');await expect(sheet.locator('pre')).not.toContainText('/ip/address/add') + expect(writes).toBe(0);expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth+1)).toBe(true) +})