diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index f2c2547e..a9aa791d 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-12: завершён 12.5.157 — общая регрессия: 1260 UI + 221 context, все 24 backend профиля, source TypeScript прошли. 348 исходных изображений восстановлены и сверены по SHA256, включая пользовательские изменения. Runtime ux-id156/ux-ospf153 сохранён. Следующий 158 — проверить корректность сопоставления IPv6 OSPF/BFD; внешняя матрица 12.5 остаётся открытой. +Актуальное продолжение 2026-10-12: завершён 12.5.158 — OSPF/BFD сопоставляет эквивалентные IPv6 адреса, отвергает чужую zone/invalid IP и неоднозначные stale duplicate sessions. 5 unit/11 E2E/types/ESLint/frontend build/2 real deployed UI прошли; frontend ux-bfd158, backend ux-id156. Общая регрессия157 принята до этой delta. Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре с cleanup; внешняя матрица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). @@ -696,7 +696,7 @@ flowchart LR ## 12.5.77 — основной блок IPsec (2026-10-09) -Актуальное продолжение 2026-10-12: завершён 12.5.157 — общая регрессия: 1260 UI + 221 context, все 24 backend профиля, source TypeScript прошли. 348 исходных изображений восстановлены и сверены по SHA256, включая пользовательские изменения. Runtime ux-id156/ux-ospf153 сохранён. Следующий 158 — проверить корректность сопоставления IPv6 OSPF/BFD; внешняя матрица 12.5 остаётся открытой. +Актуальное продолжение 2026-10-12: завершён 12.5.158 — OSPF/BFD сопоставляет эквивалентные IPv6 адреса, отвергает чужую zone/invalid IP и неоднозначные stale duplicate sessions. 5 unit/11 E2E/types/ESLint/frontend build/2 real deployed UI прошли; frontend ux-bfd158, backend ux-id156. Общая регрессия157 принята до этой delta. Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре с cleanup; внешняя матрица12.5 открыта. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). @@ -1727,3 +1727,19 @@ Permanent server-id.test.ts проверяет25 valid/invalid forms без SQL. Source TypeScript прошёл после остановки тестового Next dev. Все348 tracked изображения восстановлены из сохранённых перед прогоном текущих bytes, каждое сверено по SHA256; сохранены в том числе8 пользовательских GRE/VXLAN изменений. Сгенерированные тестами изображения не заменяют согласованные референсы. Production source не менялся, образы ux-id156/ux-ospf153 повторно не собирались и не развёртывались. RouterOS конфигурация и пароли этим блоком не изменялись. Протокол: [регрессия157](ux-ui/acceptance/regression-157-2026-10-12.json). Это локальная контролируемая регрессия интерфейса/контекста/backend, а не повтор native сценариев или приёмка внешних сервисов, клиентских ОС, масштаба и физических WAN. Исторический timeout orchestration154 остаётся в исходном протоколе. Этап12.5 открыт; следующий158 — проверка эквивалентных IPv6 адресов в сопоставлении OSPF/BFD. + +## 12.5.158 — корректное сопоставление IPv6 OSPF и BFD (2026-10-12) + +Строковое сравнение не связывало эквивалентные IPv6 адреса: например FE80:0000:0000:0000:0000:0000:0000:0002 и fe80::2. Теперь IPv6 приводится к канонической записи, optional zone должна совпадать с наблюдаемым интерфейсом. Hostnames, malformed IPv4/IPv6, пустая/чужая/повторная zone не создают совпадение. Stale duplicate с тем же точным device/interface/peer не исключается до проверки уникальности: наличие такой неоднозначности подавляет предупреждение. Single stale session также не доказывает конфликт. Это только корреляция наблюдений; состояния RouterOS и правила сети не менялись. + +5 unit tests,11 E2E, source TypeScript и ESLint прошли. E2E включает IPv4/IPv6 на1440/320, предупреждение/переход к BFD с сохранением устройства и очисткой поиска, recovery/foreign/not-used/unknown; остальные7 проверяют состояния данных OSPF. Полную1481 UI/context регрессию157 повторно не запускали: она принята на предыдущем source, эта delta проверена отдельно. + +Переданный production source SHA256 совпал локально/на сервере. Frontend production build exit0; ux-bfd158 развёрнут с сохранённой private rollback env, backend ux-id156/PG сохранены. Немедленный curl после старта получил000 до готовности frontend; последующие две browser проверки1440/320 получили200, реальные catalog/server API200, page errors/overflow0 и отсутствие ложного предупреждения после очистки native fixtures. Позитивная native BFDv6 сессия этим блоком не заявляется. Пароли и RouterOS конфигурация не менялись; прежний закрытый SSH-туннель localhost3000/8000 восстановлен. + +Протоколы: [профильные проверки и сборка](ux-ui/acceptance/ospf-bfd-correlation-2026-10-12.json), [реальный развёрнутый интерфейс](ux-ui/acceptance/ospf-bfd-ipv6-smoke-2026-10-12.json). Установленные ReUI/Frame/base-nova переиспользованы без изменения primitives. + +| Референс | Схема доработки | +| --- | --- | +| [ReUI Data Grid Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Устройство → точный IPv6 peer/интерфейс → достоверное предупреждение → соответствующая BFD сессия | + +Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре, short loss/recovery и независимая сверка cleanup. Официальный [BFD manual](https://manual.mikrotik.com/docs/user-guides/routing-and-networking-protocols/unicast/bfd/) описывает IPv4/IPv6 и use-bfd, но текущая страница версии7.26 не заменяет эксперимент на стенде7.24.5. Sustained route gate, scale/IPv6 public WAN/outer и физическая резервность остаются непроверенными;12.5 открыт. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 67dd75ec..f523cd4d 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,12 +1,12 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-12: завершён 12.5.157 — общая регрессия: 1260 UI + 221 context, все 24 backend профиля, source TypeScript прошли. 348 исходных изображений восстановлены и сверены по SHA256, включая пользовательские изменения. Runtime ux-id156/ux-ospf153 сохранён. Следующий 158 — проверить корректность сопоставления IPv6 OSPF/BFD; внешняя матрица 12.5 остаётся открытой. +Актуальное продолжение 2026-10-12: завершён 12.5.158 — OSPF/BFD сопоставляет эквивалентные IPv6 адреса, отвергает чужую zone/invalid IP и неоднозначные stale duplicate sessions. 5 unit/11 E2E/types/ESLint/frontend build/2 real deployed UI прошли; frontend ux-bfd158, backend ux-id156. Общая регрессия157 принята до этой delta. Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре с cleanup; внешняя матрица12.5 открыта. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-12. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. ## Актуальная точка продолжения — 2026-10-12 -Актуальное продолжение 2026-10-12: завершён 12.5.157 — общая регрессия: 1260 UI + 221 context, все 24 backend профиля, source TypeScript прошли. 348 исходных изображений восстановлены и сверены по SHA256, включая пользовательские изменения. Runtime ux-id156/ux-ospf153 сохранён. Следующий 158 — проверить корректность сопоставления IPv6 OSPF/BFD; внешняя матрица 12.5 остаётся открытой. +Актуальное продолжение 2026-10-12: завершён 12.5.158 — OSPF/BFD сопоставляет эквивалентные IPv6 адреса, отвергает чужую zone/invalid IP и неоднозначные stale duplicate sessions. 5 unit/11 E2E/types/ESLint/frontend build/2 real deployed UI прошли; frontend ux-bfd158, backend ux-id156. Общая регрессия157 принята до этой delta. Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре с cleanup; внешняя матрица12.5 открыта. Этапы0–11 завершены в локальных границах журнала. История выполненных внешних блоков и доказательства сохранены в [журнале](ux-ui-stage-12.md) и [протоколе](ux-ui-external-acceptance.md). Реальная Telegram доставка, Portal SSO, multi-instance и оставшиеся профильные сетевые ограничения открыты. @@ -371,6 +371,6 @@ flowchart LR ## 12.5.77 — основной блок IPsec (2026-10-09) -Актуальное продолжение 2026-10-12: завершён 12.5.157 — общая регрессия: 1260 UI + 221 context, все 24 backend профиля, source TypeScript прошли. 348 исходных изображений восстановлены и сверены по SHA256, включая пользовательские изменения. Runtime ux-id156/ux-ospf153 сохранён. Следующий 158 — проверить корректность сопоставления IPv6 OSPF/BFD; внешняя матрица 12.5 остаётся открытой. +Актуальное продолжение 2026-10-12: завершён 12.5.158 — OSPF/BFD сопоставляет эквивалентные IPv6 адреса, отвергает чужую zone/invalid IP и неоднозначные stale duplicate sessions. 5 unit/11 E2E/types/ESLint/frontend build/2 real deployed UI прошли; frontend ux-bfd158, backend ux-id156. Общая регрессия157 принята до этой delta. Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре с cleanup; внешняя матрица12.5 открыта. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index 37b42047..45319951 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-12: завершён 12.5.157 — общая регрессия: 1260 UI + 221 context, все 24 backend профиля, source TypeScript прошли. 348 исходных изображений восстановлены и сверены по SHA256, включая пользовательские изменения. Runtime ux-id156/ux-ospf153 сохранён. Следующий 158 — проверить корректность сопоставления IPv6 OSPF/BFD; внешняя матрица 12.5 остаётся открытой. +Актуальное продолжение 2026-10-12: завершён 12.5.158 — OSPF/BFD сопоставляет эквивалентные IPv6 адреса, отвергает чужую zone/invalid IP и неоднозначные stale duplicate sessions. 5 unit/11 E2E/types/ESLint/frontend build/2 real deployed UI прошли; frontend ux-bfd158, backend ux-id156. Общая регрессия157 принята до этой delta. Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре с cleanup; внешняя матрица12.5 открыта. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -36,7 +36,23 @@ | 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–157 и ограничения ниже. Runtime backend ux-month149/frontend ux-sessions150. | +| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–158 и ограничения ниже. Runtime backend ux-month149/frontend ux-sessions150. | + +## 12.5.158 — корректное сопоставление IPv6 OSPF и BFD (2026-10-12) + +Строковое сравнение не связывало эквивалентные IPv6 адреса: например FE80:0000:0000:0000:0000:0000:0000:0002 и fe80::2. Теперь IPv6 приводится к канонической записи, optional zone должна совпадать с наблюдаемым интерфейсом. Hostnames, malformed IPv4/IPv6, пустая/чужая/повторная zone не создают совпадение. Stale duplicate с тем же точным device/interface/peer не исключается до проверки уникальности: наличие такой неоднозначности подавляет предупреждение. Single stale session также не доказывает конфликт. Это только корреляция наблюдений; состояния RouterOS и правила сети не менялись. + +5 unit tests,11 E2E, source TypeScript и ESLint прошли. E2E включает IPv4/IPv6 на1440/320, предупреждение/переход к BFD с сохранением устройства и очисткой поиска, recovery/foreign/not-used/unknown; остальные7 проверяют состояния данных OSPF. Полную1481 UI/context регрессию157 повторно не запускали: она принята на предыдущем source, эта delta проверена отдельно. + +Переданный production source SHA256 совпал локально/на сервере. Frontend production build exit0; ux-bfd158 развёрнут с сохранённой private rollback env, backend ux-id156/PG сохранены. Немедленный curl после старта получил000 до готовности frontend; последующие две browser проверки1440/320 получили200, реальные catalog/server API200, page errors/overflow0 и отсутствие ложного предупреждения после очистки native fixtures. Позитивная native BFDv6 сессия этим блоком не заявляется. Пароли и RouterOS конфигурация не менялись; прежний закрытый SSH-туннель localhost3000/8000 восстановлен. + +Протоколы: [профильные проверки и сборка](ux-ui/acceptance/ospf-bfd-correlation-2026-10-12.json), [реальный развёрнутый интерфейс](ux-ui/acceptance/ospf-bfd-ipv6-smoke-2026-10-12.json). Установленные ReUI/Frame/base-nova переиспользованы без изменения primitives. + +| Референс | Схема доработки | +| --- | --- | +| [ReUI Data Grid Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Устройство → точный IPv6 peer/интерфейс → достоверное предупреждение → соответствующая BFD сессия | + +Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре, short loss/recovery и независимая сверка cleanup. Официальный [BFD manual](https://manual.mikrotik.com/docs/user-guides/routing-and-networking-protocols/unicast/bfd/) описывает IPv4/IPv6 и use-bfd, но текущая страница версии7.26 не заменяет эксперимент на стенде7.24.5. Sustained route gate, scale/IPv6 public WAN/outer и физическая резервность остаются непроверенными;12.5 открыт. ## 12.5.157 — общая регрессия после IPv6 и bigint исправлений (2026-10-12) diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index cdac6dd6..d51e21c5 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,8 +1,8 @@ # Оставшаяся внешняя приёмка — 2026-10-12 -Это актуальная матрица после 12.5.157. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.158. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. -Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-id156`, frontend `ux-ospf153`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. +Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-id156`, frontend `ux-bfd158`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. | Раздел | Подтверждено | Осталось / условие завершения | | --- | --- | --- | @@ -18,7 +18,7 @@ | Recursive routes | Production PUT/change/own history restore88, disabled guards, partial/unknown/applied outcomes, live формы/контекст | Автоматический rollback/retry, durable receipts и несколько экземпляров отсутствуют; PUT не является idempotent noop. Полная произвольная legacy catalog миграция не принята | | Diagnostics/terminal | Allowlist/native reads, Ping/trace/route/MTU/DNS, actual avg-rtt, disabled guards, JWT/live PC/mobile89; real default memory tail/log limits/API/UI133 | DNS использует backend resolver; MTU — ограниченная оценка, не гарантированный максимум. Stop ожидания не доказывает остановку RouterOS команды; arbitrary CLI и physical disconnect не приняты | | Portal/интеграции | Локальные и isolated JWT guards; UI/API error states в границах журналов | Настоящий Portal issuer/login/отзыв прав; RIPE SDK two-IP/no-fetch passed140, native IPv6 ULA flow pipeline passed145 (IPv4 transport), public IPv6 WAN/local licensed MaxMind/S3/container/certificate jobs и Gitea delivery требуют отдельных тестовых endpoints/аккаунтов. Не отправлять сообщения и не публиковать релиз без соответствующего поручения | -| Общая приёмка | Локальная12.3.83; UI1244/context221/compiled984 parity139; профильные build/E2E/live проверки последующих блоков | Traffic initial live mock-id gate passed141; IPv6 special ranges/cache passed142; unknown RIPE coordinates passed143; IPv6 synthetic UDP/worker/SQL passed144; native CHR ULA/IPFIX/API/UI passed145; ICMPv6/IPv6 endpoint labels passed146; HTTP DTO validation passed147; scoped flow catalog/serverId guards passed148; strict monthly calendar passed149; Sessions labels passed150; application GRE static IPv6 lifecycle151 passed; WireGuard static IPv6 lifecycle152 и disabled SQL/API gates passed; OSPF/BFD boundary/warning153 passed; OSPFv3 routes154 accepted in recorded bounds; BGP IPv6 basic155 passed; bigint ID/SQL guards156 passed; общая UI1260/context221/backend24 regression157 passed; последующие изменения проверять отдельно; scoped axe не означает полную WCAG сертификацию | +| Общая приёмка | Локальная12.3.83; UI1244/context221/compiled984 parity139; профильные build/E2E/live проверки последующих блоков | Traffic initial live mock-id gate passed141; IPv6 special ranges/cache passed142; unknown RIPE coordinates passed143; IPv6 synthetic UDP/worker/SQL passed144; native CHR ULA/IPFIX/API/UI passed145; ICMPv6/IPv6 endpoint labels passed146; HTTP DTO validation passed147; scoped flow catalog/serverId guards passed148; strict monthly calendar passed149; Sessions labels passed150; application GRE static IPv6 lifecycle151 passed; WireGuard static IPv6 lifecycle152 и disabled SQL/API gates passed; OSPF/BFD boundary/warning153 passed; OSPFv3 routes154 accepted in recorded bounds; BGP IPv6 basic155 passed; bigint ID/SQL guards156 passed; общая UI1260/context221/backend24 regression157 passed; IPv6 BFD correlation158 profile/deployed passed; последующие изменения проверять отдельно; scoped axe не означает полную WCAG сертификацию | Доказательства и точные ограничения: [полная история этапа12](ux-ui-stage-12.md), [внешний протокол](ux-ui-external-acceptance.md), [BGP93](ux-ui/acceptance/bgp-failover-2026-10-10.json), [паспорт стенда](ux-ui-test-server.md). Невыполненные пункты не являются все блокерами данного лабораторного сценария: для выпуска необходимо явно определить требуемые конфигурации и принять их либо согласовать ограничение. @@ -642,3 +642,19 @@ Permanent server-id.test.ts проверяет25 valid/invalid forms без SQL. Source TypeScript прошёл после остановки тестового Next dev. Все348 tracked изображения восстановлены из сохранённых перед прогоном текущих bytes, каждое сверено по SHA256; сохранены в том числе8 пользовательских GRE/VXLAN изменений. Сгенерированные тестами изображения не заменяют согласованные референсы. Production source не менялся, образы ux-id156/ux-ospf153 повторно не собирались и не развёртывались. RouterOS конфигурация и пароли этим блоком не изменялись. Протокол: [регрессия157](ux-ui/acceptance/regression-157-2026-10-12.json). Это локальная контролируемая регрессия интерфейса/контекста/backend, а не повтор native сценариев или приёмка внешних сервисов, клиентских ОС, масштаба и физических WAN. Исторический timeout orchestration154 остаётся в исходном протоколе. Этап12.5 открыт; следующий158 — проверка эквивалентных IPv6 адресов в сопоставлении OSPF/BFD. + +## 12.5.158 — корректное сопоставление IPv6 OSPF и BFD (2026-10-12) + +Строковое сравнение не связывало эквивалентные IPv6 адреса: например FE80:0000:0000:0000:0000:0000:0000:0002 и fe80::2. Теперь IPv6 приводится к канонической записи, optional zone должна совпадать с наблюдаемым интерфейсом. Hostnames, malformed IPv4/IPv6, пустая/чужая/повторная zone не создают совпадение. Stale duplicate с тем же точным device/interface/peer не исключается до проверки уникальности: наличие такой неоднозначности подавляет предупреждение. Single stale session также не доказывает конфликт. Это только корреляция наблюдений; состояния RouterOS и правила сети не менялись. + +5 unit tests,11 E2E, source TypeScript и ESLint прошли. E2E включает IPv4/IPv6 на1440/320, предупреждение/переход к BFD с сохранением устройства и очисткой поиска, recovery/foreign/not-used/unknown; остальные7 проверяют состояния данных OSPF. Полную1481 UI/context регрессию157 повторно не запускали: она принята на предыдущем source, эта delta проверена отдельно. + +Переданный production source SHA256 совпал локально/на сервере. Frontend production build exit0; ux-bfd158 развёрнут с сохранённой private rollback env, backend ux-id156/PG сохранены. Немедленный curl после старта получил000 до готовности frontend; последующие две browser проверки1440/320 получили200, реальные catalog/server API200, page errors/overflow0 и отсутствие ложного предупреждения после очистки native fixtures. Позитивная native BFDv6 сессия этим блоком не заявляется. Пароли и RouterOS конфигурация не менялись; прежний закрытый SSH-туннель localhost3000/8000 восстановлен. + +Протоколы: [профильные проверки и сборка](ux-ui/acceptance/ospf-bfd-correlation-2026-10-12.json), [реальный развёрнутый интерфейс](ux-ui/acceptance/ospf-bfd-ipv6-smoke-2026-10-12.json). Установленные ReUI/Frame/base-nova переиспользованы без изменения primitives. + +| Референс | Схема доработки | +| --- | --- | +| [ReUI Data Grid Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Устройство → точный IPv6 peer/интерфейс → достоверное предупреждение → соответствующая BFD сессия | + +Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре, short loss/recovery и независимая сверка cleanup. Официальный [BFD manual](https://manual.mikrotik.com/docs/user-guides/routing-and-networking-protocols/unicast/bfd/) описывает IPv4/IPv6 и use-bfd, но текущая страница версии7.26 не заменяет эксперимент на стенде7.24.5. Sustained route gate, scale/IPv6 public WAN/outer и физическая резервность остаются непроверенными;12.5 открыт. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index a016ecc4..036fb6bc 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1,6 +1,6 @@ # Этап 12: итоговая приёмка UX/UI -Актуальное продолжение 2026-10-12: завершён 12.5.157 — общая регрессия: 1260 UI + 221 context, все 24 backend профиля, source TypeScript прошли. 348 исходных изображений восстановлены и сверены по SHA256, включая пользовательские изменения. Runtime ux-id156/ux-ospf153 сохранён. Следующий 158 — проверить корректность сопоставления IPv6 OSPF/BFD; внешняя матрица 12.5 остаётся открытой. +Актуальное продолжение 2026-10-12: завершён 12.5.158 — OSPF/BFD сопоставляет эквивалентные IPv6 адреса, отвергает чужую zone/invalid IP и неоднозначные stale duplicate sessions. 5 unit/11 E2E/types/ESLint/frontend build/2 real deployed UI прошли; frontend ux-bfd158, backend ux-id156. Общая регрессия157 принята до этой delta. Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре с cleanup; внешняя матрица12.5 открыта. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -3032,3 +3032,19 @@ Permanent server-id.test.ts проверяет25 valid/invalid forms без SQL. Source TypeScript прошёл после остановки тестового Next dev. Все348 tracked изображения восстановлены из сохранённых перед прогоном текущих bytes, каждое сверено по SHA256; сохранены в том числе8 пользовательских GRE/VXLAN изменений. Сгенерированные тестами изображения не заменяют согласованные референсы. Production source не менялся, образы ux-id156/ux-ospf153 повторно не собирались и не развёртывались. RouterOS конфигурация и пароли этим блоком не изменялись. Протокол: [регрессия157](ux-ui/acceptance/regression-157-2026-10-12.json). Это локальная контролируемая регрессия интерфейса/контекста/backend, а не повтор native сценариев или приёмка внешних сервисов, клиентских ОС, масштаба и физических WAN. Исторический timeout orchestration154 остаётся в исходном протоколе. Этап12.5 открыт; следующий158 — проверка эквивалентных IPv6 адресов в сопоставлении OSPF/BFD. + +## 12.5.158 — корректное сопоставление IPv6 OSPF и BFD (2026-10-12) + +Строковое сравнение не связывало эквивалентные IPv6 адреса: например FE80:0000:0000:0000:0000:0000:0000:0002 и fe80::2. Теперь IPv6 приводится к канонической записи, optional zone должна совпадать с наблюдаемым интерфейсом. Hostnames, malformed IPv4/IPv6, пустая/чужая/повторная zone не создают совпадение. Stale duplicate с тем же точным device/interface/peer не исключается до проверки уникальности: наличие такой неоднозначности подавляет предупреждение. Single stale session также не доказывает конфликт. Это только корреляция наблюдений; состояния RouterOS и правила сети не менялись. + +5 unit tests,11 E2E, source TypeScript и ESLint прошли. E2E включает IPv4/IPv6 на1440/320, предупреждение/переход к BFD с сохранением устройства и очисткой поиска, recovery/foreign/not-used/unknown; остальные7 проверяют состояния данных OSPF. Полную1481 UI/context регрессию157 повторно не запускали: она принята на предыдущем source, эта delta проверена отдельно. + +Переданный production source SHA256 совпал локально/на сервере. Frontend production build exit0; ux-bfd158 развёрнут с сохранённой private rollback env, backend ux-id156/PG сохранены. Немедленный curl после старта получил000 до готовности frontend; последующие две browser проверки1440/320 получили200, реальные catalog/server API200, page errors/overflow0 и отсутствие ложного предупреждения после очистки native fixtures. Позитивная native BFDv6 сессия этим блоком не заявляется. Пароли и RouterOS конфигурация не менялись; прежний закрытый SSH-туннель localhost3000/8000 восстановлен. + +Протоколы: [профильные проверки и сборка](ux-ui/acceptance/ospf-bfd-correlation-2026-10-12.json), [реальный развёрнутый интерфейс](ux-ui/acceptance/ospf-bfd-ipv6-smoke-2026-10-12.json). Установленные ReUI/Frame/base-nova переиспользованы без изменения primitives. + +| Референс | Схема доработки | +| --- | --- | +| [ReUI Data Grid Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Устройство → точный IPv6 peer/интерфейс → достоверное предупреждение → соответствующая BFD сессия | + +Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре, short loss/recovery и независимая сверка cleanup. Официальный [BFD manual](https://manual.mikrotik.com/docs/user-guides/routing-and-networking-protocols/unicast/bfd/) описывает IPv4/IPv6 и use-bfd, но текущая страница версии7.26 не заменяет эксперимент на стенде7.24.5. Sustained route gate, scale/IPv6 public WAN/outer и физическая резервность остаются непроверенными;12.5 открыт. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index affe3b34..9fd4a769 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -1,6 +1,6 @@ # Тестовый сервер UX/UI — 2026-10-10 -Сервер161.104.46.222: завершён 12.5.157 — общая регрессия: 1260 UI + 221 context, все 24 backend профиля, source TypeScript прошли. 348 исходных изображений восстановлены и сверены по SHA256, включая пользовательские изменения. Runtime ux-id156/ux-ospf153 сохранён. Следующий 158 — проверить корректность сопоставления IPv6 OSPF/BFD; внешняя матрица 12.5 остаётся открытой. +Сервер161.104.46.222: завершён 12.5.158 — OSPF/BFD сопоставляет эквивалентные IPv6 адреса, отвергает чужую zone/invalid IP и неоднозначные stale duplicate sessions. 5 unit/11 E2E/types/ESLint/frontend build/2 real deployed UI прошли; frontend ux-bfd158, backend ux-id156. Общая регрессия157 принята до этой delta. Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре с cleanup; внешняя матрица12.5 открыта. | Параметр | Проверенное состояние | | --- | --- | @@ -14,7 +14,7 @@ | PostgreSQL | postgres:18-alpine,18.6;mmapp-test-postgres healthy;SELECT version() passed | | Данные | Отдельный Compose project mmapp-test,том mmapp-test_mmapp-pgdata и каталог ./data | | Доступ | PostgreSQL не публикуется;frontend3000/backend8000 привязаны к127.0.0.1 после запуска | -| Образы приложения | mmapp-test/backend:ux-id156 и mmapp-test/frontend:ux-ospf153; запущены | +| Образы приложения | mmapp-test/backend:ux-id156 и mmapp-test/frontend:ux-bfd158; запущены | Compose SHA256:3052bd6ab5d9865f97605cebfb5ff27a4410cd3357b81153a65a87fb7c92582f. OptionalBACKEND_IMAGE_TAG позволяетобновлятьbackendотдельно. Локальный и удалённый файлы совпали. Шаблоны: [Compose](../deploy/docker-compose.test.yml), [env без секретов](../deploy/env.test.example). @@ -1458,3 +1458,19 @@ Permanent server-id.test.ts проверяет25 valid/invalid forms без SQL. Source TypeScript прошёл после остановки тестового Next dev. Все348 tracked изображения восстановлены из сохранённых перед прогоном текущих bytes, каждое сверено по SHA256; сохранены в том числе8 пользовательских GRE/VXLAN изменений. Сгенерированные тестами изображения не заменяют согласованные референсы. Production source не менялся, образы ux-id156/ux-ospf153 повторно не собирались и не развёртывались. RouterOS конфигурация и пароли этим блоком не изменялись. Протокол: [регрессия157](ux-ui/acceptance/regression-157-2026-10-12.json). Это локальная контролируемая регрессия интерфейса/контекста/backend, а не повтор native сценариев или приёмка внешних сервисов, клиентских ОС, масштаба и физических WAN. Исторический timeout orchestration154 остаётся в исходном протоколе. Этап12.5 открыт; следующий158 — проверка эквивалентных IPv6 адресов в сопоставлении OSPF/BFD. + +## 12.5.158 — корректное сопоставление IPv6 OSPF и BFD (2026-10-12) + +Строковое сравнение не связывало эквивалентные IPv6 адреса: например FE80:0000:0000:0000:0000:0000:0000:0002 и fe80::2. Теперь IPv6 приводится к канонической записи, optional zone должна совпадать с наблюдаемым интерфейсом. Hostnames, malformed IPv4/IPv6, пустая/чужая/повторная zone не создают совпадение. Stale duplicate с тем же точным device/interface/peer не исключается до проверки уникальности: наличие такой неоднозначности подавляет предупреждение. Single stale session также не доказывает конфликт. Это только корреляция наблюдений; состояния RouterOS и правила сети не менялись. + +5 unit tests,11 E2E, source TypeScript и ESLint прошли. E2E включает IPv4/IPv6 на1440/320, предупреждение/переход к BFD с сохранением устройства и очисткой поиска, recovery/foreign/not-used/unknown; остальные7 проверяют состояния данных OSPF. Полную1481 UI/context регрессию157 повторно не запускали: она принята на предыдущем source, эта delta проверена отдельно. + +Переданный production source SHA256 совпал локально/на сервере. Frontend production build exit0; ux-bfd158 развёрнут с сохранённой private rollback env, backend ux-id156/PG сохранены. Немедленный curl после старта получил000 до готовности frontend; последующие две browser проверки1440/320 получили200, реальные catalog/server API200, page errors/overflow0 и отсутствие ложного предупреждения после очистки native fixtures. Позитивная native BFDv6 сессия этим блоком не заявляется. Пароли и RouterOS конфигурация не менялись; прежний закрытый SSH-туннель localhost3000/8000 восстановлен. + +Протоколы: [профильные проверки и сборка](ux-ui/acceptance/ospf-bfd-correlation-2026-10-12.json), [реальный развёрнутый интерфейс](ux-ui/acceptance/ospf-bfd-ipv6-smoke-2026-10-12.json). Установленные ReUI/Frame/base-nova переиспользованы без изменения primitives. + +| Референс | Схема доработки | +| --- | --- | +| [ReUI Data Grid Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Устройство → точный IPv6 peer/интерфейс → достоверное предупреждение → соответствующая BFD сессия | + +Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре, short loss/recovery и независимая сверка cleanup. Официальный [BFD manual](https://manual.mikrotik.com/docs/user-guides/routing-and-networking-protocols/unicast/bfd/) описывает IPv4/IPv6 и use-bfd, но текущая страница версии7.26 не заменяет эксперимент на стенде7.24.5. Sustained route gate, scale/IPv6 public WAN/outer и физическая резервность остаются непроверенными;12.5 открыт. diff --git a/docs/ux-ui/acceptance/ospf-bfd-correlation-2026-10-12.json b/docs/ux-ui/acceptance/ospf-bfd-correlation-2026-10-12.json new file mode 100644 index 00000000..ffb2227a --- /dev/null +++ b/docs/ux-ui/acceptance/ospf-bfd-correlation-2026-10-12.json @@ -0,0 +1,24 @@ +{ + "date": "2026-10-12", + "block": "12.5.158", + "unit": { + "passed": 5 + }, + "e2e": { + "passed": 11 + }, + "typescriptExitCode": 0, + "eslintExitCode": 0, + "frontendBuildExitCode": 0, + "sourceSha256": "66752dd8bf9378ffca13da825d14e3ebd5b4b7daffe29df5e5c367e08cf46fc8", + "remoteSourceHashMatched": true, + "runtime": { + "frontend": "ux-bfd158", + "backend": "ux-id156" + }, + "startup": { + "firstImmediateCurlStatus": "000", + "subsequentBrowserCasesHttp200": 2 + }, + "scope": "Canonical IPv6/zone/invalid address/duplicate guards; no native BFDv6 mutation or SLA acceptance; full regression157 predates this delta" +} diff --git a/docs/ux-ui/acceptance/ospf-bfd-ipv6-smoke-2026-10-12.json b/docs/ux-ui/acceptance/ospf-bfd-ipv6-smoke-2026-10-12.json new file mode 100644 index 00000000..580bba53 --- /dev/null +++ b/docs/ux-ui/acceptance/ospf-bfd-ipv6-smoke-2026-10-12.json @@ -0,0 +1,48 @@ +{ + "date": "2026-10-12", + "block": "12.5.158", + "runtime": { + "backend": "ux-id156", + "frontend": "ux-bfd158" + }, + "cases": [ + { + "width": 1440, + "status": 200, + "api": [ + { + "path": "/api/servers", + "status": 200 + }, + { + "path": "/api/ospf/catalog", + "status": 200 + } + ], + "pageErrors": [], + "noOverflow": true, + "noFalseConflict": true + }, + { + "width": 320, + "status": 200, + "api": [ + { + "path": "/api/ospf/catalog", + "status": 200 + }, + { + "path": "/api/servers", + "status": 200 + } + ], + "pageErrors": [], + "noOverflow": true, + "noFalseConflict": true + } + ], + "bounds": [ + "Read-only deployed UI with real backend after native fixture cleanup; no positive native BFDv6 claim", + "Positive IPv6 conflict and recovery covered by controlled E2E separately" + ] +} diff --git a/lib/ospf-state.test.ts b/lib/ospf-state.test.ts index d4be80d8..0fa5852e 100644 --- a/lib/ospf-state.test.ts +++ b/lib/ospf-state.test.ts @@ -29,3 +29,20 @@ test("topology does not infer Down from missing or transitional evidence", () => assert.equal(ospfNodeState(["2-Way", "Down"]), "2-Way") assert.equal(ospfNodeState(["Full", "Unknown"]), "Full") }) + +test("BFD correlation compares IPv6 addresses canonically within their interface scope", () => { + const neighbor = { localRouter: "1", localIface: "gre-own", neighborAddress: "FE80:0000:0000:0000:0000:0000:0000:0002%gre-own", state: "Full" as const } + const iface = { serverId: "1", interfaceName: "gre-own", active: true, useBfd: true } + const session = { serverId: "1", iface: "gre-own", remoteAddr: "fe80::2", state: "Down" as const, multihop: false } + assert.deepEqual(ospfBfdConflicts([neighbor], [iface], [session]), [neighbor]) + for (const remoteAddr of ["fe80::3", "fe80::2%other", "fe80::2%", "fe80::2%gre-own%extra"]) assert.deepEqual(ospfBfdConflicts([neighbor], [iface], [{ ...session, remoteAddr }]), []) + for (const neighborAddress of ["fe80::2%other", "fe80::2%", "fe80::2%gre-own%extra"]) assert.deepEqual(ospfBfdConflicts([{ ...neighbor, neighborAddress }], [iface], [session]), []) +}) + +test("invalid peer strings and stale duplicate sessions cannot prove an OSPF/BFD conflict", () => { + const neighbor = { localRouter: "1", localIface: "gre-own", neighborAddress: "198.18.153.2", state: "Full" as const } + const iface = { serverId: "1", interfaceName: "gre-own", active: true, useBfd: true } + const session = { serverId: "1", iface: "gre-own", remoteAddr: neighbor.neighborAddress, state: "Down" as const, multihop: false } + assert.deepEqual(ospfBfdConflicts([neighbor], [iface], [session, { ...session, dataUnknown: true }]), []) + for (const address of ["peer.example", "999.18.153.2", "0198.18.153.2", "fe80::invalid", ":::", "fe80::2/64", ""]) assert.deepEqual(ospfBfdConflicts([{ ...neighbor, neighborAddress: address }], [iface], [{ ...session, remoteAddr: address }]), []) +}) diff --git a/lib/ospf-state.ts b/lib/ospf-state.ts index eaf4f2dc..a73e2ddb 100644 --- a/lib/ospf-state.ts +++ b/lib/ospf-state.ts @@ -19,11 +19,22 @@ export function ospfBfdConflicts, sessions: Array<{ serverId: string; iface: string; remoteAddr: string; state: BfdState; multihop?: boolean | null; dataUnknown?: boolean }>, ): T[] { - const ip = (value: string) => value.split("%")[0]?.toLowerCase() ?? "" + const ip = (value: string, iface: string): string | null => { + const [address, zone, ...extra] = value.trim().split("%") + if (!address || extra.length || (zone !== undefined && zone !== iface)) return null + if (address.includes(":")) { + if (!/^[0-9a-f:.]+$/i.test(address)) return null + try { return new URL(`http://[${address}]/`).hostname } catch { return null } + } + const parts = address.split(".") + return parts.length === 4 && parts.every(p => /^(0|[1-9]\d{0,2})$/.test(p) && Number(p) <= 255) ? address : null + } return neighbors.filter(n => { if (n.dataUnknown || n.state !== "Full" || !n.neighborAddress || !n.localIface) return false if (!interfaces.some(i => !i.dataUnknown && i.active === true && i.useBfd === true && i.serverId === n.localRouter && i.interfaceName === n.localIface)) return false - const matching = sessions.filter(s => !s.dataUnknown && s.multihop === false && s.serverId === n.localRouter && s.iface === n.localIface && ip(s.remoteAddr) === ip(n.neighborAddress!)) - return matching.length === 1 && (matching[0]!.state === "Down" || matching[0]!.state === "AdminDown") + const peer = ip(n.neighborAddress, n.localIface) + if (!peer) return false + const matching = sessions.filter(s => s.multihop === false && s.serverId === n.localRouter && s.iface === n.localIface && ip(s.remoteAddr, s.iface) === peer) + return matching.length === 1 && !matching[0]!.dataUnknown && (matching[0]!.state === "Down" || matching[0]!.state === "AdminDown") }) } diff --git a/tests/e2e/ospf-bfd-conflict.spec.ts b/tests/e2e/ospf-bfd-conflict.spec.ts index fed56d40..b55b5a4f 100644 --- a/tests/e2e/ospf-bfd-conflict.spec.ts +++ b/tests/e2e/ospf-bfd-conflict.spec.ts @@ -1,12 +1,13 @@ import { test, expect } from "@playwright/test" for (const width of [1440, 320]) { - test(`OSPF Full/BFD Down: предупреждение, scope и recovery, ширина ${width}`, async ({ page }) => { + for (const ipv6 of [false, true]) { + test(`OSPF Full/BFD Down: предупреждение, scope и recovery, IPv${ipv6 ? 6 : 4}, ширина ${width}`, async ({ page }) => { await page.setViewportSize({ width, height: 1000 }) let phase = "down" const base = { serverId: 1, serverName: "CHR 1", serverSite: "", serverCountry: "RU" } - const neighbor = { ...base, id: "*n", address: "198.18.153.2", routerId: "198.18.253.2", instance: "own", area: "own", areaId: "0.0.0.0", interface: "gre-own", state: "Full", uptime: "1m", stateChanges: 1, priority: 1 } + const neighbor = { ...base, id: "*n", address: ipv6 ? "FE80:0000:0000:0000:0000:0000:0000:0002%gre-own" : "198.18.153.2", routerId: "198.18.253.2", instance: "own", area: "own", areaId: "0.0.0.0", interface: "gre-own", state: "Full", uptime: "1m", stateChanges: 1, priority: 1 } const iface = { ...base, id: "*i", instance: "own", area: "own", areaId: "0.0.0.0", interface: "gre-own", cost: 10, type: "ptp", disabled: false, inactive: false, priority: 1, helloInterval: 1, deadInterval: 20, useBfd: true } - const bfd = { ...base, id: "*b", localAddr: "198.18.153.1", remoteAddr: "198.18.153.2", interface: "gre-own", state: "Down", uptime: "1s", multihop: false, multiplier: 3, txInterval: 200, rxInterval: 200, holdTime: null, packetsRx: 10, packetsTx: 20, stateChanges: 1 } + const bfd = { ...base, id: "*b", localAddr: ipv6 ? "fe80::1" : "198.18.153.1", remoteAddr: ipv6 ? "fe80::2" : "198.18.153.2", interface: "gre-own", state: "Down", uptime: "1s", multihop: false, multiplier: 3, txInterval: 200, rxInterval: 200, holdTime: null, packetsRx: 10, packetsTx: 20, stateChanges: 1 } const errors: string[] = [] page.on("pageerror", e => errors.push(e.message)) await page.route("**/health", route => route.fulfill({ json: { ok: true } })) @@ -34,4 +35,5 @@ for (const width of [1440, 320]) { } expect(errors).toEqual([]) }) + } }