diff --git a/backend/src/services/ipsec-live.ts b/backend/src/services/ipsec-live.ts index 7c5ece9f..7e7f26c5 100644 --- a/backend/src/services/ipsec-live.ts +++ b/backend/src/services/ipsec-live.ts @@ -304,7 +304,10 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] { const subject = routerOsCertificateDn(cert) const bySubject = subject && subjectCounts.get(subject) === 1 ? activeByRemote.get(subject) : undefined const uniqueCn = cn && cnCounts.get(cn) === 1 - const active = (uniqueCn ? findActive(cn) : undefined) ?? bySubject + // A literal CN is not a typed remote-id. It may also resemble another + // certificate's complete DN, in which case the bare-CN alias is unsafe. + const byCommonName = uniqueCn && !subjectCounts.has(cn) ? activeByRemote.get(cn) : undefined + const active = bySubject ?? byCommonName ?? (identity?.["remote-id"] ? findActive(String(identity["remote-id"]).trim()) : undefined) out.push({ id: `${server.id}:${identity ? "identity" : "cert"}:${String(identity?.[".id"] ?? cert[".id"] ?? certName)}`, diff --git a/backend/src/services/ipsec-state.test.ts b/backend/src/services/ipsec-state.test.ts index 4c057db7..9dd71eb5 100644 --- a/backend/src/services/ipsec-state.test.ts +++ b/backend/src/services/ipsec-state.test.ts @@ -129,4 +129,27 @@ state.active[0]!.id = 'C=US, S=New York, L=Albany, O=Example, Ltd, OU=QA+Operati assert.equal(mapClients(state).find(c => c.certName === "client")?.online, true); checks++ certificate.organization = "bad\nsubject" assert.equal(mapClients(state).find(c => c.certName === "client")?.online, false); checks++ +const namespaceState = { + ...state, + identities: [], + certs: [ + { ".id": "*PLAIN", name: "ipsec-user-plain", "common-name": "alice", ca: "ca", "key-usage": "tls-client" }, + { ".id": "*DNNAME", name: "ipsec-user-dn-name", "common-name": "CN=alice", ca: "ca", "key-usage": "tls-client" }, + { ".id": "*TYPEDNAME", name: "ipsec-user-typed-name", "common-name": "key-id:alice", ca: "ca", "key-usage": "tls-client" }, + ], + active: [{ ".id": "*NATIVE", id: "CN=alice", state: "established", "dynamic-address": "198.18.111.250" }], +} as typeof state +assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-plain")?.online, true); checks++ +assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-dn-name")?.online, false); checks++ +namespaceState.active[0]!.id = "alice" +assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-plain")?.online, true); checks++ +assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-typed-name")?.online, false); checks++ +namespaceState.active[0]!.id = "key-id:alice" +assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-typed-name")?.online, true); checks++ +// Type normalization belongs to an explicitly configured remote ID, not a CN. +namespaceState.identities = [{ ".id": "*EXPLICIT", peer: "ike", "auth-method": "digital-signature", "remote-certificate": "ipsec-user-plain", "remote-id": "fqdn:explicit.example", comment: "explicit certificate" }] +namespaceState.active[0]!.id = "explicit.example" +assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-plain")?.online, true); checks++ +namespaceState.identities[0]!["remote-id"] = "unknown:explicit.example" +assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-plain")?.online, false); 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 f389d937..043d4664 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-10: завершён12.5.110 — исправлено сопоставление сертификатного IPsec по полному DN (C/S/L/O/OU/CN, специальные символы), неоднозначные rendered subjects/active IDs не подтверждают online. Backend ux-dn110/version1.0.0-test.dn110, frontend ux-a11y101 прежний. State89/89, профильный IPsec/build/lint, live UI4/4 с проверкой actual theme; native established/assigned IP/catalog online и cleanup13 коллекций×2 passed. Все предварительные ошибки сохранены. Следующий111 — нестандартные IKE ID/границы сопоставления сертификатов; внешние Portal/Telegram требуют настройки и разрешения.12.5 открыт. +Актуальное продолжение 2026-10-10: завершён12.5.111 — буквальный CN больше не трактуется как typed Remote ID или чужой DN. Реальная одна сессия/два сертификата: только настоящий клиент online; explicit FQDN/SAN подключение подтверждено. Backend ux-id111/version1.0.0-test.id111, frontend ux-a11y101 прежний. State96/96, профильный IPsec/build/lint, live UI4/4 и cleanup13 коллекций×2 passed. Следующий112 — общие configured Remote IDs/коллизии aliases между identity и PSK; внешние Portal/Telegram ожидают настройки и разрешения.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). @@ -1074,3 +1074,21 @@ Production aggregate GET /api/gre/tunnels и /api/wireguard вернули со Границы: это сопоставление подтверждённой native сессии для данного формата RouterOS7.24.5, не общая DN/ASN.1 библиотека и не новая проверка encrypted data plane (77–82 остаются источником). Custom OIDs/другие форматы и IKE ID namespaces, клиентские ОС, полнаяPKI/policy-profile-proposal restore/IPv6/scale открыты. При неоднозначном rendered subject адрес не приписывается одному из клиентов. Следующий111 — нестандартные IKE ID и границы сопоставления сертификатных сессий; внешние интеграции всё ещё требуют настройки. Квота после live-блока: использовано33% пятичасового/67% недельного (значение до финальной записи). Референс семантики certificate ID: [официальная документация MikroTik IPsec](https://help.mikrotik.com/docs/spaces/ROS/pages/11993097/IPsec); фактический формат S/порядок/символы подтверждён native отчётом выше. + +## 12.5.111 — IPsec: буквальный CN, чужой DN и явно настроенный FQDN ID (2026-10-10) + +Исправлены две ошибки атрибуции. При одном native active-peers.id=CN=alice приложение могло пометить online также сертификат с буквальным common-name=CN=alice. Bare-CN fallback теперь не используется, если эта строка совпадает с полным subject другого сертификата; full-DN match имеет приоритет. Для common-name=key-id:alice прежний findActive удалял type prefix и приписывал ему сессию alice. Буквальный CN теперь сравнивается буквально через exact lookup; нормализация key-id/fqdn/user-fqdn/address сохраняется только для явно настроенного identity.remote-id. Сетевые операции, certificate auth/PKI, DTO, UI и ReUI компоненты не менялись. + +Red-before state test остановился на ложном online; после исправления state96/96. Семь новых assertions проверяют DN-looking CN, typed-looking CN, сохранение literal exact match, нормализацию explicit fqdn и отказ unsupported prefix. Полный test:ipsec (8 скриптов), backend/contracts production TypeScript build, ESLint двух изменённых файлов и diff check passed. Дополнительно actual compiled mapper ux-dn110 на synthetic alice/key-id:alice показывал обоих online; compiled ux-id111 показывает только alice. Это проверка mapper с подставленным снимком, не native допуск данного typed-looking CN как IKE ID. + +[Native before/after](ux-ui/acceptance/ipsec-session-id-2026-10-10.json): на собственных CHR7.24.5 созданы CA/server/client сертификаты и второй signed client certificate с common-name=CN=<имя первого>. Второй сертификат не экспортировался/не использовался инициатором; server identity строго ссылается на первый remote-certificate. На ux-dn110 native одна established сессия/адрес198.18.111.250, каталог давал online=true/тот же адрес обоим сертификатам. Эта red-attempt и её successful cleanup сохранены. После deploy ux-id111 тот же сценарий даёт только original online и decoy offline/без activeAddress. + +В той же собственной паре отдельно подтверждён explicit certificate FQDN ID: подписанный original cert имеет SAN DNS:<имя>.example; initiator my-id=fqdn:<имя>.example, responder remote-id=fqdn:<имя>.example. Отключён/включён только собственный client peer для нового handshake. Native established id содержит bare DNS value, lease198.18.111.250, production catalog originalOnline=true/decoyOnline=false. Это reserved test name в сертификате/ID, внешние DNS endpoints не использовались. Не утверждается независимый data-plane/throughput/SLA тест. + +[Live UI4/4](ux-ui/acceptance/browser-ipsec-id-2026-10-10.json):1280/320×dark/light с проверкой actual root class; original online address, decoy offline/без чужого адреса, reload, no page overflow, pageErrors0/applicationWrites0. Свежие скриншоты сохранены; desktop light просмотрен. Helper повторно находит только read-only locator при refresh, mutations не повторяет. Frontend ux-a11y101 прежний, общая UI регрессия не повторялась. + +[Source/runtime manifest](ux-ui/acceptance/ipsec-id-source-2026-10-10.json): build-id111 из audited build-dn110 +2 working overrides отHEAD2aa93ad, context byte hashes2/2 и changed compiled mapper byte hash совпали. Backend mmapp-test/backend:ux-id111/version1.0.0-test.id111/imagesha256:e9a5cf65433ed77b8c67991a556f3863a0e9609411a0e3e58d39463323c65414; labelid111 — stage marker, неGitSHA. Одна backend build, entrypoint/node check/pg_restore18.6/Compose wait passed; приватный pre-id111.env сохранён, прежний image доступен для rollback. Backend/PG healthy, frontend unchanged/HTTP/browser passed; миграции и DB test rows не создавались. + +Обе native attempts сравнили baseline13 коллекций×2 после удаления собственных сертификатов, imported chain с уникальными именами, peer/identity/profile/proposal/group/template/mode-config/files. Cleanup passed, logging/default/public/metadata routes и исходный195.195.195.195/32CHR2 сохранены; passwords прежние, SSH/обаCHR доступны. Private P12/PEM/pass files удалены, приватные ключи/секреты не сохранены в evidence. Native helpers используют aggregate GET /api/ipsec, не selected observed-revision write. + +Границы: shared configured Remote IDs, aliases нескольких identity/PSK с одинаковым bare value, arbitrary IKE ID types, custom DN/OIDs/client OS/full PKI/restore/IPv6 остаются открытыми. Этот блок принимает два конкретных CN fallback нарушения и одну real explicit-FQDN certificate сессию; не закрывает всю12.5. Следующий112 — коллизии configured Remote IDs между identity/PSK и безопасная атрибуция в этих случаях. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index ee5ce07d..d42d5ad4 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,12 +1,12 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-10: завершён12.5.110 — исправлено сопоставление сертификатного IPsec по полному DN (C/S/L/O/OU/CN, специальные символы), неоднозначные rendered subjects/active IDs не подтверждают online. Backend ux-dn110/version1.0.0-test.dn110, frontend ux-a11y101 прежний. State89/89, профильный IPsec/build/lint, live UI4/4 с проверкой actual theme; native established/assigned IP/catalog online и cleanup13 коллекций×2 passed. Все предварительные ошибки сохранены. Следующий111 — нестандартные IKE ID/границы сопоставления сертификатов; внешние Portal/Telegram требуют настройки и разрешения.12.5 открыт. +Актуальное продолжение 2026-10-10: завершён12.5.111 — буквальный CN больше не трактуется как typed Remote ID или чужой DN. Реальная одна сессия/два сертификата: только настоящий клиент online; explicit FQDN/SAN подключение подтверждено. Backend ux-id111/version1.0.0-test.id111, frontend ux-a11y101 прежний. State96/96, профильный IPsec/build/lint, live UI4/4 и cleanup13 коллекций×2 passed. Следующий112 — общие configured Remote IDs/коллизии aliases между identity и PSK; внешние Portal/Telegram ожидают настройки и разрешения.12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-10. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. ## Актуальная точка продолжения — 2026-10-10 -Актуальное продолжение 2026-10-10: завершён12.5.110 — исправлено сопоставление сертификатного IPsec по полному DN (C/S/L/O/OU/CN, специальные символы), неоднозначные rendered subjects/active IDs не подтверждают online. Backend ux-dn110/version1.0.0-test.dn110, frontend ux-a11y101 прежний. State89/89, профильный IPsec/build/lint, live UI4/4 с проверкой actual theme; native established/assigned IP/catalog online и cleanup13 коллекций×2 passed. Все предварительные ошибки сохранены. Следующий111 — нестандартные IKE ID/границы сопоставления сертификатов; внешние Portal/Telegram требуют настройки и разрешения.12.5 открыт. +Актуальное продолжение 2026-10-10: завершён12.5.111 — буквальный CN больше не трактуется как typed Remote ID или чужой DN. Реальная одна сессия/два сертификата: только настоящий клиент online; explicit FQDN/SAN подключение подтверждено. Backend ux-id111/version1.0.0-test.id111, frontend ux-a11y101 прежний. State96/96, профильный IPsec/build/lint, live UI4/4 и cleanup13 коллекций×2 passed. Следующий112 — общие configured Remote IDs/коллизии aliases между identity и PSK; внешние Portal/Telegram ожидают настройки и разрешения.12.5 открыт. Этапы0–11 завершены в локальных границах журнала. История выполненных внешних блоков и доказательства сохранены в [журнале](ux-ui-stage-12.md) и [протоколе](ux-ui-external-acceptance.md). Реальная Telegram доставка, Portal SSO, multi-instance и оставшиеся профильные сетевые ограничения открыты. diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index f34c00ed..a77065f9 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-10: завершён12.5.110 — исправлено сопоставление сертификатного IPsec по полному DN (C/S/L/O/OU/CN, специальные символы), неоднозначные rendered subjects/active IDs не подтверждают online. Backend ux-dn110/version1.0.0-test.dn110, frontend ux-a11y101 прежний. State89/89, профильный IPsec/build/lint, live UI4/4 с проверкой actual theme; native established/assigned IP/catalog online и cleanup13 коллекций×2 passed. Все предварительные ошибки сохранены. Следующий111 — нестандартные IKE ID/границы сопоставления сертификатов; внешние Portal/Telegram требуют настройки и разрешения.12.5 открыт. +Актуальное продолжение 2026-10-10: завершён12.5.111 — буквальный CN больше не трактуется как typed Remote ID или чужой DN. Реальная одна сессия/два сертификата: только настоящий клиент online; explicit FQDN/SAN подключение подтверждено. Backend ux-id111/version1.0.0-test.id111, frontend ux-a11y101 прежний. State96/96, профильный IPsec/build/lint, live UI4/4 и cleanup13 коллекций×2 passed. Следующий112 — общие configured Remote IDs/коллизии aliases между identity и PSK; внешние Portal/Telegram ожидают настройки и разрешения.12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -36,7 +36,25 @@ | 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–110 и ограничения ниже. Runtime backend ux-dn110/frontend ux-a11y101. | +| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–111 и ограничения ниже. Runtime backend ux-id111/frontend ux-a11y101. | + +## 12.5.111 — IPsec: буквальный CN, чужой DN и явно настроенный FQDN ID (2026-10-10) + +Исправлены две ошибки атрибуции. При одном native active-peers.id=CN=alice приложение могло пометить online также сертификат с буквальным common-name=CN=alice. Bare-CN fallback теперь не используется, если эта строка совпадает с полным subject другого сертификата; full-DN match имеет приоритет. Для common-name=key-id:alice прежний findActive удалял type prefix и приписывал ему сессию alice. Буквальный CN теперь сравнивается буквально через exact lookup; нормализация key-id/fqdn/user-fqdn/address сохраняется только для явно настроенного identity.remote-id. Сетевые операции, certificate auth/PKI, DTO, UI и ReUI компоненты не менялись. + +Red-before state test остановился на ложном online; после исправления state96/96. Семь новых assertions проверяют DN-looking CN, typed-looking CN, сохранение literal exact match, нормализацию explicit fqdn и отказ unsupported prefix. Полный test:ipsec (8 скриптов), backend/contracts production TypeScript build, ESLint двух изменённых файлов и diff check passed. Дополнительно actual compiled mapper ux-dn110 на synthetic alice/key-id:alice показывал обоих online; compiled ux-id111 показывает только alice. Это проверка mapper с подставленным снимком, не native допуск данного typed-looking CN как IKE ID. + +[Native before/after](ux-ui/acceptance/ipsec-session-id-2026-10-10.json): на собственных CHR7.24.5 созданы CA/server/client сертификаты и второй signed client certificate с common-name=CN=<имя первого>. Второй сертификат не экспортировался/не использовался инициатором; server identity строго ссылается на первый remote-certificate. На ux-dn110 native одна established сессия/адрес198.18.111.250, каталог давал online=true/тот же адрес обоим сертификатам. Эта red-attempt и её successful cleanup сохранены. После deploy ux-id111 тот же сценарий даёт только original online и decoy offline/без activeAddress. + +В той же собственной паре отдельно подтверждён explicit certificate FQDN ID: подписанный original cert имеет SAN DNS:<имя>.example; initiator my-id=fqdn:<имя>.example, responder remote-id=fqdn:<имя>.example. Отключён/включён только собственный client peer для нового handshake. Native established id содержит bare DNS value, lease198.18.111.250, production catalog originalOnline=true/decoyOnline=false. Это reserved test name в сертификате/ID, внешние DNS endpoints не использовались. Не утверждается независимый data-plane/throughput/SLA тест. + +[Live UI4/4](ux-ui/acceptance/browser-ipsec-id-2026-10-10.json):1280/320×dark/light с проверкой actual root class; original online address, decoy offline/без чужого адреса, reload, no page overflow, pageErrors0/applicationWrites0. Свежие скриншоты сохранены; desktop light просмотрен. Helper повторно находит только read-only locator при refresh, mutations не повторяет. Frontend ux-a11y101 прежний, общая UI регрессия не повторялась. + +[Source/runtime manifest](ux-ui/acceptance/ipsec-id-source-2026-10-10.json): build-id111 из audited build-dn110 +2 working overrides отHEAD2aa93ad, context byte hashes2/2 и changed compiled mapper byte hash совпали. Backend mmapp-test/backend:ux-id111/version1.0.0-test.id111/imagesha256:e9a5cf65433ed77b8c67991a556f3863a0e9609411a0e3e58d39463323c65414; labelid111 — stage marker, неGitSHA. Одна backend build, entrypoint/node check/pg_restore18.6/Compose wait passed; приватный pre-id111.env сохранён, прежний image доступен для rollback. Backend/PG healthy, frontend unchanged/HTTP/browser passed; миграции и DB test rows не создавались. + +Обе native attempts сравнили baseline13 коллекций×2 после удаления собственных сертификатов, imported chain с уникальными именами, peer/identity/profile/proposal/group/template/mode-config/files. Cleanup passed, logging/default/public/metadata routes и исходный195.195.195.195/32CHR2 сохранены; passwords прежние, SSH/обаCHR доступны. Private P12/PEM/pass files удалены, приватные ключи/секреты не сохранены в evidence. Native helpers используют aggregate GET /api/ipsec, не selected observed-revision write. + +Границы: shared configured Remote IDs, aliases нескольких identity/PSK с одинаковым bare value, arbitrary IKE ID types, custom DN/OIDs/client OS/full PKI/restore/IPv6 остаются открытыми. Этот блок принимает два конкретных CN fallback нарушения и одну real explicit-FQDN certificate сессию; не закрывает всю12.5. Следующий112 — коллизии configured Remote IDs между identity/PSK и безопасная атрибуция в этих случаях. ## 12.5.110 — IPsec: полный DN сертификата и достоверный online (2026-10-10) diff --git a/docs/ux-ui-remaining-acceptance.md b/docs/ux-ui-remaining-acceptance.md index cac9b206..6c1cddda 100644 --- a/docs/ux-ui-remaining-acceptance.md +++ b/docs/ux-ui-remaining-acceptance.md @@ -1,8 +1,8 @@ # Оставшаяся внешняя приёмка — 2026-10-10 -Это актуальная матрица после 12.5.110. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. +Это актуальная матрица после 12.5.111. Исторические записи сохраняют версии и ограничения на момент выполнения; поздние проверки ниже уточняют их. Этап 12.5 открыт. Успех в двух CHR и одном backend не означает приёмку всех конфигураций, интеграций или полной регрессии. -Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-dn110`, frontend `ux-a11y101`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты110 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. +Стенд: Debian13/Compose, PostgreSQL18.6, два CHR RouterOS7.24.5. Backend `ux-id111`, frontend `ux-a11y101`; production lab использует AUTH_REQUIRED=false. Подписанные JWT/RBAC проверялись в изолированных процессах. Все собственные объекты111 удалены, исходные13 коллекций×2 (включая logging/certificates/files/routes) проверены; пароли не менялись. | Раздел | Подтверждено | Осталось / условие завершения | | --- | --- | --- | @@ -12,7 +12,7 @@ | GRE | Native lifecycle, metadata, live формы/меню/URL/Ping53–57; GRE используется в OSPF/BGP/IPsec последующих блоков; native IPv6 ULA inner109 | IPv6 outer и application IPv6 interface address lifecycle, независимые WAN, масштаб и длительное восстановление; принятие GRE не означает приёмку всех сценариев автоматического расписания | | WireGuard | Native handshake/data plane58, deletion60, live create/peer/disable/enable/delete62, mobile64, export/import67–74; native IPv6 ULA inner/allowedIps/handshake109 | Клиентские ОС и произвольные конфигурации, IPv6 outer/scale и application IPv6 interface address lifecycle, физический lost ACK и устойчивое восстановление; `.conf` с placeholders — шаблон, не принятый клиентский tunnel | | VXLAN | Собственная пара/private Ping/catalog/URL/export75–76; bridge/FDB/port loss/recovery107; IPv6 ULA inner по IPv4 outer108 | API приложения read-only: create/delete проверены native. IPv6 outer, масштаб/производительность, профильные mutation RBAC/concurrency отдельно не приняты | -| IPsec | PSK и сертификатное шифрование77–82, active peer/online/mode-config, scoped NAT/group, partial/unknown/applied receipts, restore conflicts, JWT; full DN/специальные символы/online110 | Клиентские Windows/macOS/iOS/Android, прочие DN форматы/custom OIDs/IKE ID namespaces, полная PKI и policy/profile/proposal restore, физический disconnect, durable retry/multi-instance, IPv6/maximum throughput | +| IPsec | PSK и сертификатное шифрование77–82, active peer/online/mode-config, scoped NAT/group, partial/unknown/applied receipts, restore conflicts, JWT; full DN/специальные символы/online110; literal CN namespace guards и explicit FQDN111 | Клиентские Windows/macOS/iOS/Android, прочие DN форматы/custom OIDs/IKE ID namespaces, полная PKI и policy/profile/proposal restore, физический disconnect, durable retry/multi-instance, IPv6/maximum throughput | | OSPF/BFD | Real Full/own routes84–85, раздельные наблюдения BFD86, effective disabled/optimizer cost/partial/RBAC87, alternate path90 и CIDR91 | Sustained BFD-only gate не принят: в86 сосед мог вновь статьFull при доступныхHello. В90 переходный Ping18/40 с55% loss: бесшовность не принята. REST timing — наблюдаемая граница, не SLA; IPv6/scale/independent WAN открыты | | BGP | Established83, exact /32 exchange/API/UI/administrative withdrawal92, BFD primary GRE loss/alternate/recovery93 | Hold timer/TCP loss безBFD принят104; packet loss в переходе, разные внешние peers/WAN policy, IPv6/scale. Два логических пути используют тот же public WAN; physical redundancy не принята | | Recursive routes | Production PUT/change/own history restore88, disabled guards, partial/unknown/applied outcomes, live формы/контекст | Автоматический rollback/retry, durable receipts и несколько экземпляров отсутствуют; PUT не является idempotent noop. Полная произвольная legacy catalog миграция не принята | @@ -25,7 +25,7 @@ ## Следующая последовательность 1. **12.5.95 завершён:** [source/context/compiled audit](ux-ui/acceptance/deployment-source-audit-2026-10-10.json), production source drift не выявлен; нормализация и исключения явно указаны. -2. **12.5.96 timezone завершён:** [6 live UI cases](ux-ui/acceptance/browser-speed-timezone-2026-10-10.json). 97 HTTP receipt disconnect принят: [протокол](ux-ui/acceptance/speed-disconnect-2026-10-10.json). 98 сообщение неизвестного native результата исправлено/развёрнуто. 99 main/context завершён с точной записью одного failure/delta;100 transport и101 accessibility исправлены/развёрнуты.102 malformed PATCH исправлен/принят.103 packet rows/public/GRE приняты в границах коротких samples; initial loss/root cause остаётся открытым.104 hold/TCP loss/recovery принят.105 source/runtime/evidence сверка passed.106 read-only readiness: auth disabled/Portal localhost/bot and chat unconfigured.107 — native bridge/FDB/loss/recovery принят.108 — IPv6 inner VXLAN принят, initial0/3 и1/3 остаются в протоколе;109 — native GRE/WireGuard IPv6 inner принят; readers /ip/address не показывают native IPv6 interface addresses.110 — полный native DN/online исправлен и принят;111 — нестандартные IKE ID/границы сопоставления. Реальные интеграции требуют тестовых доступов и отдельного разрешения на сообщение. +2. **12.5.96 timezone завершён:** [6 live UI cases](ux-ui/acceptance/browser-speed-timezone-2026-10-10.json). 97 HTTP receipt disconnect принят: [протокол](ux-ui/acceptance/speed-disconnect-2026-10-10.json). 98 сообщение неизвестного native результата исправлено/развёрнуто. 99 main/context завершён с точной записью одного failure/delta;100 transport и101 accessibility исправлены/развёрнуты.102 malformed PATCH исправлен/принят.103 packet rows/public/GRE приняты в границах коротких samples; initial loss/root cause остаётся открытым.104 hold/TCP loss/recovery принят.105 source/runtime/evidence сверка passed.106 read-only readiness: auth disabled/Portal localhost/bot and chat unconfigured.107 — native bridge/FDB/loss/recovery принят.108 — IPv6 inner VXLAN принят, initial0/3 и1/3 остаются в протоколе;109 — native GRE/WireGuard IPv6 inner принят; readers /ip/address не показывают native IPv6 interface addresses.110 — полный native DN/online исправлен и принят;111 — literal CN guards/real explicit FQDN accepted;112 — shared configured ID/identity-PSK aliases. Реальные интеграции требуют тестовых доступов и отдельного разрешения на сообщение. 3. **Заключительный профильный контроль:** после последнего исправления собрать только затронутую часть, проверить её live и обновить матрицу. Общую регрессию выполнить один раз на согласованном runtime. 4. **Внешние зависимости:** Telegram/Portal/client OS/multi-WAN/scale проходят отдельную приёмку при наличии нужных аккаунтов, устройств и разрешений. Лабораторный результат двух CHR не закрывает их автоматически. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 577c8a24..77e436e8 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -1,6 +1,6 @@ # Этап 12: итоговая приёмка UX/UI -Актуальное продолжение 2026-10-10: завершён12.5.110 — исправлено сопоставление сертификатного IPsec по полному DN (C/S/L/O/OU/CN, специальные символы), неоднозначные rendered subjects/active IDs не подтверждают online. Backend ux-dn110/version1.0.0-test.dn110, frontend ux-a11y101 прежний. State89/89, профильный IPsec/build/lint, live UI4/4 с проверкой actual theme; native established/assigned IP/catalog online и cleanup13 коллекций×2 passed. Все предварительные ошибки сохранены. Следующий111 — нестандартные IKE ID/границы сопоставления сертификатов; внешние Portal/Telegram требуют настройки и разрешения.12.5 открыт. +Актуальное продолжение 2026-10-10: завершён12.5.111 — буквальный CN больше не трактуется как typed Remote ID или чужой DN. Реальная одна сессия/два сертификата: только настоящий клиент online; explicit FQDN/SAN подключение подтверждено. Backend ux-id111/version1.0.0-test.id111, frontend ux-a11y101 прежний. State96/96, профильный IPsec/build/lint, live UI4/4 и cleanup13 коллекций×2 passed. Следующий112 — общие configured Remote IDs/коллизии aliases между identity и PSK; внешние Portal/Telegram ожидают настройки и разрешения.12.5 открыт. План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push. @@ -2379,3 +2379,21 @@ Production aggregate GET /api/gre/tunnels и /api/wireguard вернули со Границы: это сопоставление подтверждённой native сессии для данного формата RouterOS7.24.5, не общая DN/ASN.1 библиотека и не новая проверка encrypted data plane (77–82 остаются источником). Custom OIDs/другие форматы и IKE ID namespaces, клиентские ОС, полнаяPKI/policy-profile-proposal restore/IPv6/scale открыты. При неоднозначном rendered subject адрес не приписывается одному из клиентов. Следующий111 — нестандартные IKE ID и границы сопоставления сертификатных сессий; внешние интеграции всё ещё требуют настройки. Квота после live-блока: использовано33% пятичасового/67% недельного (значение до финальной записи). Референс семантики certificate ID: [официальная документация MikroTik IPsec](https://help.mikrotik.com/docs/spaces/ROS/pages/11993097/IPsec); фактический формат S/порядок/символы подтверждён native отчётом выше. + +## 12.5.111 — IPsec: буквальный CN, чужой DN и явно настроенный FQDN ID (2026-10-10) + +Исправлены две ошибки атрибуции. При одном native active-peers.id=CN=alice приложение могло пометить online также сертификат с буквальным common-name=CN=alice. Bare-CN fallback теперь не используется, если эта строка совпадает с полным subject другого сертификата; full-DN match имеет приоритет. Для common-name=key-id:alice прежний findActive удалял type prefix и приписывал ему сессию alice. Буквальный CN теперь сравнивается буквально через exact lookup; нормализация key-id/fqdn/user-fqdn/address сохраняется только для явно настроенного identity.remote-id. Сетевые операции, certificate auth/PKI, DTO, UI и ReUI компоненты не менялись. + +Red-before state test остановился на ложном online; после исправления state96/96. Семь новых assertions проверяют DN-looking CN, typed-looking CN, сохранение literal exact match, нормализацию explicit fqdn и отказ unsupported prefix. Полный test:ipsec (8 скриптов), backend/contracts production TypeScript build, ESLint двух изменённых файлов и diff check passed. Дополнительно actual compiled mapper ux-dn110 на synthetic alice/key-id:alice показывал обоих online; compiled ux-id111 показывает только alice. Это проверка mapper с подставленным снимком, не native допуск данного typed-looking CN как IKE ID. + +[Native before/after](ux-ui/acceptance/ipsec-session-id-2026-10-10.json): на собственных CHR7.24.5 созданы CA/server/client сертификаты и второй signed client certificate с common-name=CN=<имя первого>. Второй сертификат не экспортировался/не использовался инициатором; server identity строго ссылается на первый remote-certificate. На ux-dn110 native одна established сессия/адрес198.18.111.250, каталог давал online=true/тот же адрес обоим сертификатам. Эта red-attempt и её successful cleanup сохранены. После deploy ux-id111 тот же сценарий даёт только original online и decoy offline/без activeAddress. + +В той же собственной паре отдельно подтверждён explicit certificate FQDN ID: подписанный original cert имеет SAN DNS:<имя>.example; initiator my-id=fqdn:<имя>.example, responder remote-id=fqdn:<имя>.example. Отключён/включён только собственный client peer для нового handshake. Native established id содержит bare DNS value, lease198.18.111.250, production catalog originalOnline=true/decoyOnline=false. Это reserved test name в сертификате/ID, внешние DNS endpoints не использовались. Не утверждается независимый data-plane/throughput/SLA тест. + +[Live UI4/4](ux-ui/acceptance/browser-ipsec-id-2026-10-10.json):1280/320×dark/light с проверкой actual root class; original online address, decoy offline/без чужого адреса, reload, no page overflow, pageErrors0/applicationWrites0. Свежие скриншоты сохранены; desktop light просмотрен. Helper повторно находит только read-only locator при refresh, mutations не повторяет. Frontend ux-a11y101 прежний, общая UI регрессия не повторялась. + +[Source/runtime manifest](ux-ui/acceptance/ipsec-id-source-2026-10-10.json): build-id111 из audited build-dn110 +2 working overrides отHEAD2aa93ad, context byte hashes2/2 и changed compiled mapper byte hash совпали. Backend mmapp-test/backend:ux-id111/version1.0.0-test.id111/imagesha256:e9a5cf65433ed77b8c67991a556f3863a0e9609411a0e3e58d39463323c65414; labelid111 — stage marker, неGitSHA. Одна backend build, entrypoint/node check/pg_restore18.6/Compose wait passed; приватный pre-id111.env сохранён, прежний image доступен для rollback. Backend/PG healthy, frontend unchanged/HTTP/browser passed; миграции и DB test rows не создавались. + +Обе native attempts сравнили baseline13 коллекций×2 после удаления собственных сертификатов, imported chain с уникальными именами, peer/identity/profile/proposal/group/template/mode-config/files. Cleanup passed, logging/default/public/metadata routes и исходный195.195.195.195/32CHR2 сохранены; passwords прежние, SSH/обаCHR доступны. Private P12/PEM/pass files удалены, приватные ключи/секреты не сохранены в evidence. Native helpers используют aggregate GET /api/ipsec, не selected observed-revision write. + +Границы: shared configured Remote IDs, aliases нескольких identity/PSK с одинаковым bare value, arbitrary IKE ID types, custom DN/OIDs/client OS/full PKI/restore/IPv6 остаются открытыми. Этот блок принимает два конкретных CN fallback нарушения и одну real explicit-FQDN certificate сессию; не закрывает всю12.5. Следующий112 — коллизии configured Remote IDs между identity/PSK и безопасная атрибуция в этих случаях. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index 17e763c9..6dc2d7ad 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 предоставлен для временного тестирования. Backend ux-dn110/version1.0.0-test.dn110, frontend ux-a11y101/version1.0.0-test.a11y101; backend/PG healthy, frontend HTTP/browser passed. VPN107–109 и IPsec110: bridge/FDB/IPv6 inner и исправление online по полному DN приняты в границах журнала; собственные объекты удалены, baseline восстановлен; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние. +Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-id111/version1.0.0-test.id111, frontend ux-a11y101/version1.0.0-test.a11y101; backend/PG healthy, frontend HTTP/browser passed. VPN107–109 и IPsec110–111: bridge/FDB/IPv6 inner и исправление online по DN/CN и explicit FQDN приняты в границах журнала; собственные объекты удалены, baseline восстановлен; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние. | Параметр | Проверенное состояние | | --- | --- | @@ -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-dn110 и mmapp-test/frontend:ux-a11y101; запущены | +| Образы приложения | mmapp-test/backend:ux-id111 и mmapp-test/frontend:ux-a11y101; запущены | Compose SHA256:3052bd6ab5d9865f97605cebfb5ff27a4410cd3357b81153a65a87fb7c92582f. OptionalBACKEND_IMAGE_TAG позволяетобновлятьbackendотдельно. Локальный и удалённый файлы совпали. Шаблоны: [Compose](../deploy/docker-compose.test.yml), [env без секретов](../deploy/env.test.example). diff --git a/docs/ux-ui/acceptance/browser-ipsec-id-2026-10-10.json b/docs/ux-ui/acceptance/browser-ipsec-id-2026-10-10.json new file mode 100644 index 00000000..f1860cdd --- /dev/null +++ b/docs/ux-ui/acceptance/browser-ipsec-id-2026-10-10.json @@ -0,0 +1,49 @@ +{ + "date": "2026-10-10", + "runtime": { + "backend": "ux-id111", + "frontend": "ux-a11y101" + }, + "httpMocks": false, + "cases": [ + { + "theme": "dark", + "width": 1280, + "rootThemeConfirmed": true, + "unconnectedCertificateOffline": true, + "onlineAddressConfirmed": true, + "reloadConfirmed": true, + "noPageOverflow": true + }, + { + "theme": "dark", + "width": 320, + "rootThemeConfirmed": true, + "unconnectedCertificateOffline": true, + "onlineAddressConfirmed": true, + "reloadConfirmed": true, + "noPageOverflow": true + }, + { + "theme": "light", + "width": 1280, + "rootThemeConfirmed": true, + "unconnectedCertificateOffline": true, + "onlineAddressConfirmed": true, + "reloadConfirmed": true, + "noPageOverflow": true + }, + { + "theme": "light", + "width": 320, + "rootThemeConfirmed": true, + "unconnectedCertificateOffline": true, + "onlineAddressConfirmed": true, + "reloadConfirmed": true, + "noPageOverflow": true + } + ], + "pageErrors": [], + "applicationWrites": [], + "scope": "Real explicit FQDN certificate client status/address and unconnected DN-looking CN, reload, desktop/mobile, two themes" +} \ No newline at end of file diff --git a/docs/ux-ui/acceptance/ipsec-id-source-2026-10-10.json b/docs/ux-ui/acceptance/ipsec-id-source-2026-10-10.json new file mode 100644 index 00000000..c15658c2 --- /dev/null +++ b/docs/ux-ui/acceptance/ipsec-id-source-2026-10-10.json @@ -0,0 +1,42 @@ +{ + "date": "2026-10-10", + "baseCommit": "2aa93ad", + "baseContext": "build-dn110", + "context": "build-id111", + "source": "Audited dn110 context plus two explicit working-file overrides; revision label id111 is not a Git SHA", + "files": [ + { + "path": "backend/src/services/ipsec-live.ts", + "sha256": "2c4717b570077cfa931697ff5fcc9cb5c825dd683265d2757f305807a924cc13", + "contextByteHashMatches": true + }, + { + "path": "backend/src/services/ipsec-state.test.ts", + "sha256": "e13f2d801b9eb250bd6da3f8c0de1c306008a36df1c2393e344c86157e57f133", + "contextByteHashMatches": true + } + ], + "compiled": { + "path": "backend/dist/services/ipsec-live.js", + "sha256": "7e379bc5b08ecf745e9c77e0cc8cce557383dae13c6cfebc6d90f46998611774", + "containerByteHashMatches": true + }, + "deployment": { + "imageId": "sha256:e9a5cf65433ed77b8c67991a556f3863a0e9609411a0e3e58d39463323c65414", + "tag": "ux-id111", + "revisionLabel": "id111", + "health": { + "status": "ok", + "timestamp": "2026-10-10T02:51:44.826Z", + "version": "1.0.0-test.id111", + "eventLoopDelayMs": 20, + "flowWorker": { + "alive": false, + "bound": false, + "pendingSize": 0, + "dropped": 0, + "packetsReceived": 0 + } + } + } +} \ No newline at end of file diff --git a/docs/ux-ui/acceptance/ipsec-session-id-2026-10-10.json b/docs/ux-ui/acceptance/ipsec-session-id-2026-10-10.json new file mode 100644 index 00000000..700fea2a --- /dev/null +++ b/docs/ux-ui/acceptance/ipsec-session-id-2026-10-10.json @@ -0,0 +1,420 @@ +{ + "date": "2026-10-10", + "block": "12.5.111", + "runtime": { + "backend": "ux-id111", + "frontend": "ux-a11y101" + }, + "nativeBefore": { + "date": "2026-10-10", + "block": "12.5.111", + "name": "mm-ipsec111-1791600431289", + "cn": "mm-ipsec111-1791600431289", + "observations": [ + { + "serverId": 1, + "active": [ + { + ".id": "*1", + "id": "CN=mm-ipsec111-1791600431289", + "state": "established", + "dynamic-address": "198.18.111.250", + "remote-address": "104.165.244.7", + "uptime": "1s" + } + ], + "catalog": [ + { + "name": "CN=mm-ipsec111-1791600431289", + "commonName": "CN=mm-ipsec111-1791600431289", + "certName": "ipsec-user-mm-ipsec111-1791600431289-decoy", + "online": true, + "activeAddress": "198.18.111.250" + }, + { + "name": "mm-ipsec111-1791600431289", + "commonName": "mm-ipsec111-1791600431289", + "certName": "ipsec-user-mm-ipsec111-1791600431289", + "online": true, + "activeAddress": "198.18.111.250" + } + ] + }, + { + "serverId": 2, + "active": [ + { + ".id": "*1", + "id": "194.226.121.150", + "state": "established", + "remote-address": "194.226.121.150", + "uptime": "1s" + } + ], + "catalog": [] + } + ], + "cleanup": [ + { + "serverId": 1, + "/system/logging": true, + "/ip/ipsec/identity": true, + "/ip/ipsec/peer": true, + "/ip/ipsec/policy": true, + "/ip/ipsec/policy/group": true, + "/ip/ipsec/mode-config": true, + "/ip/ipsec/proposal": true, + "/ip/ipsec/profile": true, + "/certificate": true, + "/file": true, + "/ip/address": true, + "/ip/route": true, + "/ip/firewall/nat": true + }, + { + "serverId": 2, + "/system/logging": true, + "/ip/ipsec/identity": true, + "/ip/ipsec/peer": true, + "/ip/ipsec/policy": true, + "/ip/ipsec/policy/group": true, + "/ip/ipsec/mode-config": true, + "/ip/ipsec/proposal": true, + "/ip/ipsec/profile": true, + "/certificate": true, + "/file": true, + "/ip/address": true, + "/ip/route": true, + "/ip/firewall/nat": true + } + ], + "databaseWrites": false, + "certificate": { + "name": "ipsec-user-mm-ipsec111-1791600431289", + "common-name": "mm-ipsec111-1791600431289", + "ca": "mm-ipsec111-1791600431289-ca", + "key-usage": "digital-signature,key-encipherment,tls-client" + }, + "certificates": [ + [ + { + "name": "mm-ipsec111-1791600431289-ca", + "trusted": "true", + "trust-store": "all", + "invalid-before": "2026-10-10 05:47:12", + "invalid-after": "2026-10-12 05:47:12", + "common-name": "mm-ipsec111-1791600431289-CA" + }, + { + "name": "mm-ipsec111-1791600431289-server", + "trusted": "false", + "trust-store": "all", + "ca": "mm-ipsec111-1791600431289-ca", + "invalid-before": "2026-10-10 05:47:14", + "invalid-after": "2026-10-12 05:47:14", + "common-name": "194.226.121.150" + }, + { + "name": "ipsec-user-mm-ipsec111-1791600431289", + "trusted": "false", + "trust-store": "all", + "ca": "mm-ipsec111-1791600431289-ca", + "invalid-before": "2026-10-10 05:47:15", + "invalid-after": "2026-10-12 05:47:15", + "common-name": "mm-ipsec111-1791600431289" + }, + { + "name": "ipsec-user-mm-ipsec111-1791600431289-decoy", + "trusted": "false", + "trust-store": "all", + "ca": "mm-ipsec111-1791600431289-ca", + "invalid-before": "2026-10-10 05:47:16", + "invalid-after": "2026-10-12 05:47:16", + "common-name": "CN=mm-ipsec111-1791600431289" + } + ], + [ + { + "name": "mm-ipsec111-1791600431289-client-imported", + "trusted": "true", + "trust-store": "ipsec", + "invalid-before": "2026-10-10 04:47:15", + "invalid-after": "2026-10-12 04:47:15", + "common-name": "mm-ipsec111-1791600431289" + }, + { + "name": "mm-ipsec111-1791600431289-ca-imported", + "trusted": "true", + "trust-store": "ipsec", + "invalid-before": "2026-10-10 04:47:12", + "invalid-after": "2026-10-12 04:47:12", + "common-name": "mm-ipsec111-1791600431289-CA" + } + ] + ], + "catalogCorrect": true, + "dnPhase": { + "active": [ + { + ".id": "*1", + "id": "CN=mm-ipsec111-1791600431289", + "state": "established", + "dynamic-address": "198.18.111.250", + "remote-address": "104.165.244.7", + "uptime": "1s" + } + ], + "clients": [ + { + "name": "CN=mm-ipsec111-1791600431289", + "commonName": "CN=mm-ipsec111-1791600431289", + "certName": "ipsec-user-mm-ipsec111-1791600431289-decoy", + "online": true, + "activeAddress": "198.18.111.250" + }, + { + "name": "mm-ipsec111-1791600431289", + "commonName": "mm-ipsec111-1791600431289", + "certName": "ipsec-user-mm-ipsec111-1791600431289", + "online": true, + "activeAddress": "198.18.111.250" + } + ], + "decoyOnline": true + }, + "error": "DN-looking literal CN inherited another certificate session\n\ntrue !== false\n" + }, + "nativeAccepted": { + "date": "2026-10-10", + "block": "12.5.111", + "name": "mm-ipsec111-1791600594968", + "cn": "mm-ipsec111-1791600594968", + "observations": [ + { + "serverId": 1, + "active": [ + { + ".id": "*1", + "id": "CN=mm-ipsec111-1791600594968", + "state": "established", + "dynamic-address": "198.18.111.250", + "remote-address": "104.165.244.7", + "uptime": "0s" + } + ], + "catalog": [ + { + "name": "CN=mm-ipsec111-1791600594968", + "commonName": "CN=mm-ipsec111-1791600594968", + "certName": "ipsec-user-mm-ipsec111-1791600594968-decoy", + "online": false + }, + { + "name": "mm-ipsec111-1791600594968", + "commonName": "mm-ipsec111-1791600594968", + "certName": "ipsec-user-mm-ipsec111-1791600594968", + "online": true, + "activeAddress": "198.18.111.250" + } + ] + }, + { + "serverId": 2, + "active": [ + { + ".id": "*1", + "id": "194.226.121.150", + "state": "established", + "remote-address": "194.226.121.150", + "uptime": "0s" + } + ], + "catalog": [] + } + ], + "cleanup": [ + { + "serverId": 1, + "/system/logging": true, + "/ip/ipsec/identity": true, + "/ip/ipsec/peer": true, + "/ip/ipsec/policy": true, + "/ip/ipsec/policy/group": true, + "/ip/ipsec/mode-config": true, + "/ip/ipsec/proposal": true, + "/ip/ipsec/profile": true, + "/certificate": true, + "/file": true, + "/ip/address": true, + "/ip/route": true, + "/ip/firewall/nat": true + }, + { + "serverId": 2, + "/system/logging": true, + "/ip/ipsec/identity": true, + "/ip/ipsec/peer": true, + "/ip/ipsec/policy": true, + "/ip/ipsec/policy/group": true, + "/ip/ipsec/mode-config": true, + "/ip/ipsec/proposal": true, + "/ip/ipsec/profile": true, + "/certificate": true, + "/file": true, + "/ip/address": true, + "/ip/route": true, + "/ip/firewall/nat": true + } + ], + "databaseWrites": false, + "certificate": { + "name": "ipsec-user-mm-ipsec111-1791600594968", + "common-name": "mm-ipsec111-1791600594968", + "ca": "mm-ipsec111-1791600594968-ca", + "key-usage": "digital-signature,key-encipherment,tls-client" + }, + "certificates": [ + [ + { + "name": "mm-ipsec111-1791600594968-ca", + "trusted": "true", + "trust-store": "all", + "invalid-before": "2026-10-10 05:49:56", + "invalid-after": "2026-10-12 05:49:56", + "common-name": "mm-ipsec111-1791600594968-CA" + }, + { + "name": "mm-ipsec111-1791600594968-server", + "trusted": "false", + "trust-store": "all", + "ca": "mm-ipsec111-1791600594968-ca", + "invalid-before": "2026-10-10 05:49:57", + "invalid-after": "2026-10-12 05:49:57", + "common-name": "194.226.121.150" + }, + { + "name": "ipsec-user-mm-ipsec111-1791600594968", + "trusted": "false", + "trust-store": "all", + "ca": "mm-ipsec111-1791600594968-ca", + "invalid-before": "2026-10-10 05:49:57", + "invalid-after": "2026-10-12 05:49:57", + "common-name": "mm-ipsec111-1791600594968" + }, + { + "name": "ipsec-user-mm-ipsec111-1791600594968-decoy", + "trusted": "false", + "trust-store": "all", + "ca": "mm-ipsec111-1791600594968-ca", + "invalid-before": "2026-10-10 05:49:59", + "invalid-after": "2026-10-12 05:49:59", + "common-name": "CN=mm-ipsec111-1791600594968" + } + ], + [ + { + "name": "mm-ipsec111-1791600594968-client-imported", + "trusted": "true", + "trust-store": "ipsec", + "invalid-before": "2026-10-10 04:49:57", + "invalid-after": "2026-10-12 04:49:57", + "common-name": "mm-ipsec111-1791600594968" + }, + { + "name": "mm-ipsec111-1791600594968-ca-imported", + "trusted": "true", + "trust-store": "ipsec", + "invalid-before": "2026-10-10 04:49:56", + "invalid-after": "2026-10-12 04:49:56", + "common-name": "mm-ipsec111-1791600594968-CA" + } + ] + ], + "catalogCorrect": true, + "dnPhase": { + "active": [ + { + ".id": "*1", + "id": "CN=mm-ipsec111-1791600594968", + "state": "established", + "dynamic-address": "198.18.111.250", + "remote-address": "104.165.244.7", + "uptime": "0s" + } + ], + "clients": [ + { + "name": "CN=mm-ipsec111-1791600594968", + "commonName": "CN=mm-ipsec111-1791600594968", + "certName": "ipsec-user-mm-ipsec111-1791600594968-decoy", + "online": false + }, + { + "name": "mm-ipsec111-1791600594968", + "commonName": "mm-ipsec111-1791600594968", + "certName": "ipsec-user-mm-ipsec111-1791600594968", + "online": true, + "activeAddress": "198.18.111.250" + } + ], + "decoyOnline": false + }, + "fqdnPhase": { + "configuredRemoteId": "fqdn:mm-ipsec111-1791600594968.example", + "nativeId": "mm-ipsec111-1791600594968.example", + "assignedAddress": "198.18.111.250", + "originalOnline": true, + "decoyOnline": false + } + }, + "compiledSyntheticBefore": { + "scope": "Compiled baseline mapper with synthetic input; not native typed-ID admission", + "clients": [ + { + "name": "ipsec-user-original", + "online": true + }, + { + "name": "ipsec-user-typed", + "online": true + } + ] + }, + "compiledSyntheticAfter": { + "scope": "Compiled deployed mapper with synthetic input; not native typed-ID admission", + "clients": [ + { + "name": "ipsec-user-original", + "online": true + }, + { + "name": "ipsec-user-typed", + "online": false + } + ] + }, + "deployment": { + "imageId": "sha256:e9a5cf65433ed77b8c67991a556f3863a0e9609411a0e3e58d39463323c65414", + "tag": "ux-id111", + "revisionLabel": "id111", + "health": { + "status": "ok", + "timestamp": "2026-10-10T02:51:44.826Z", + "version": "1.0.0-test.id111", + "eventLoopDelayMs": 20, + "flowWorker": { + "alive": false, + "bound": false, + "pendingSize": 0, + "dropped": 0, + "packetsReceived": 0 + } + } + }, + "browserEvidence": "browser-ipsec-id-2026-10-10.json", + "limits": [ + "Native DN collision and explicit certificate FQDN ID accepted", + "Typed-looking literal CN stripping tested against compiled mappers with synthetic input, not native admission of that IKE ID", + "Shared configured Remote IDs/cross-auth aliases, arbitrary ID types, client OS, PKI/restore/IPv6 remain open" + ] +} \ No newline at end of file diff --git a/docs/ux-ui/screens/ipsec-id-dark-1280-2026-10-10.png b/docs/ux-ui/screens/ipsec-id-dark-1280-2026-10-10.png new file mode 100644 index 00000000..e6ed91c3 Binary files /dev/null and b/docs/ux-ui/screens/ipsec-id-dark-1280-2026-10-10.png differ diff --git a/docs/ux-ui/screens/ipsec-id-dark-320-2026-10-10.png b/docs/ux-ui/screens/ipsec-id-dark-320-2026-10-10.png new file mode 100644 index 00000000..7afa62e3 Binary files /dev/null and b/docs/ux-ui/screens/ipsec-id-dark-320-2026-10-10.png differ diff --git a/docs/ux-ui/screens/ipsec-id-light-1280-2026-10-10.png b/docs/ux-ui/screens/ipsec-id-light-1280-2026-10-10.png new file mode 100644 index 00000000..5be04d22 Binary files /dev/null and b/docs/ux-ui/screens/ipsec-id-light-1280-2026-10-10.png differ diff --git a/docs/ux-ui/screens/ipsec-id-light-320-2026-10-10.png b/docs/ux-ui/screens/ipsec-id-light-320-2026-10-10.png new file mode 100644 index 00000000..af99bef2 Binary files /dev/null and b/docs/ux-ui/screens/ipsec-id-light-320-2026-10-10.png differ