From b9a8615b8bfcec394a943c0ffece20e97d3eb267 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Fri, 9 Oct 2026 15:14:41 +0700 Subject: [PATCH] =?UTF-8?q?fix(ipsec):=20=D0=BF=D0=BE=D0=BA=D0=B0=D0=B7?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D1=82=D1=8C=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB?= =?UTF-8?q?=D1=8E=D1=87=D1=91=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BA=D0=BB=D0=B8?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=BE=D0=B2=20=D0=B8=20=D0=B0=D0=B4=D1=80?= =?UTF-8?q?=D0=B5=D1=81=20mode-config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/services/ipsec-live.ts | 26 ++-- backend/src/services/ipsec-state.test.ts | 17 +++ docs/ux-ui-external-acceptance.md | 4 +- docs/ux-ui-plan.md | 2 +- docs/ux-ui-progress.md | 18 ++- docs/ux-ui-stage-12.md | 14 ++ docs/ux-ui-test-server.md | 6 +- .../ipsec-mode-config-2026-10-09.json | 131 ++++++++++++++++++ 8 files changed, 204 insertions(+), 14 deletions(-) create mode 100644 docs/ux-ui/acceptance/ipsec-mode-config-2026-10-09.json diff --git a/backend/src/services/ipsec-live.ts b/backend/src/services/ipsec-live.ts index c721af3a..685629da 100644 --- a/backend/src/services/ipsec-live.ts +++ b/backend/src/services/ipsec-live.ts @@ -108,6 +108,11 @@ export interface RosIpsecActivePeer { "remote-id"?: string identity?: string established?: string + id?: string + state?: string + "remote-address"?: string + "dynamic-address"?: string + uptime?: string } type RosCertRow = Record @@ -238,10 +243,15 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] { const activeByRemote = new Map() for (const a of state.active) { - const rid = String(a["remote-id"] ?? "").trim() + if (a.state !== "established") continue + const rid = String(a.id ?? a["remote-id"] ?? "").trim() if (rid) activeByRemote.set(rid, a) } + // RouterOS 7 active-peers.id contains the received value without its configured type prefix. + const findActive = (remoteId: string) => activeByRemote.get(remoteId) + ?? activeByRemote.get(remoteId.replace(/^(key-id|fqdn|user-fqdn|address):/, "")) + const identityByRemoteCert = new Map() for (const i of state.identities) { const rc = (i["remote-certificate"] ?? "").trim() @@ -270,8 +280,8 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] { const comment = identity?.comment ?? "" const mcName = (identity?.["mode-config"] ?? "").trim() const cn = String(cert["common-name"] ?? "").trim() - const active = (cn ? activeByRemote.get(cn) : undefined) - ?? (identity?.["remote-id"] ? activeByRemote.get(String(identity["remote-id"]).trim()) : undefined) + const active = (cn ? findActive(cn) : undefined) + ?? (identity?.["remote-id"] ? findActive(String(identity["remote-id"]).trim()) : undefined) out.push({ id: `${server.id}:${identity ? "identity" : "cert"}:${String(identity?.[".id"] ?? cert[".id"] ?? certName)}`, rosId: `${identity ? "identity" : "cert"}:${String(identity?.[".id"] ?? cert[".id"] ?? certName)}`, @@ -289,8 +299,8 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] { modeConfigName: mcName || undefined, peerName: (identity?.peer ?? "").trim() || undefined, online: Boolean(active), - activeAddress: active?.address || undefined, - activeSince: active?.established || undefined, + activeAddress: active?.["dynamic-address"] || active?.["remote-address"] || active?.address || undefined, + activeSince: active?.uptime || active?.established || undefined, disabled: asBool(identity?.disabled), comment: comment || undefined, managed: isUser || isIpsecManagedComment(comment), @@ -306,7 +316,7 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] { if (!managed && !isIke2RemoteAccessIdentity(i, ike2PeerNames)) continue const mcName = (i["mode-config"] ?? "").trim() const remoteId = (i["remote-id"] ?? "").trim() - const active = remoteId ? activeByRemote.get(remoteId) : undefined + const active = remoteId ? findActive(remoteId) : undefined out.push({ id: `${server.id}:identity:${rosId}`, rosId: `identity:${rosId}`, @@ -320,8 +330,8 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] { modeConfigName: mcName || undefined, peerName: (i.peer ?? "").trim() || undefined, online: Boolean(active), - activeAddress: active?.address || undefined, - activeSince: active?.established || undefined, + activeAddress: active?.["dynamic-address"] || active?.["remote-address"] || active?.address || undefined, + activeSince: active?.uptime || active?.established || undefined, disabled: asBool(i.disabled), comment: i.comment || undefined, managed, diff --git a/backend/src/services/ipsec-state.test.ts b/backend/src/services/ipsec-state.test.ts index 9183d694..b6848c37 100644 --- a/backend/src/services/ipsec-state.test.ts +++ b/backend/src/services/ipsec-state.test.ts @@ -75,4 +75,21 @@ assert.equal(mapClients(state).find(c => c.certName === "client")?.name, "Existi let foreignCertificateWrites = 0 await assert.rejects(removeManagedIpsecServer({ get: async (path: string) => path === "/certificate" ? [{ ".id": "*CA", name: "ipsec-ca" }, { ".id": "*FOREIGN", name: "external-client", ca: "ipsec-ca" }] : [], delete: async () => { foreignCertificateWrites++ } } as unknown as MikrotikClient, true), /чужой сертификат/) assert.equal(foreignCertificateWrites, 0); checks++ +const sessionState = { ...state, certs: [], identities: [{ ".id": "*SESSION", peer: "ike", "auth-method": "pre-shared-key", "remote-id": "key-id:alice", comment: ipsecManagedComment("user=Alice") }], active: [] } as typeof state +for (const phase of ["starting", "established", "dying", undefined]) { + sessionState.active = [{ ".id": "*ACTIVE", id: "alice", state: phase, "remote-address": "192.0.2.2", "dynamic-address": "198.18.78.10", uptime: "1m" }] + const client = mapClients(sessionState)[0]! + assert.equal(client.online, phase === "established") + assert.equal(client.activeAddress, phase === "established" ? "198.18.78.10" : undefined) + assert.equal(client.activeSince, phase === "established" ? "1m" : undefined); checks++ +} +sessionState.active = [{ ".id": "*ACTIVE", id: "key-id:other", state: "established", "remote-address": "192.0.2.2" }] +assert.equal(mapClients(sessionState)[0]?.online, false); checks++ +sessionState.active = [{ ".id": "*ACTIVE", "remote-id": "key-id:alice", state: "established", "remote-address": "192.0.2.2", uptime: "2m" }] +assert.equal(mapClients(sessionState)[0]?.activeAddress, "192.0.2.2"); checks++ +for (const prefix of ["fqdn", "user-fqdn", "address", "unknown"]) { + sessionState.identities[0]!["remote-id"] = prefix + ":alice" + sessionState.active = [{ ".id": "*ACTIVE", id: "alice", state: "established" }] + assert.equal(mapClients(sessionState)[0]?.online, prefix !== "unknown"); checks++ +} console.log(`ipsec-state: ${checks} checks passed`) diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index 7ae29278..a53b94bd 100644 --- a/docs/ux-ui-external-acceptance.md +++ b/docs/ux-ui-external-acceptance.md @@ -1,6 +1,8 @@ # UX/UI: протокол внешней приёмки 12.5 -Статус на2026-10-09: backend/frontend ux-ipsec77, backend healthy; основной блок IPsec77 и VXLAN76 приняты в описанных границах. В12.5.67 исправленный Peer .conf принят как клиентский шаблон: API6/6, browser4/4, server endpoint и placeholders; настоящий RSC roundtrip через UI/native/handshake/Ping принят в12.5.68, .conf с явнымName/отказы400/409/сохранение формы приняты в70; поздний native rejection/подтверждённая компенсация/retry приняты в72; изолированный audit INSERT permission denial принят в74; остальные неизвестные исходы/DB faults открыты. Мобильная ширина WireGuard Sheets принята в12.5.64. Мобильная GRE форма и native сохранение на обоих CHR приняты в12.5.57. WireGuard handshake/короткий Ping/native API/read-only UI приняты в границах12.5.58; 12.5.59 воспроизвёл оставшиеся peers/IP; 12.5.60 развернул исправление и принял обычное удаление own WG интерфейса с peer/IPv4 адресом на обоих CHR. 12.5.62 принял полный WireGuard UI create/peer/disable/enable/Ping/delete на обоих CHR; устойчивое меню развёрнуто. Устойчивость меню GRE при live refresh на обоих CHR принята в12.5.55. GRE peer metadata и реальный lifecycle/API/UI/двусторонний Ping подтверждены в12.5.53. Browser retry/checkpoint на реальном HTTP/PG принят в границах12.5.43–45; Telegram sender responses подменены, реальная доставка не проверена. PG-1/2/3/4/5 приняты в описанных границах, PG-6 integrated для одного isolated instance, PG-7 real JWT/processcounts и browser restore passed. PG-8 real PG/native и browser unknown→history done приняты с fault injection после настоящего COMMIT. ROS-8/9 real API/SQL/native приняты в границах12.5.23; browser pair/duration change и delete приняты в12.5.24. ROS-2 authentication failure принят в12.5.25. PortalSSO, физический TCP disconnect, мультиэкземпляры и остальные ROS/Q/интеграции остаются открытыми. [Паспорт](ux-ui-test-server.md), [журнал](ux-ui-progress.md). VXLAN75: собственная native пара/Ping/catalog/URL/export приняты, create/delete API отсутствует; selected baseline восстановлен. +Статус на2026-10-09: backend ux-ipsec78/frontend ux-ipsec77, backend healthy; основной блок IPsec77 и VXLAN76 приняты в описанных границах. В12.5.67 исправленный Peer .conf принят как клиентский шаблон: API6/6, browser4/4, server endpoint и placeholders; настоящий RSC roundtrip через UI/native/handshake/Ping принят в12.5.68, .conf с явнымName/отказы400/409/сохранение формы приняты в70; поздний native rejection/подтверждённая компенсация/retry приняты в72; изолированный audit INSERT permission denial принят в74; остальные неизвестные исходы/DB faults открыты. Мобильная ширина WireGuard Sheets принята в12.5.64. Мобильная GRE форма и native сохранение на обоих CHR приняты в12.5.57. WireGuard handshake/короткий Ping/native API/read-only UI приняты в границах12.5.58; 12.5.59 воспроизвёл оставшиеся peers/IP; 12.5.60 развернул исправление и принял обычное удаление own WG интерфейса с peer/IPv4 адресом на обоих CHR. 12.5.62 принял полный WireGuard UI create/peer/disable/enable/Ping/delete на обоих CHR; устойчивое меню развёрнуто. Устойчивость меню GRE при live refresh на обоих CHR принята в12.5.55. GRE peer metadata и реальный lifecycle/API/UI/двусторонний Ping подтверждены в12.5.53. Browser retry/checkpoint на реальном HTTP/PG принят в границах12.5.43–45; Telegram sender responses подменены, реальная доставка не проверена. PG-1/2/3/4/5 приняты в описанных границах, PG-6 integrated для одного isolated instance, PG-7 real JWT/processcounts и browser restore passed. PG-8 real PG/native и browser unknown→history done приняты с fault injection после настоящего COMMIT. ROS-8/9 real API/SQL/native приняты в границах12.5.23; browser pair/duration change и delete приняты в12.5.24. ROS-2 authentication failure принят в12.5.25. PortalSSO, физический TCP disconnect, мультиэкземпляры и остальные ROS/Q/интеграции остаются открытыми. [Паспорт](ux-ui-test-server.md), [журнал](ux-ui-progress.md). VXLAN75: собственная native пара/Ping/catalog/URL/export приняты, create/delete API отсутствует; selected baseline восстановлен. + +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). ## Паспорт стенда diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 37d2d94a..9fca78b2 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,6 +1,6 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-09: 12.5.77 завершил укрупнённый основной блок IPsec: достоверное чтение, запрет опроса выключенных устройств, совместимый RouterOS7 мастер, раздельные ID клиентов, безопаснее удаление, URL устройства/вкладки, Docker обеих частей и реальная приёмка. Local30/30 + context6/6 + backend67, live browser4/4, PSK и сертификатный защищённый GRE/Ping3/3 на двух CHR; cleanup/DB controls passed. Runtime backend/frontend ux-ipsec77, version1.0.0-test.ipsec77. Следующий12.5.78 — остаточная профильная приёмка IPsec: сопоставление active-peer/online, выдача mode-config, поздние ошибки операций и история восстановления; затем маршрутизация. Этап12.5 открыт. +Актуальное продолжение 2026-10-09: 12.5.78 подтвердил реальное PSK IKEv2 подключение с выдачей mode-config и исправил ложный offline в каталоге клиентов. Backend ux-ipsec78, frontend ux-ipsec77; 77 backend-проверок, TypeScript/ESLint, одна backend Docker сборка и native/API приёмка; собственные объекты удалены. Следующий12.5.79 — сертификатный клиент/выдача mode-config, затем поздние ошибки операций и история восстановления. Этап12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-09. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index 8b62b1d1..65e55fc8 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-09: 12.5.77 завершил укрупнённый основной блок IPsec: достоверное чтение, запрет опроса выключенных устройств, совместимый RouterOS7 мастер, раздельные ID клиентов, безопаснее удаление, URL устройства/вкладки, Docker обеих частей и реальная приёмка. Local30/30 + context6/6 + backend67, live browser4/4, PSK и сертификатный защищённый GRE/Ping3/3 на двух CHR; cleanup/DB controls passed. Runtime backend/frontend ux-ipsec77, version1.0.0-test.ipsec77. Следующий12.5.78 — остаточная профильная приёмка IPsec: сопоставление active-peer/online, выдача mode-config, поздние ошибки операций и история восстановления; затем маршрутизация. Этап12.5 открыт. +Актуальное продолжение 2026-10-09: 12.5.78 подтвердил реальное PSK IKEv2 подключение с выдачей mode-config и исправил ложный offline в каталоге клиентов. Backend ux-ipsec78, frontend ux-ipsec77; 77 backend-проверок, TypeScript/ESLint, одна backend Docker сборка и native/API приёмка; собственные объекты удалены. Следующий12.5.79 — сертификатный клиент/выдача mode-config, затем поздние ошибки операций и история восстановления. Этап12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -36,7 +36,21 @@ | 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–77 и ограничения ниже. Runtime backend/frontend ux-ipsec77. | +| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–78 и ограничения ниже. Runtime backend ux-ipsec78/frontend ux-ipsec77. | + +## 12.5.78 — IPsec: реальный online и адрес mode-config (2026-10-09) + +**Результат.** Установленный PSK IKEv2 клиент отображался offline: RouterOS7 возвращает active-peers.id без префикса key-id:, а старый mapper ожидал remote-id; address/established также не соответствовали реальному ответу. Теперь используются id, state=established, dynamic-address (при наличии), remote-address и uptime. Для настроенного remote-id распознаются только известные префиксы key-id/fqdn/user-fqdn/address; starting/dying/отсутствующее состояние не подтверждают online. Изменены только ipsec-live.ts и профильный тест; UI-компоненты сохранены. + +**Реальное подтверждение.** Собственный responder на194.226.121.150 и initiator на104.165.244.7: PSK, IKEv2, SHA256/AES256/modp2048, отдельные profile/proposal/group/template/mode-config/pool/peer/identity. На responder RouterOS и развёрнутый GET /api/ipsec?serverId=1 подтвердили established, online=true, activeAddress=198.18.78.10, activeSince=0s. Это проверка выдачи адреса и корреляции PSK, не NAT/интернет/throughput. На initiator remote-id=auto не связывается с персональным клиентом, его online=false не считается принятой корреляцией. Сертификатный/DN вариант остаётся открытым. [Очищенный отчёт](ux-ui/acceptance/ipsec-mode-config-2026-10-09.json). + +**Проверки и очистка.** npm --prefix backend run test:ipsec: config passed +77 state checks; backend TypeScript, scoped ESLint, diff check passed. Native/API сценарий прошёл на новом backend. До удаления проверены точные ID и атрибуты всех собственных объектов; после — исходные ID восьми коллекций совпали на обоих CHR. Пароли не менялись; flash не затрагивался. Первые три попытки настройки fixture завершились authentication failure; чтение IPsec logs показало identity not found. Удаление избыточных явных responder my-id / initiator remote-id восстановило переговоры; это настройка тестовой пары, приложение не меняет my-id этим блоком. + +**Runtime и происхождение.** Единственная backend production сборка/deploy: mmapp-test/backend:ux-ipsec78, version1.0.0-test.ipsec78, image sha256:d25bb95996e7b917c8829a40e5d90cdcd75a4909e4a4654fcfc818f617262d81, healthy. Frontend остаётся ux-ipsec77; его сборка и общая UI-регрессия не повторялись, поскольку frontend не изменён. Backend context основан на предыдущем проверенном ipsec77 (production соответствует f80d9b7), с заменой ipsec-live.ts; SHA256 runtime исходника29b6843f9b6c80cc83af61ec44f3fdc99759ea656ba126722be3eb5f03501b0b совпал локально/удалённо. Архив двух backend-файлов3bf89cbefc57c3d0002da7285abaa300544700eb3ebeb9e5a83ad4622396ac3a; в нём тест на73 checks, ещё4 проверки префиксов добавлены локально после старта сборки и прошли — это не изменение production кода. Образ не заявляется сборкой из итогового Git SHA; label revision=ipsec78. Backup .env сохранён приватно на сервере; миграций БД нет. + +**Организация.** По замечанию пользователя о длительности предыдущего блока: одна подтверждённая проблема, профильные проверки, одна backend сборка, без повторной frontend сборки и полного набора E2E. Расход пятичасового окна на контрольной точке8%; это квота, не длительность работы. Один локальный коммит без push. Следующий шаг12.5.79: проверить сертификатный active-peer/DN и mode-config, затем late failure receipts/DB/transport и history restore. Остальные ограничения12.5.77 сохраняются. + +Референс: [RouterOS IPsec — Active Peers](https://help.mikrotik.com/docs/spaces/ROS/pages/11993097/IPsec), поля state/dynamic-address/remote-address/uptime. Приёмка подтверждена собственным native ответом и API, а не одной документацией. ## 12.5.77 — IPsec: основной раздел, RouterOS7 и реальная профильная приёмка (2026-10-09) diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 36f7b4f9..df907bbc 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1884,3 +1884,17 @@ flowchart LR ``` Остаточные границы: online/active-peer корреляция, настоящая выдача mode-config, NAT/интернет, IPv6, Windows/macOS/iOS/Android подключения, late failure receipts/DB/transport, history restore, многопроцессность, IPsec-specific live JWT/RBAC и throughput не приняты этим блоком. Основной раздел внедрён и принят в перечисленных сценариях; этап12.5 и эти профильные ограничения остаются открытыми. + +## 12.5.78 — IPsec: реальный online и адрес mode-config (2026-10-09) + +**Результат.** Установленный PSK IKEv2 клиент отображался offline: RouterOS7 возвращает active-peers.id без префикса key-id:, а старый mapper ожидал remote-id; address/established также не соответствовали реальному ответу. Теперь используются id, state=established, dynamic-address (при наличии), remote-address и uptime. Для настроенного remote-id распознаются только известные префиксы key-id/fqdn/user-fqdn/address; starting/dying/отсутствующее состояние не подтверждают online. Изменены только ipsec-live.ts и профильный тест; UI-компоненты сохранены. + +**Реальное подтверждение.** Собственный responder на194.226.121.150 и initiator на104.165.244.7: PSK, IKEv2, SHA256/AES256/modp2048, отдельные profile/proposal/group/template/mode-config/pool/peer/identity. На responder RouterOS и развёрнутый GET /api/ipsec?serverId=1 подтвердили established, online=true, activeAddress=198.18.78.10, activeSince=0s. Это проверка выдачи адреса и корреляции PSK, не NAT/интернет/throughput. На initiator remote-id=auto не связывается с персональным клиентом, его online=false не считается принятой корреляцией. Сертификатный/DN вариант остаётся открытым. [Очищенный отчёт](ux-ui/acceptance/ipsec-mode-config-2026-10-09.json). + +**Проверки и очистка.** npm --prefix backend run test:ipsec: config passed +77 state checks; backend TypeScript, scoped ESLint, diff check passed. Native/API сценарий прошёл на новом backend. До удаления проверены точные ID и атрибуты всех собственных объектов; после — исходные ID восьми коллекций совпали на обоих CHR. Пароли не менялись; flash не затрагивался. Первые три попытки настройки fixture завершились authentication failure; чтение IPsec logs показало identity not found. Удаление избыточных явных responder my-id / initiator remote-id восстановило переговоры; это настройка тестовой пары, приложение не меняет my-id этим блоком. + +**Runtime и происхождение.** Единственная backend production сборка/deploy: mmapp-test/backend:ux-ipsec78, version1.0.0-test.ipsec78, image sha256:d25bb95996e7b917c8829a40e5d90cdcd75a4909e4a4654fcfc818f617262d81, healthy. Frontend остаётся ux-ipsec77; его сборка и общая UI-регрессия не повторялись, поскольку frontend не изменён. Backend context основан на предыдущем проверенном ipsec77 (production соответствует f80d9b7), с заменой ipsec-live.ts; SHA256 runtime исходника29b6843f9b6c80cc83af61ec44f3fdc99759ea656ba126722be3eb5f03501b0b совпал локально/удалённо. Архив двух backend-файлов3bf89cbefc57c3d0002da7285abaa300544700eb3ebeb9e5a83ad4622396ac3a; в нём тест на73 checks, ещё4 проверки префиксов добавлены локально после старта сборки и прошли — это не изменение production кода. Образ не заявляется сборкой из итогового Git SHA; label revision=ipsec78. Backup .env сохранён приватно на сервере; миграций БД нет. + +**Организация.** По замечанию пользователя о длительности предыдущего блока: одна подтверждённая проблема, профильные проверки, одна backend сборка, без повторной frontend сборки и полного набора E2E. Расход пятичасового окна на контрольной точке8%; это квота, не длительность работы. Один локальный коммит без push. Следующий шаг12.5.79: проверить сертификатный active-peer/DN и mode-config, затем late failure receipts/DB/transport и history restore. Остальные ограничения12.5.77 сохраняются. + +Референс: [RouterOS IPsec — Active Peers](https://help.mikrotik.com/docs/spaces/ROS/pages/11993097/IPsec), поля state/dynamic-address/remote-address/uptime. Приёмка подтверждена собственным native ответом и API, а не одной документацией. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index 69cec086..9d165087 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -1,6 +1,6 @@ # Тестовый сервер UX/UI — 2026-10-09 -Сервер161.104.46.222 предоставлен для временного тестирования. Backend/frontend ux-ipsec77/version1.0.0-test.ipsec77; backend/PG healthy, frontend HTTP/browser passed. Основной блок IPsec77 принят в границах журнала, own fixtures/fake DB rows удалены; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние. +Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-ipsec78/version1.0.0-test.ipsec78, frontend ux-ipsec77/version1.0.0-test.ipsec77; backend/PG healthy, frontend HTTP/browser passed. Основной блок IPsec77 принят в границах журнала, own fixtures/fake DB rows удалены; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние. | Параметр | Проверенное состояние | | --- | --- | @@ -14,10 +14,12 @@ | 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-ipsec77 и mmapp-test/frontend:ux-ipsec77; запущены | +| Образы приложения | mmapp-test/backend:ux-ipsec78 и mmapp-test/frontend:ux-ipsec77; запущены | Compose SHA256:3052bd6ab5d9865f97605cebfb5ff27a4410cd3357b81153a65a87fb7c92582f. OptionalBACKEND_IMAGE_TAG позволяетобновлятьbackendотдельно. Локальный и удалённый файлы совпали. Шаблоны: [Compose](../deploy/docker-compose.test.yml), [env без секретов](../deploy/env.test.example). +IPsec78: PSK active-peer/online и mode-config приняты через native и развёрнутый API; точные собственные ID удалены, восемь коллекций восстановлены. Одна backend сборка, без изменения frontend; подробности и границы — в12.5.78 журнала. + ## Развёртывание приложения Чистые frontend/backend build contexts подготовлены по .gitea/workflows/docker.yml из закреплённого Git HEAD;образы собраны на сервере без push. Локально docker CLI сейчас отсутствует, на сервере доступен Docker. В корневом .dockerignore исключён backend, поэтому обычный backend build из корня не повторяет CI: использовать отдельный backend context, как main workflow. Не передавать .env.local,backend/.env,ключи и локальные node_modules/.next. diff --git a/docs/ux-ui/acceptance/ipsec-mode-config-2026-10-09.json b/docs/ux-ui/acceptance/ipsec-mode-config-2026-10-09.json new file mode 100644 index 00000000..b1ce3df2 --- /dev/null +++ b/docs/ux-ui/acceptance/ipsec-mode-config-2026-10-09.json @@ -0,0 +1,131 @@ +{ + "date": "2026-10-09", + "name": "mm-ipsec78-1791533486215", + "observations": [ + { + "serverId": 1, + "identities": [ + { + "peer": "mm-ipsec78-1791533486215", + "remote-id": "key-id:mm-ipsec78-1791533486215", + "auth-method": "pre-shared-key" + } + ], + "active": [ + { + "keys": [ + ".id", + "comment", + "dynamic-address", + "id", + "last-seen", + "local-address", + "natt-peer", + "ph2-total", + "port", + "ppk", + "remote-address", + "responder", + "rx-bytes", + "rx-packets", + "side", + "spii", + "spir", + "state", + "tx-bytes", + "tx-packets", + "uptime" + ], + ".id": "*1", + "id": "mm-ipsec78-1791533486215", + "state": "established", + "remote-address": "104.165.244.7", + "dynamic-address": "198.18.78.10", + "uptime": "0s", + "side": "responder" + } + ], + "catalog": [ + { + "name": "mm-ipsec78-1791533486215", + "remoteId": "key-id:mm-ipsec78-1791533486215", + "online": true, + "activeAddress": "198.18.78.10", + "activeSince": "0s" + } + ] + }, + { + "serverId": 2, + "identities": [ + { + "peer": "mm-ipsec78-1791533486215", + "my-id": "key-id:mm-ipsec78-1791533486215", + "auth-method": "pre-shared-key" + } + ], + "active": [ + { + "keys": [ + ".id", + "comment", + "id", + "last-seen", + "local-address", + "natt-peer", + "ph2-total", + "port", + "ppk", + "remote-address", + "responder", + "rx-bytes", + "rx-packets", + "side", + "spii", + "spir", + "state", + "tx-bytes", + "tx-packets", + "uptime" + ], + ".id": "*1", + "id": "194.226.121.150", + "state": "established", + "remote-address": "194.226.121.150", + "uptime": "0s", + "side": "initiator" + } + ], + "catalog": [ + { + "name": "mm-ipsec78-1791533486215", + "online": false + } + ] + } + ], + "cleanup": [ + { + "serverId": 1, + "/ip/ipsec/identity": true, + "/ip/ipsec/peer": true, + "/ip/ipsec/policy": true, + "/ip/ipsec/policy/group": true, + "/ip/ipsec/mode-config": true, + "/ip/pool": true, + "/ip/ipsec/proposal": true, + "/ip/ipsec/profile": true + }, + { + "serverId": 2, + "/ip/ipsec/identity": true, + "/ip/ipsec/peer": true, + "/ip/ipsec/policy": true, + "/ip/ipsec/policy/group": true, + "/ip/ipsec/mode-config": true, + "/ip/pool": true, + "/ip/ipsec/proposal": true, + "/ip/ipsec/profile": true + } + ] +} \ No newline at end of file