From 979dc3cfb036a9d4bd55d6cfc670def65fdb7c0c Mon Sep 17 00:00:00 2001 From: Denozordec Date: Sun, 11 Oct 2026 17:31:06 +0700 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=D1=83=D1=82=D0=BE=D1=87=D0=BD=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D0=BE=D0=B4=D0=BF=D0=B8=D1=81=D0=B8=20ICM?= =?UTF-8?q?Pv6=20=D0=B8=20=D0=BF=D0=BE=D1=80=D1=82=D0=BE=D0=B2=20IPv6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/services/traffic-flow-apps.ts | 1 + .../src/services/traffic-flow-parse.test.ts | 5 ++ backend/src/services/traffic-flow-parse.ts | 1 + .../data-grids/traffic-flows-data-grid.tsx | 2 +- docs/ux-ui-external-acceptance.md | 14 +++- docs/ux-ui-plan.md | 6 +- docs/ux-ui-progress.md | 14 +++- docs/ux-ui-remaining-acceptance.md | 16 +++- docs/ux-ui-stage-12.md | 12 ++- docs/ux-ui-test-server.md | 14 +++- .../ipv6-protocol-labels-2026-10-11.json | 39 +++++++++ .../traffic-labels-smoke-2026-10-11.json | 84 +++++++++++++++++++ tests/e2e/traffic-ipv6-labels.spec.ts | 41 +++++++++ 13 files changed, 235 insertions(+), 14 deletions(-) create mode 100644 docs/ux-ui/acceptance/ipv6-protocol-labels-2026-10-11.json create mode 100644 docs/ux-ui/acceptance/traffic-labels-smoke-2026-10-11.json create mode 100644 tests/e2e/traffic-ipv6-labels.spec.ts diff --git a/backend/src/services/traffic-flow-apps.ts b/backend/src/services/traffic-flow-apps.ts index dc9eb366..a39ccbea 100644 --- a/backend/src/services/traffic-flow-apps.ts +++ b/backend/src/services/traffic-flow-apps.ts @@ -53,6 +53,7 @@ const WELL_KNOWN: Record = { export function applicationName(proto: number, dstPort: number, srcPort = 0): string { if (proto === 1) return "ICMP" + if (proto === 58) return "ICMPv6" if (proto === 47) return "GRE" if (proto === 50) return "ESP" if (proto === 89) return "OSPF" diff --git a/backend/src/services/traffic-flow-parse.test.ts b/backend/src/services/traffic-flow-parse.test.ts index 016d3162..0f325d3d 100644 --- a/backend/src/services/traffic-flow-parse.test.ts +++ b/backend/src/services/traffic-flow-parse.test.ts @@ -1,4 +1,5 @@ import assert from "node:assert/strict" +import { applicationName } from "./traffic-flow-apps.js" import { parseFlowPacket, protoName, resetFlowTemplatesForTests, templateExporterCountForTests } from "./traffic-flow-parse.js" import { allocateOverlayAddress, FLOW_CACHE_ENTRIES, FLOW_TARGET_SRC_AUTO, usablePublicHost } from "./traffic-flow-overlay.js" @@ -26,6 +27,10 @@ assert.equal(flows[0]?.proto, 6) assert.equal(flows[0]?.bytes, 1500) assert.equal(flows[0]?.inIface, "1") assert.equal(protoName(6), "TCP") +assert.equal(protoName(58), "ICMPv6") +assert.equal(applicationName(58, 0), "ICMPv6") +assert.equal(applicationName(1, 0), "ICMP") +assert.equal(protoName(255), "255") assert.equal(parseFlowPacket(Buffer.from([0, 1]), "1.1.1.1").length, 0) const taken = new Set(["10.255.254.2"]) diff --git a/backend/src/services/traffic-flow-parse.ts b/backend/src/services/traffic-flow-parse.ts index c310a8e9..50c9ddfb 100644 --- a/backend/src/services/traffic-flow-parse.ts +++ b/backend/src/services/traffic-flow-parse.ts @@ -434,6 +434,7 @@ export function protoName(proto: number): string { case 17: return "UDP" case 47: return "GRE" case 50: return "ESP" + case 58: return "ICMPv6" case 89: return "OSPF" default: return String(proto) } diff --git a/components/data-grids/traffic-flows-data-grid.tsx b/components/data-grids/traffic-flows-data-grid.tsx index 97f3d27e..6a55db85 100644 --- a/components/data-grids/traffic-flows-data-grid.tsx +++ b/components/data-grids/traffic-flows-data-grid.tsx @@ -25,7 +25,7 @@ function formatBytes(n: number): string { function formatEndpoint(ip: string | undefined, port: number | undefined): string { const host = String(ip ?? "").trim() if (!host) return "—" - return port ? `${host}:${port}` : host + return port ? `${host.includes(":") ? `[${host}]` : host}:${port}` : host } function packetTuple(row: FlowTalkerDto): string { diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index 79d961b4..a6f81ebe 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-11: завершён12.5.145 — native CHR IPv6 ULA→IPFIX→production worker/SQL/API→frontend Sessions подтверждён; Ping5/5×2, PC/mobile DOM/API/no-overflow passed. Initial cleanup GET401 сохранён, recovery удалил2 exact-owned objects;12 collections×2/configs restored, own DB/container/ports/tunnel удалены. Backend ux-ipfix144/frontend ux-traffic141. Далее146 — понятные ICMPv6/IPv6 endpoint labels;12.5 открыт. +Актуальное продолжение 2026-10-11: завершён12.5.146 — ICMPv6 вместо58, IPv6 endpoint [IP]:port с сохранением IPv4/portless формата.3 backend profiles/source+candidate,30 E2E across attempts,984 outputs/types/ESLint и обе production builds passed; live PC/mobile loading passed. Runtime backend/frontend ux-labels146. Далее147 — schema validation HTTP analytics/monthly DTO, понятная ошибка вместо page crash.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-11: завершён12.5.145 — native CHR IPv6 ULA→IPFIX→production worker/SQL/API→frontend Sessions подтверждён; Ping5/5×2, PC/mobile DOM/API/no-overflow passed. Initial cleanup GET401 сохранён, recovery удалил2 exact-owned objects;12 collections×2/configs restored, own DB/container/ports/tunnel удалены. Backend ux-ipfix144/frontend ux-traffic141. Далее146 — понятные ICMPv6/IPv6 endpoint labels;12.5 открыт. +Актуальное продолжение 2026-10-11: завершён12.5.146 — ICMPv6 вместо58, IPv6 endpoint [IP]:port с сохранением IPv4/portless формата.3 backend profiles/source+candidate,30 E2E across attempts,984 outputs/types/ESLint и обе production builds passed; live PC/mobile loading passed. Runtime backend/frontend ux-labels146. Далее147 — schema validation HTTP analytics/monthly DTO, понятная ошибка вместо page crash.12.5 открыт. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). @@ -1567,3 +1567,13 @@ Backend ux-ipfix144 развёрнут, health healthy; frontend ux-traffic141 Own container удалён после проверки exact container ID; UDP48145/HTTP18145 и отдельный SSH tunnel закрыты, основной стенд backend ux-ipfix144/frontend ux-traffic141 healthy. Начальный неверный host port81245 был отвергнут до запуска/изменений, исправлен18145. [Native/API/cleanup receipt](ux-ui/acceptance/native-ipv6-ipfix-2026-10-11.json), [UI receipt](ux-ui/acceptance/native-ipv6-ipfix-ui-2026-10-11.json), [PC screenshot](ux-ui/screens/native-ipv6-ipfix145-1440-2026-10-11.png), [mobile screenshot](ux-ui/screens/native-ipv6-ipfix145-320-2026-10-11.png). Доказан IPv6 ULA inner/native IPFIX поверх IPv4 GRE/export transport, не public IPv6 WAN/outer или throughput/произвольные clients. На live UI ICMPv6 подписан numeric58, IPv6 endpoints с портом требуют однозначного bracket format; следующий146 — улучшить эти подписи, сохранив ReUI/Frame/base-nova.12.5 открыт. + +## 12.5.146 — понятные подписи ICMPv6 и адресов IPv6 с портами (2026-10-11) + +После native145 устранены две неоднозначные подписи. protoName/applicationName protocol58 теперь ICMPv6 вместо numeric58 или58/—. Existing ICMP, TCP/UDP, unknown numeric fallback сохранены. В существующей ReUI Sessions table IPv6 с портом выводится [IP]:port, включая packet-tuple tooltip; IPv4:port и IPv6 без порта не изменились. Frame/base-nova/vendor компоненты и порядок колонок сохранены. + +Parser/interface/classifier profiles прошли локально и в production candidate; последние выполнены без подключения к working PostgreSQL. Changed-file ESLint, source-only TypeScript, backend/frontend production Docker builds и984 emitted backend output comparison passed. Existing28 flow E2E прошли первым запуском. Два новых1440/320 tests сначала получили неверный fixture (sessions вместо conversationsList), что выявило отсутствие HTTP DTO guard; corrected fixture повторён отдельно,2 passed. Проверены visible IPv6 TCP/UDP endpoints, tooltip, portless ICMPv6, IPv4 compatibility и отсутствие document overflow. Итого30 принятых сценариев across attempts; первый failure не скрыт и прошедшие28 не повторялись. + +Backend/frontend ux-labels146 развёрнуты; backend/PG healthy, deployed traffic PC/mobile loading passed. [Label/check receipt](ux-ui/acceptance/ipv6-protocol-labels-2026-10-11.json), [readonly smoke](ux-ui/acceptance/traffic-labels-smoke-2026-10-11.json). Это live rendering/catalog smoke после label delta, а не повтор populated native145. Raw protocol integer сохранён в DB; talker/analytics response отображает его через новый protoName, schema/migration не требовались. Rollback env/images оставлены, device settings/passwords не менялись. + +Следующий147 — применить существующие contract schemas к HTTP analytics/monthly, как уже сделано для SSE/settings, чтобы malformed200 response давал existing error/retry state без ложных нулей или page crash.12.5 открыт. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 7dae719b..fe7a0f8f 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,12 +1,12 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-11: завершён12.5.145 — native CHR IPv6 ULA→IPFIX→production worker/SQL/API→frontend Sessions подтверждён; Ping5/5×2, PC/mobile DOM/API/no-overflow passed. Initial cleanup GET401 сохранён, recovery удалил2 exact-owned objects;12 collections×2/configs restored, own DB/container/ports/tunnel удалены. Backend ux-ipfix144/frontend ux-traffic141. Далее146 — понятные ICMPv6/IPv6 endpoint labels;12.5 открыт. +Актуальное продолжение 2026-10-11: завершён12.5.146 — ICMPv6 вместо58, IPv6 endpoint [IP]:port с сохранением IPv4/portless формата.3 backend profiles/source+candidate,30 E2E across attempts,984 outputs/types/ESLint и обе production builds passed; live PC/mobile loading passed. Runtime backend/frontend ux-labels146. Далее147 — schema validation HTTP analytics/monthly DTO, понятная ошибка вместо page crash.12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-10. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. ## Актуальная точка продолжения — 2026-10-10 -Актуальное продолжение 2026-10-11: завершён12.5.145 — native CHR IPv6 ULA→IPFIX→production worker/SQL/API→frontend Sessions подтверждён; Ping5/5×2, PC/mobile DOM/API/no-overflow passed. Initial cleanup GET401 сохранён, recovery удалил2 exact-owned objects;12 collections×2/configs restored, own DB/container/ports/tunnel удалены. Backend ux-ipfix144/frontend ux-traffic141. Далее146 — понятные ICMPv6/IPv6 endpoint labels;12.5 открыт. +Актуальное продолжение 2026-10-11: завершён12.5.146 — ICMPv6 вместо58, IPv6 endpoint [IP]:port с сохранением IPv4/portless формата.3 backend profiles/source+candidate,30 E2E across attempts,984 outputs/types/ESLint и обе production builds passed; live PC/mobile loading passed. Runtime backend/frontend ux-labels146. Далее147 — schema validation HTTP analytics/monthly DTO, понятная ошибка вместо page crash.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-11: завершён12.5.145 — native CHR IPv6 ULA→IPFIX→production worker/SQL/API→frontend Sessions подтверждён; Ping5/5×2, PC/mobile DOM/API/no-overflow passed. Initial cleanup GET401 сохранён, recovery удалил2 exact-owned objects;12 collections×2/configs restored, own DB/container/ports/tunnel удалены. Backend ux-ipfix144/frontend ux-traffic141. Далее146 — понятные ICMPv6/IPv6 endpoint labels;12.5 открыт. +Актуальное продолжение 2026-10-11: завершён12.5.146 — ICMPv6 вместо58, IPv6 endpoint [IP]:port с сохранением IPv4/portless формата.3 backend profiles/source+candidate,30 E2E across attempts,984 outputs/types/ESLint и обе production builds passed; live PC/mobile loading passed. Runtime backend/frontend ux-labels146. Далее147 — schema validation HTTP analytics/monthly DTO, понятная ошибка вместо page crash.12.5 открыт. Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md). diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index 33736850..eb1b0df7 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-11: завершён12.5.145 — native CHR IPv6 ULA→IPFIX→production worker/SQL/API→frontend Sessions подтверждён; Ping5/5×2, PC/mobile DOM/API/no-overflow passed. Initial cleanup GET401 сохранён, recovery удалил2 exact-owned objects;12 collections×2/configs restored, own DB/container/ports/tunnel удалены. Backend ux-ipfix144/frontend ux-traffic141. Далее146 — понятные ICMPv6/IPv6 endpoint labels;12.5 открыт. +Актуальное продолжение 2026-10-11: завершён12.5.146 — ICMPv6 вместо58, IPv6 endpoint [IP]:port с сохранением IPv4/portless формата.3 backend profiles/source+candidate,30 E2E across attempts,984 outputs/types/ESLint и обе production builds passed; live PC/mobile loading passed. Runtime backend/frontend ux-labels146. Далее147 — schema validation HTTP analytics/monthly DTO, понятная ошибка вместо page crash.12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -36,7 +36,17 @@ | 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–145 и ограничения ниже. Runtime backend ux-ipfix144/frontend ux-traffic141. | +| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–146 и ограничения ниже. Runtime backend/frontend ux-labels146. | + +## 12.5.146 — понятные подписи ICMPv6 и адресов IPv6 с портами (2026-10-11) + +После native145 устранены две неоднозначные подписи. protoName/applicationName protocol58 теперь ICMPv6 вместо numeric58 или58/—. Existing ICMP, TCP/UDP, unknown numeric fallback сохранены. В существующей ReUI Sessions table IPv6 с портом выводится [IP]:port, включая packet-tuple tooltip; IPv4:port и IPv6 без порта не изменились. Frame/base-nova/vendor компоненты и порядок колонок сохранены. + +Parser/interface/classifier profiles прошли локально и в production candidate; последние выполнены без подключения к working PostgreSQL. Changed-file ESLint, source-only TypeScript, backend/frontend production Docker builds и984 emitted backend output comparison passed. Existing28 flow E2E прошли первым запуском. Два новых1440/320 tests сначала получили неверный fixture (sessions вместо conversationsList), что выявило отсутствие HTTP DTO guard; corrected fixture повторён отдельно,2 passed. Проверены visible IPv6 TCP/UDP endpoints, tooltip, portless ICMPv6, IPv4 compatibility и отсутствие document overflow. Итого30 принятых сценариев across attempts; первый failure не скрыт и прошедшие28 не повторялись. + +Backend/frontend ux-labels146 развёрнуты; backend/PG healthy, deployed traffic PC/mobile loading passed. [Label/check receipt](ux-ui/acceptance/ipv6-protocol-labels-2026-10-11.json), [readonly smoke](ux-ui/acceptance/traffic-labels-smoke-2026-10-11.json). Это live rendering/catalog smoke после label delta, а не повтор populated native145. Raw protocol integer сохранён в DB; talker/analytics response отображает его через новый protoName, schema/migration не требовались. Rollback env/images оставлены, device settings/passwords не менялись. + +Следующий147 — применить существующие contract schemas к HTTP analytics/monthly, как уже сделано для SSE/settings, чтобы malformed200 response давал existing error/retry state без ложных нулей или page crash.12.5 открыт. ## 12.5.145 — настоящий RouterOS IPv6 IPFIX и заполненный интерфейс (2026-10-11) diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index 3bbdac43..06bc8c22 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,8 +1,8 @@ # Оставшаяся внешняя приёмка — 2026-10-11 -Это актуальная матрица после 12.5.145. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.146. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. -Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-ipfix144`, frontend `ux-traffic141`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты112 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. +Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-labels146`, frontend `ux-labels146`; 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 labels146; последующие изменения проверять отдельно; 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 validation147; последующие изменения проверять отдельно; 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). Невыполненные пункты не являются все блокерами данного лабораторного сценария: для выпуска необходимо явно определить требуемые конфигурации и принять их либо согласовать ограничение. @@ -482,3 +482,13 @@ Backend ux-ipfix144 развёрнут, health healthy; frontend ux-traffic141 Own container удалён после проверки exact container ID; UDP48145/HTTP18145 и отдельный SSH tunnel закрыты, основной стенд backend ux-ipfix144/frontend ux-traffic141 healthy. Начальный неверный host port81245 был отвергнут до запуска/изменений, исправлен18145. [Native/API/cleanup receipt](ux-ui/acceptance/native-ipv6-ipfix-2026-10-11.json), [UI receipt](ux-ui/acceptance/native-ipv6-ipfix-ui-2026-10-11.json), [PC screenshot](ux-ui/screens/native-ipv6-ipfix145-1440-2026-10-11.png), [mobile screenshot](ux-ui/screens/native-ipv6-ipfix145-320-2026-10-11.png). Доказан IPv6 ULA inner/native IPFIX поверх IPv4 GRE/export transport, не public IPv6 WAN/outer или throughput/произвольные clients. На live UI ICMPv6 подписан numeric58, IPv6 endpoints с портом требуют однозначного bracket format; следующий146 — улучшить эти подписи, сохранив ReUI/Frame/base-nova.12.5 открыт. + +## 12.5.146 — понятные подписи ICMPv6 и адресов IPv6 с портами (2026-10-11) + +После native145 устранены две неоднозначные подписи. protoName/applicationName protocol58 теперь ICMPv6 вместо numeric58 или58/—. Existing ICMP, TCP/UDP, unknown numeric fallback сохранены. В существующей ReUI Sessions table IPv6 с портом выводится [IP]:port, включая packet-tuple tooltip; IPv4:port и IPv6 без порта не изменились. Frame/base-nova/vendor компоненты и порядок колонок сохранены. + +Parser/interface/classifier profiles прошли локально и в production candidate; последние выполнены без подключения к working PostgreSQL. Changed-file ESLint, source-only TypeScript, backend/frontend production Docker builds и984 emitted backend output comparison passed. Existing28 flow E2E прошли первым запуском. Два новых1440/320 tests сначала получили неверный fixture (sessions вместо conversationsList), что выявило отсутствие HTTP DTO guard; corrected fixture повторён отдельно,2 passed. Проверены visible IPv6 TCP/UDP endpoints, tooltip, portless ICMPv6, IPv4 compatibility и отсутствие document overflow. Итого30 принятых сценариев across attempts; первый failure не скрыт и прошедшие28 не повторялись. + +Backend/frontend ux-labels146 развёрнуты; backend/PG healthy, deployed traffic PC/mobile loading passed. [Label/check receipt](ux-ui/acceptance/ipv6-protocol-labels-2026-10-11.json), [readonly smoke](ux-ui/acceptance/traffic-labels-smoke-2026-10-11.json). Это live rendering/catalog smoke после label delta, а не повтор populated native145. Raw protocol integer сохранён в DB; talker/analytics response отображает его через новый protoName, schema/migration не требовались. Rollback env/images оставлены, device settings/passwords не менялись. + +Следующий147 — применить существующие contract schemas к HTTP analytics/monthly, как уже сделано для SSE/settings, чтобы malformed200 response давал existing error/retry state без ложных нулей или page crash.12.5 открыт. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 1f7fdde9..f60f723d 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1,6 +1,6 @@ # Этап 12: итоговая приёмка UX/UI -Актуальное продолжение 2026-10-11: завершён12.5.145 — native CHR IPv6 ULA→IPFIX→production worker/SQL/API→frontend Sessions подтверждён; Ping5/5×2, PC/mobile DOM/API/no-overflow passed. Initial cleanup GET401 сохранён, recovery удалил2 exact-owned objects;12 collections×2/configs restored, own DB/container/ports/tunnel удалены. Backend ux-ipfix144/frontend ux-traffic141. Далее146 — понятные ICMPv6/IPv6 endpoint labels;12.5 открыт. +Актуальное продолжение 2026-10-11: завершён12.5.146 — ICMPv6 вместо58, IPv6 endpoint [IP]:port с сохранением IPv4/portless формата.3 backend profiles/source+candidate,30 E2E across attempts,984 outputs/types/ESLint и обе production builds passed; live PC/mobile loading passed. Runtime backend/frontend ux-labels146. Далее147 — schema validation HTTP analytics/monthly DTO, понятная ошибка вместо page crash.12.5 открыт. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -2872,3 +2872,13 @@ Backend ux-ipfix144 развёрнут, health healthy; frontend ux-traffic141 Own container удалён после проверки exact container ID; UDP48145/HTTP18145 и отдельный SSH tunnel закрыты, основной стенд backend ux-ipfix144/frontend ux-traffic141 healthy. Начальный неверный host port81245 был отвергнут до запуска/изменений, исправлен18145. [Native/API/cleanup receipt](ux-ui/acceptance/native-ipv6-ipfix-2026-10-11.json), [UI receipt](ux-ui/acceptance/native-ipv6-ipfix-ui-2026-10-11.json), [PC screenshot](ux-ui/screens/native-ipv6-ipfix145-1440-2026-10-11.png), [mobile screenshot](ux-ui/screens/native-ipv6-ipfix145-320-2026-10-11.png). Доказан IPv6 ULA inner/native IPFIX поверх IPv4 GRE/export transport, не public IPv6 WAN/outer или throughput/произвольные clients. На live UI ICMPv6 подписан numeric58, IPv6 endpoints с портом требуют однозначного bracket format; следующий146 — улучшить эти подписи, сохранив ReUI/Frame/base-nova.12.5 открыт. + +## 12.5.146 — понятные подписи ICMPv6 и адресов IPv6 с портами (2026-10-11) + +После native145 устранены две неоднозначные подписи. protoName/applicationName protocol58 теперь ICMPv6 вместо numeric58 или58/—. Existing ICMP, TCP/UDP, unknown numeric fallback сохранены. В существующей ReUI Sessions table IPv6 с портом выводится [IP]:port, включая packet-tuple tooltip; IPv4:port и IPv6 без порта не изменились. Frame/base-nova/vendor компоненты и порядок колонок сохранены. + +Parser/interface/classifier profiles прошли локально и в production candidate; последние выполнены без подключения к working PostgreSQL. Changed-file ESLint, source-only TypeScript, backend/frontend production Docker builds и984 emitted backend output comparison passed. Existing28 flow E2E прошли первым запуском. Два новых1440/320 tests сначала получили неверный fixture (sessions вместо conversationsList), что выявило отсутствие HTTP DTO guard; corrected fixture повторён отдельно,2 passed. Проверены visible IPv6 TCP/UDP endpoints, tooltip, portless ICMPv6, IPv4 compatibility и отсутствие document overflow. Итого30 принятых сценариев across attempts; первый failure не скрыт и прошедшие28 не повторялись. + +Backend/frontend ux-labels146 развёрнуты; backend/PG healthy, deployed traffic PC/mobile loading passed. [Label/check receipt](ux-ui/acceptance/ipv6-protocol-labels-2026-10-11.json), [readonly smoke](ux-ui/acceptance/traffic-labels-smoke-2026-10-11.json). Это live rendering/catalog smoke после label delta, а не повтор populated native145. Raw protocol integer сохранён в DB; talker/analytics response отображает его через новый protoName, schema/migration не требовались. Rollback env/images оставлены, device settings/passwords не менялись. + +Следующий147 — применить существующие contract schemas к HTTP analytics/monthly, как уже сделано для SSE/settings, чтобы malformed200 response давал existing error/retry state без ложных нулей или page crash.12.5 открыт. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index 4d8cd884..6f0ae37b 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.145 — native CHR IPv6 ULA→IPFIX→production worker/SQL/API→frontend Sessions подтверждён; Ping5/5×2, PC/mobile DOM/API/no-overflow passed. Initial cleanup GET401 сохранён, recovery удалил2 exact-owned objects;12 collections×2/configs restored, own DB/container/ports/tunnel удалены. Backend ux-ipfix144/frontend ux-traffic141. Далее146 — понятные ICMPv6/IPv6 endpoint labels;12.5 открыт. +Сервер161.104.46.222: завершён12.5.146 — ICMPv6 вместо58, IPv6 endpoint [IP]:port с сохранением IPv4/portless формата.3 backend profiles/source+candidate,30 E2E across attempts,984 outputs/types/ESLint и обе production builds passed; live PC/mobile loading passed. Runtime backend/frontend ux-labels146. Далее147 — schema validation HTTP analytics/monthly DTO, понятная ошибка вместо page crash.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-ipfix144 и mmapp-test/frontend:ux-traffic141; запущены | +| Образы приложения | mmapp-test/backend:ux-labels146 и mmapp-test/frontend:ux-labels146; запущены | Compose SHA256:3052bd6ab5d9865f97605cebfb5ff27a4410cd3357b81153a65a87fb7c92582f. OptionalBACKEND_IMAGE_TAG позволяетобновлятьbackendотдельно. Локальный и удалённый файлы совпали. Шаблоны: [Compose](../deploy/docker-compose.test.yml), [env без секретов](../deploy/env.test.example). @@ -1298,3 +1298,13 @@ Backend ux-ipfix144 развёрнут, health healthy; frontend ux-traffic141 Own container удалён после проверки exact container ID; UDP48145/HTTP18145 и отдельный SSH tunnel закрыты, основной стенд backend ux-ipfix144/frontend ux-traffic141 healthy. Начальный неверный host port81245 был отвергнут до запуска/изменений, исправлен18145. [Native/API/cleanup receipt](ux-ui/acceptance/native-ipv6-ipfix-2026-10-11.json), [UI receipt](ux-ui/acceptance/native-ipv6-ipfix-ui-2026-10-11.json), [PC screenshot](ux-ui/screens/native-ipv6-ipfix145-1440-2026-10-11.png), [mobile screenshot](ux-ui/screens/native-ipv6-ipfix145-320-2026-10-11.png). Доказан IPv6 ULA inner/native IPFIX поверх IPv4 GRE/export transport, не public IPv6 WAN/outer или throughput/произвольные clients. На live UI ICMPv6 подписан numeric58, IPv6 endpoints с портом требуют однозначного bracket format; следующий146 — улучшить эти подписи, сохранив ReUI/Frame/base-nova.12.5 открыт. + +## 12.5.146 — понятные подписи ICMPv6 и адресов IPv6 с портами (2026-10-11) + +После native145 устранены две неоднозначные подписи. protoName/applicationName protocol58 теперь ICMPv6 вместо numeric58 или58/—. Existing ICMP, TCP/UDP, unknown numeric fallback сохранены. В существующей ReUI Sessions table IPv6 с портом выводится [IP]:port, включая packet-tuple tooltip; IPv4:port и IPv6 без порта не изменились. Frame/base-nova/vendor компоненты и порядок колонок сохранены. + +Parser/interface/classifier profiles прошли локально и в production candidate; последние выполнены без подключения к working PostgreSQL. Changed-file ESLint, source-only TypeScript, backend/frontend production Docker builds и984 emitted backend output comparison passed. Existing28 flow E2E прошли первым запуском. Два новых1440/320 tests сначала получили неверный fixture (sessions вместо conversationsList), что выявило отсутствие HTTP DTO guard; corrected fixture повторён отдельно,2 passed. Проверены visible IPv6 TCP/UDP endpoints, tooltip, portless ICMPv6, IPv4 compatibility и отсутствие document overflow. Итого30 принятых сценариев across attempts; первый failure не скрыт и прошедшие28 не повторялись. + +Backend/frontend ux-labels146 развёрнуты; backend/PG healthy, deployed traffic PC/mobile loading passed. [Label/check receipt](ux-ui/acceptance/ipv6-protocol-labels-2026-10-11.json), [readonly smoke](ux-ui/acceptance/traffic-labels-smoke-2026-10-11.json). Это live rendering/catalog smoke после label delta, а не повтор populated native145. Raw protocol integer сохранён в DB; talker/analytics response отображает его через новый protoName, schema/migration не требовались. Rollback env/images оставлены, device settings/passwords не менялись. + +Следующий147 — применить существующие contract schemas к HTTP analytics/monthly, как уже сделано для SSE/settings, чтобы malformed200 response давал existing error/retry state без ложных нулей или page crash.12.5 открыт. diff --git a/docs/ux-ui/acceptance/ipv6-protocol-labels-2026-10-11.json b/docs/ux-ui/acceptance/ipv6-protocol-labels-2026-10-11.json new file mode 100644 index 00000000..69d4532f --- /dev/null +++ b/docs/ux-ui/acceptance/ipv6-protocol-labels-2026-10-11.json @@ -0,0 +1,39 @@ +{ + "date": "2026-10-11", + "block": "12.5.146", + "runtime": { + "backend": "ux-labels146", + "frontend": "ux-labels146", + "backendHealthy": true + }, + "checks": { + "sourceAndCandidateParserInterfaceClassifierProfilesPassed": true, + "eslintChangedFilesPassed": true, + "sourceOnlyTypesPassed": true, + "backendAndFrontendProductionBuildPassed": true, + "compiledBackendOutputsMatched": 984, + "e2eExistingPassed": 28, + "e2eNewViewportCasesPassed": 2, + "e2eAcceptedAcrossAttempts": 30 + }, + "initialE2e": { + "failed": 2, + "reason": "New fixture used sessions instead of conversationsList; incomplete DTO crashed unvalidated HTTP render path", + "existingPassed": 28 + }, + "retry": { + "onlyFailedCasesRepeated": true, + "passed": 2, + "fixtureMatchesActualConversationsList": true + }, + "bounds": [ + "Protocol58 and application58 now ICMPv6; IPv4 ICMP and unknown protocol fallback retained", + "IPv6 endpoints bracketed only when port is present; IPv4 and portless IPv6 formatting retained; packet tuple tooltip uses same formatter", + "Two controlled E2E viewports1440/320 check visible cells, IPv6 TCP/UDP ports, ICMPv6 and IPv4 compatibility plus no document overflow", + "Candidate profile checks ran without working PostgreSQL connection; no SQL fixtures or device mutations in this block", + "Live deployed smoke checks numeric-catalog traffic loading and rendering, not newly populated IPv6 labels; populated native IPv6 acceptance was145 before label delta", + "Existing persisted numeric raw protocol values are displayed through updated protoName in talker/analytics responses; no DB migration/schema/theme/vendor changes", + "Incomplete successful HTTP DTO vulnerability observed in initial fixture failure; next147 will reuse existing contract schema and error/retry UI", + "Both rollback images/private env retained; no push/password changes" + ] +} diff --git a/docs/ux-ui/acceptance/traffic-labels-smoke-2026-10-11.json b/docs/ux-ui/acceptance/traffic-labels-smoke-2026-10-11.json new file mode 100644 index 00000000..4ddf3ec0 --- /dev/null +++ b/docs/ux-ui/acceptance/traffic-labels-smoke-2026-10-11.json @@ -0,0 +1,84 @@ +{ + "date": "2026-10-11", + "block": "12.5.146", + "runtime": { + "backend": "ux-labels146", + "frontend": "ux-labels146" + }, + "checks": { + "readOnlyFrontendUnchanged": true, + "backendHealthy": true, + "backendProductionBuildPassed": true + }, + "cases": [ + { + "width": 1440, + "httpStatus": 200, + "api": [ + { + "path": "/api/traffic/users", + "status": 200 + }, + { + "path": "/api/traffic/bound-interfaces", + "status": 200 + }, + { + "path": "/api/traffic/servers", + "status": 200 + }, + { + "path": "/api/traffic/servers/1/live", + "status": 200 + }, + { + "path": "/api/traffic/servers/1", + "status": 200 + }, + { + "path": "/api/traffic/servers/1/interfaces", + "status": 200 + } + ], + "pageErrors": [], + "noOverflow": true + }, + { + "width": 320, + "httpStatus": 200, + "api": [ + { + "path": "/api/traffic/users", + "status": 200 + }, + { + "path": "/api/traffic/bound-interfaces", + "status": 200 + }, + { + "path": "/api/traffic/servers", + "status": 200 + }, + { + "path": "/api/traffic/servers/1/live", + "status": 200 + }, + { + "path": "/api/traffic/servers/1", + "status": 200 + }, + { + "path": "/api/traffic/servers/1/interfaces", + "status": 200 + } + ], + "pageErrors": [], + "noOverflow": true + } + ], + "bounds": [ + "Read-only initial loading with real current lab catalog; no full NetFlow ingestion or throughput claim", + "Catalog failure and pending loading checked by controlled E2E; numeric live server details/interfaces/SSE enabled only after confirmed catalog ownership", + "Interface filter remains selected on range changes; backend source switch invalidates prior catalog ownership" + ] +} diff --git a/tests/e2e/traffic-ipv6-labels.spec.ts b/tests/e2e/traffic-ipv6-labels.spec.ts new file mode 100644 index 00000000..63cd438c --- /dev/null +++ b/tests/e2e/traffic-ipv6-labels.spec.ts @@ -0,0 +1,41 @@ +import { test, expect } from '@playwright/test' + +for (const width of [1440, 320]) { + test(`Потоки IPv6: адрес с портом однозначен, ICMPv6 подписан/${width}`, async ({ page }) => { + await page.setViewportSize({ width, height: 1000 }) + const rows = [ + { src: 'fd00::10', dst: '2001:4860:4860::8888', srcPort: 50000, dstPort: 443, internetPeer: '2001:4860:4860::8888', internetPeerPort: 443, proto: 6, protoName: 'TCP', application: 'HTTPS' }, + { src: 'fd00::11', dst: '2606:4700:4700::1111', srcPort: 50001, dstPort: 53, internetPeer: '2606:4700:4700::1111', internetPeerPort: 53, proto: 17, protoName: 'UDP', application: 'DNS' }, + { src: 'fd00::12', dst: '2001:4860:4860::8844', srcPort: 0, dstPort: 0, internetPeer: '2001:4860:4860::8844', internetPeerPort: 0, proto: 58, protoName: 'ICMPv6', application: 'ICMPv6' }, + { src: '10.0.0.1', dst: '8.8.8.8', srcPort: 50002, dstPort: 443, internetPeer: '8.8.8.8', internetPeerPort: 443, proto: 6, protoName: 'TCP', application: 'HTTPS' }, + ].map(row => ({ ...row, serverId: '1', serverName: 'IPv6 exporter', clientIp: row.src, inIface: 'ether1', bps: 1000, bytes: 1000, packets: 10 })) + const stats = { bpsNow: 0, bytes: 4000, packets: 40, conversations: 4, uniqueSrc: 4, uniqueDst: 4, topCategory: 'Прочее', topProto: 'ICMPv6', rxSeries: [], txSeries: [], interfaces: [], ifaces: [], live: false, timeline: [], applications: [], categories: [], services: [], countries: [], asns: [], protocols: [], sources: [], destinations: [], conversationsList: rows, dedupApplied: false } + await page.route('**/health', route => route.fulfill({ json: { ok: true } })) + await page.route('**/api/**', route => { + const path = new URL(route.request().url()).pathname + if (path.endsWith('/live')) return route.fulfill({ status: 503, json: {} }) + const json = path === '/api/auth/config' ? { required: false } + : path === '/api/traffic/flow/analytics' ? stats + : path === '/api/traffic/flow/exporters' ? { exporters: [{ id: '1', name: 'IPv6 exporter', subtitle: '', site: 'TEST', country: '', status: 'online', rxNow: 0, txNow: 0, sessions: 4, bytes: 4000, rxSeries: [], txSeries: [] }] } + : path === '/api/traffic/flows' ? { exportersOnline: 1, bytesPerMin: 4000, uniqueSrc: 4, uniqueDst: 4, topProto: 'ICMPv6', talkers: rows, listenerBound: true } + : path === '/api/traffic/servers' ? { servers: [] } + : path === '/api/traffic/users' ? { users: [] } + : path === '/api/traffic/flow/clients' ? { clients: [] } + : path.endsWith('/interfaces') ? { interfaces: [] } + : path === '/api/servers' ? [] : {} + return route.fulfill({ json }) + }) + await page.goto('/traffic') + await page.getByRole('group', { name: 'Разделы трафика' }).getByRole('button', { name: 'Потоки', exact: true }).click() + await page.getByRole('tab', { name: 'Сессии', exact: true }).click() + const ipv6 = page.getByText('[2001:4860:4860::8888]:443', { exact: true }) + await ipv6.scrollIntoViewIfNeeded() + await expect(ipv6).toBeVisible() + await expect(ipv6).toHaveAttribute('title', '[fd00::10]:50000 → [2001:4860:4860::8888]:443') + await expect(page.getByText('[2606:4700:4700::1111]:53', { exact: true })).toBeVisible() + await expect(page.getByText('2001:4860:4860::8844', { exact: true })).toBeVisible() + await expect(page.getByText('8.8.8.8:443', { exact: true })).toBeVisible() + await expect(page.getByRole('cell', { name: 'ICMPv6', exact: true }).first()).toBeVisible() + expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true) + }) +}