Files
MikrotikManager/docs/ux-ui-test-server.md
T

2383 lines
623 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Тестовый сервер UX/UI — 2026-10-10
Актуальное продолжение 2026-10-14:236 — по приоритету пользователя проверен REST:384 paired samples из workstation/Debian +40 diagnostics, отказов0; current credentials/policies/addresses/service load исправны. На7.24.5 сохранены828/304 rest-api sessions и2 api на каждом; после3 дополнительных reads delta0. Найден vendor fix inactive REST sessions в7.25rc, это гипотеза, причинность401/500 не доказана. Runtime ux-backup234/ux-routing218 unchanged. Следующий REST шаг — корреляция сбоя/renewal или согласованный firmware control; общий следующий237 — missing local files UX. Этап12.5 открыт.
| Параметр | Проверенное состояние |
| --- | --- |
| ОС / архитектура | Debian13 trixie13.7 / x86_64 |
| Ресурсы | 1CPU,1973MiB RAM,4GiB swap; исходно23GiB свободного диска |
| Docker Engine | 29.8.2;systemd enabled/active;hello-world passed |
| Compose / Buildx | v5.6.0 / v0.37.1 |
| Каталог | /opt/mmapp-test;0700 |
| Конфигурация | /opt/mmapp-test/compose.yaml;0600;docker compose config --quiet passed |
| Секреты | Сгенерированы только на сервере в /opt/mmapp-test/.env;0600;в Git не сохранены |
| 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-peak190 и mmapp-test/frontend:ux-warning183; запущены |
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 журнала.
IPsec79: сертификатный responder online=true/static mode-config198.18.79.250 принят; recordRevision=null после native patch даёт502/state=applied. Собственные объекты и private files удалены. [Отчёт](ux-ui/acceptance/ipsec-certificate-2026-10-09.json).
IPsec80: real restore staticIp/disabled, повтор без дубликатов, foreign-reference409 и cleanup приняты. Первоначальный неполный образ откатан; исправленный runtime healthy. [Отчёт](ux-ui/acceptance/ipsec-restore-2026-10-09.json).
IPsec81: partial/unknown native fault injection, preflight конфликтов, typed Remote ID, удаление старого mode-config и isolated JWT/RBAC приняты. Рабочая авторизация не менялась, физический TCP disconnect не моделировался. [Отчёт](ux-ui/acceptance/ipsec-mutations-2026-10-09.json).
IPsec82: production certificate data plane/NAT Ping3/3, capped UDP3s, history group/egress и API server delete приняты. Baseline14 коллекций×2 восстановлен после route convergence; own/private fixtures удалены. [Отчёт](ux-ui/acceptance/ipsec-network-2026-10-09.json).
Routing83: disabled BGP/OSPF selected/raw409/probe0 и собственная eBGP Established пара с reject-all filters приняты; original routes/config preserved, own DB/native fixtures удалены. [Отчёт](ux-ui/acceptance/routing-bgp-disabled-2026-10-09.json).
OSPF84: real GRE Full adjacency/private routes/Ping3/3 и4 live PC/320px URL/browser checks приняты. Exact own cleanup и исходные7 коллекций×2 passed; runtime routing83 без новой сборки. [Отчёт](ux-ui/acceptance/ospf-gre-2026-10-09.json).
BFD85: Up/Full/own route/Ping,4 live UI и loss/withdrawal/recovery приняты; exact own cleanup8 коллекций×2 passed. Withdrawal5,245ms не подтверждает sub-second BFD timing; этот вопрос открыт. Runtime routing83 без новой сборки. [Отчёт](ux-ui/acceptance/ospf-bfd-loss-2026-10-09.json).
## Развёртывание приложения
Чистые 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.
После сборки/загрузки образов выполнить на сервере:
~~~bash
cd /opt/mmapp-test
docker compose config --quiet
docker compose up -d --wait --wait-timeout 300 postgres backend frontend
docker compose ps
curl -fsS http://127.0.0.1:8000/health
curl -fsS http://127.0.0.1:3000/health
~~~
Для браузера на рабочем ПК открыть SSH-туннель в отдельном терминале:
~~~powershell
ssh -N -L 3000:127.0.0.1:3000 -L 8000:127.0.0.1:8000 root@161.104.46.222
~~~
После запуска frontend открыть http://localhost:3000. AUTH_REQUIRED=false допустим для этого доступа через loopback/SSH; при приёмке прав включить AUTH_REQUIRED и согласованный тестовый issuer/Portal, используя серверный JWT secret. Конфигурация фиксирует конкретный image tag; автообновление main:latest не используется.
## Границы результата
Выполнены подготовка12.5.1,сборка/запуск12.5.2 и исправление обнаруженной live ошибки12.5.3. На реальном PG применились9миграций0000–0009 (без0001),проверены0008/0009 и CHECK статусов/resolution_version;restart сохранил контрольную настройкуuptime_settings(id1/retention14) и список миграций. Пустые API каталоги прочитаны успешно. Это PG-1 в границе bootstrap/restart/schema/control-row,не проверка backup/restore или транзакционных отказов.
[Первый smoke](ux-ui/acceptance/test-server-smoke-2026-10-07.json) обнаружил PostgreSQL timestamp в outer sampledAt Internet path. Исправлено producer ISO преобразование,без ослабленияfrontend. [Итоговый smoke](ux-ui/acceptance/test-server-smoke-fixed-2026-10-07.json):3экрана200,54чтенияAPI200,безJSerrors,320px fits,Internet path подтверждён. HTTP-моков нет. Первое повторное ожидание подписи свежести исправлено раскрытием штатного блока;ошибка данных послеpatch отсутствует. [Дашборд320px](ux-ui/screens/test-server-dashboard-320-2026-10-07.png) просмотрен.
Image IDs при первом smoke12.5.3 (исторический снимок):
- backend: sha256:57878e320b7272edcc6efe1f6f5c140295510c85cb79b8ca12a900f7654cd917
- frontend: sha256:bfba2785b33a72965a029a3692178ba69c80eca75a12934c1dcc04c7970db53f
После пересборки контрольныйid1/retention14 и9миграций сохранились. Подробные build logs и контрольные файлы расположены в /opt/mmapp-test/artifacts. Секреты остаются только в серверном.env0600. Временный SSH-туннель3000/8000 открыт в этой задаче;если процесс остановится,повторить команду выше.
Продолжение PG проверок записано в блоке 12.5.7 ниже. Следующий 12.5.8 — lifecycle jobs/flush/worker перед API restore по [протоколу](ux-ui-external-acceptance.md). Для Telegram/Portal и других интеграций нужны тестовые endpoints/учётные записи. 1CPU/2GiB не представляют production performance.
## Первый тестовый CHR — 2026-10-07
194.226.121.150 добавлен в приложение,serverId1,имяCHR,typehome-router(default). По явному выбору пользователя используетсяHTTP REST80,useSsl=false;HTTPS443 отключён наCHR. RouterOS7.24.5 stable;identityCHR,модельCHR OpenStack Foundation OpenStack Nova. Test-connection/poll/GET200,statusonline,строка видна вUI. КонфигурацияRouterOS не изменялась. [Очищенный результат](ux-ui/acceptance/chr-connection-2026-10-07.json). Пароль в паспорт/отчёт/Git не включён. Дляspeed-test нужно второе отдельное устройство;VPN/маршрутизация/изменениясети пока не проверены.
## Второй тестовый CHR — 2026-10-07
104.165.244.7,serverId2,HTTPREST80,имяCHR,typehome-router(default),RouterOS7.24.5 stable;test-connection/poll/GET200,statusonline. [Паспорт пары без учётных данных](ux-ui/acceptance/chr-pair-2026-10-07.json). Пароль не включён в документы/Git. Следующий12.5.6 — короткиеTCP bandwidth-test по3сек,transmit/receive/both. Имена одинаковые;использоватьIP/id для выбора устройства.
## Native TCP speed — 2026-10-07
НаобоихCHR поразрешениюпользователя включёнbandwidth-server(enabled=true,authenticate=true,max-sessions100),независимымGET подтверждено;служба остаётся активной для последующих тестов. ВзаимныйPing3/3,0%loss. Триad-hocTCP runs id1→id2 по3s/transmit/receive/both завершеныdone testing,HTTP200,история/GUI подтверждены. [Настройки](ux-ui/acceptance/chr-bandwidth-server-2026-10-07.json),[результаты](ux-ui/acceptance/chr-native-speed-enabled-2026-10-07.json),[предыдущий отказ при выключенной службе](ux-ui/acceptance/chr-native-speed-2026-10-07.json). Это функциональная проверка,неbenchmark;UDP/WANbinding/probe-races/остальнойROS иPG-протокол не закрыты.
## PostgreSQL backup/RBAC/concurrency — 2026-10-07
[Отчёт 12.5.7](ux-ui/acceptance/pg-backup-auth-2026-10-07.json): admin backup200/475225bytes, pg_restore18.6 прочитал907TOC entries и восстановил отдельную mmapp_acceptance_20261007. Контрольные записи/9миграций/5speed rows/servers sequence совпали с исходной БД. Приложение не подключено к проверочной БД; она сохранена для дальнейшей приёмки. Дамп только в /opt/mmapp-test/data/acceptance-private (0700), файл0600, содержит приватные учётные данные и не копируется в Git.
При AUTH_REQUIRED=true подтверждены401/403 на backup/restore; JWT сформированы в памяти, реальный Portal SSO не проверен. Конкурирующий restore409 при наблюдаемом активном pg_dump, первый backup200 после снятия контрольного SQL lock. AUTH_REQUIRED=false восстановлен, API auth/config и health подтвердили состояние. PG-3/4/6 остаются открытыми: ожидание завершения текущих scheduler jobs/flush/worker пока не обеспечено.
## Локальный lifecycle patch — 2026-10-07
Блок12.5.8 исправляет ожидание scheduler jobs и запрещает новые запуски во время database operation;17scheduler tests,7pure database tests,HTTP/JWT scripts и build прошли. На этом стенде patch пока не развёрнут: активный source673e5ba сохраняется. Следующий12.5.9 — graceful NetFlow worker stop/flush; только после этого перейти к сборке/развёртыванию и внешней проверкеPG-6. Восстановление основной тестовой БД ещё не выполнялось.
## Локальный NetFlow shutdown patch — 2026-10-07
В12.5.9 добавлена командаshutdown с подтверждением послеflush/pool.end и ожиданиемexit0;4pure/protocol tests, database HTTP/JWT и build passed. На стенд ещё не развёрнуто, source673e5ba остаётся активным. Реальный collector/UDP/длительный SQL и прочие writers требуют отдельной проверки12.5.10 в mmapp_acceptance_20261007. Подтверждение завершения flush не гарантирует сохранение всех пакетов при прежних best-effort ошибках engine; PG-6/restore не приняты.
## Настоящий isolated collector — 2026-10-07
[12.5.10 evidence](ux-ui/acceptance/netflow-worker-2026-10-07.json): актуальныйworker изf8da3e0 в отдельном временном контейнере, выделеннаяmmapp_acceptance_20261007, UDP4749 только внутриконтейнера. Shutdown дождался blocked SQL/освободилsocket, ack+exit0, delta1500bytes,0worker connections. Контейнер удалён--rm. ПроверочнаяБД теперь содержит синтетические flow rows/counters; архив12.5.7 остаётся исходным snapshot. Основной runtime673e5ba/healthok/serverID1–2/retention14 сохранён. App-wide PG-6/ручные API writers/restore ещё открыты; следующий12.5.11 — аудит и admission остальных писателей.
## Локальный HTTP drain patch — 2026-10-07
12.5.11 добавляет instance-local gate для всех API handlers/GET, exclusive backup/restore иabort/drain traffic live streams.4gate tests,15lifecycle/database tests,HTTP/JWT scripts иbuild passed. Основнойruntime673e5ba остаётсяактивным. Detached backup jobs/audit иRIPE persistence ещёнеохвачены; следующий12.5.12 закрываетэтотпробел. PG-6/restore не приняты.
## Локальный detached work drain — 2026-10-07
12.5.12 добавляетучётbackground backup/audit/certificate/partition maintenance/cache work иpause RIPE enqueue сdrain текущихresolver/writes.19lifecycle/database tests,HTTP/JWT,backup/RIPE,10certificate tests иbuild прошли. На стенднеразвёрнуто; source673e5ba сохраняется. Следующий12.5.13 — integrated quiescence иcache invalidation передrestore/deployment. PG-6/3/4 остаютсяоткрытыми.
## Локальный cache invalidation patch — 2026-10-07
12.5.13 сбрасываетDB-зависимыеNetFlow caches/live buffers/partition memo послеуспешногоrestore доconsumer restart, сохраняяRIPE pause.22различныхlifecycle/database tests,HTTP/JWT,RIPE/ifindex/classify иbuild прошли. Runtime673e5ba не обновлён; следующий12.5.14 — integrated real-PG quiescence/restore ввыделеннойБД иdeployment. PG-6/3/4 остаютсяоткрытыми. Dump не включаетвнешниеbackup/certificate/MMDB files.
## Реальный API restore failure — 2026-10-07
[12.5.14 evidence](ux-ui/acceptance/real-restore-2026-10-07.json): isolatedsourcef1aac49/API againstmmapp_acceptance_20261007, backup200, activewrite drain/GET409. Restore400:inheritedpartitionPK нельзяудалитьсуществующим--clean. Контрольrollback прошёл (servers/speed/migrations/sequence/retention16/constraint). ПроверочнаяБДretention16,основнаяretention14/source673e5ba/healthok сохранены. Runtimeнеобновлён,PG-3 иполныйPG-6 открыты. Следующий12.5.15 — транзакционноеисправлениеclean иповторнаяприёмка.
## Partition-safe API restore — 2026-10-07
12.5.15:isolatedf1aac49+compiledpatch, [realAPIrestore200/новыйID3/injectedSQL400/rollback1587constraints](ux-ui/acceptance/real-restore-fixed-2026-10-07.json). ПроверочнаяБДmmapp_acceptance_20261007 содержитserver3 disabled192.0.2.250/retention19. ОсновнаяБДserver1–2/retention14/source673e5ba/healthok сохранена.25localtests,HTTP/JWT иbuild passed. Patchещёнеразвёрнут; следующий12.5.16 — disabled-server collector defect, integratedPG-6/deployment.
## Enabled-only мониторинг — 2026-10-07
По явномувыборупользователя12.5.16 исключаетdisabledвсетипыизuptime/RESTping/scheduledspeed, manualspeedпроверяетобасерверадосети. [Realматрица3типов/0новыхdisabledсэмплов](ux-ui/acceptance/monitoring-enabled-2026-10-07.json) прошла. ВпроверочнойБДserver3 сноваhome-router/enabledfalse, temporaryspeedprobesудалены. Основнойruntime673e5ba не обновлён,healthok. Следующий12.5.17 — integratedPG-6/deployment.
## Обновление backend иPG-6 — 2026-10-07
12.5.17 [integratedquiescence/restore/restart](ux-ui/acceptance/integrated-pg6-2026-10-07.json) passedдляодногоisolatedbackend. [Основнойbackend4c12c55](ux-ui/acceptance/deployed-4c12c55-2026-10-07.json) собран/развёрнут,healthy/sourcefullrevision/version1.0.0-test.4c12c55. Frontend673e5ba прежний. BACKEND_IMAGE_TAG=ux-4c12c55,MMAPP_IMAGE_TAG=ux-673e5ba. Приватныйpre-updatebackup вdata/acceptance-private,контрольосновнойБДserver1–2/retention14/9миграций совпал. [3realbrowser screens](ux-ui/acceptance/deploy-browser-4c12c55-2026-10-07.json) 200/320fits/безJS/APIerrors. Полный12.5 иmulti-instanceприёмкаещёоткрыты.
## RealRBAC иbrowserrestore — 2026-10-08
12.5.18 [RBAC16denials/childprocess0/adminbackup200](ux-ui/acceptance/rbac-4c12c55-2026-10-08.json),[browserrestore200/архивныйcontrol/400guardreload](ux-ui/acceptance/browser-restore-2026-10-08.json) passedнавыделеннойБД. Временныеfrontend/backend использовалиизолированнуюDocker network,посколькуNextrewritesфиксированыприbuild; guardпредотвратилwritesприошибкемаршрутизации. Temporarycontainers/network/3018tunnelудалены,основнойbackend4c12c55/frontend673e5ba/server1–2/retention14/AUTHfalse сохранены. PortalSSO иполный12.5 ещёоткрыты.
## Isolated PG-8 speed — 2026-10-08
12.5.19 [INSERTfailure/realCOMMITackfault/scheduledreceipt](ux-ui/acceptance/pg8-speed-2026-10-08.json) passedнаmmapp_acceptance_20261007/source4c12c55+worktreepatch среальнымиCHRtransmit3s. Temporaryprobe/trigger/function удалены,историческиетестовыерезультатыосталисьвпроверочнойБД. Основнойruntime4c12c55healthy/БДнеизменена;patchещёнеразвёрнут. Следующий12.5.20 — deployment/browserunknown-speed.
## Локальный snapshot guard — 2026-10-08
12.5.20 сохраняетlastconfirmedspeed snapshot дляunknown502/совпадающегоrunId.2unit tests/frontendtypecheck passed;browserunknownUX ещёнепроверен,patchнеразвёрнут. Backend4c12c55/frontend673e5ba прежние. Следующий12.5.21 — build/browserunknown/deploymentобоихобразов.
## Локальный unknown UX — 2026-10-08
12.5.21: отдельная строка unknown/runId, сохранение snapshot и сверка по идентификатору при чтении истории. 13 браузерных тестов с HTTP-моками/typecheck/ESLint прошли; это не приёмка real browser/PG. Основной backend4c12c55/frontend673e5ba прежний. Следующий 12.5.22 — сборка и проверка обновлённых образов. Полный 12.5 открыт.
## Локальный unknown UX — 2026-10-08
12.5.21: отдельная строка unknown/runId, сохранение snapshot и сверка по идентификатору при чтении истории. 13 браузерных тестов с HTTP-моками/typecheck/ESLint прошли; это не приёмка real browser/PG. Основной backend4c12c55/frontend673e5ba прежний. Следующий 12.5.22 — сборка и проверка обновлённых образов. Полный 12.5 открыт.
## Обновление обоих образов — 2026-10-08
12.5.22: [deployment](ux-ui/acceptance/deployed-8782054-2026-10-08.json), [real browser speed unknown](ux-ui/acceptance/browser-speed-unknown-2026-10-08.json), [пять экранов](ux-ui/acceptance/deploy-browser-8782054-2026-10-08.json). Backend/frontend8782054, backend healthy. MMAPP_IMAGE_TAG и BACKEND_IMAGE_TAG равны ux-8782054. Приватный pre-update backup и конфигурация сохранены только на сервере; основная БД не восстанавливалась, контроль совпал. Temporarycontainers/network/3018 закрыты; основной SSH-туннель3000/8000 восстановлен. AUTHfalse/loopback ports сохранены. Следующий12.5.23 — ROS-8/9 на выделенной БД.
## Real speed context — 2026-10-08
12.5.23 [ROS-8/9 API/SQL/native evidence](ux-ui/acceptance/speed-context-2026-10-08.json): семь preflight409/bandwidth0, enable/reorder сохраняют fixture0; три TCPtransmit3s теста при late change/delete/row lock. Фактическая history done сохранена без stale probe association, новый snapshot null. Scheduler admission закрыт в isolated process до fixture setup; основной backend8782054healthy/история5 сохранены, testprobes0/containerудалён. Browser race и multi-instance открыты. Следующий12.5.24 — browser-смена контекста вторым клиентом.
## Browser speed context — 2026-10-08
12.5.24 [real browser/native](ux-ui/acceptance/browser-speed-context-2026-10-08.json): смена пары/длительности и удаление независимым HTTP-клиентом до native response; UI refresh/reload сохраняет новый контекст без старых скоростей, history done остаётся. Принятые native2/POST[200,200]/JS0/320fits, без HTTP/RouterOS-моков. Ещё один native command выполнен в подготовительном прогоне с неверным UI selector expectation; application auto retry отсутствует. Temporarycontainers/network/3018 закрыты, testprobe удалена; runtime8782054/основнаяhistory5 сохранены. Следующий12.5.25 — ROS-2 authentication failure.
## Реальный отказ bandwidth-аутентификации — 2026-10-08
12.5.25 [native/API/browser evidence](ux-ui/acceptance/speed-auth-error-2026-10-08.json): authentication failed→HTTP502/русская UI-ошибка, history error/TXRXnull; probe previousTX42 сохранён. Native1/POST[502]/refresh/reload/320fits/JS0, без HTTP/RouterOS-моков. Тестовое имя изменялось только в выделенной app DB и восстановлено; RouterOS accounts не менялись. Temporarycontainers/network/3018 закрыты, testprobe удалена; основнаяhistory5/runtime8782054 сохранены. Подготовительный слишком длинныйuser отклонён по длине; accepted run отдельно. ROS-2 authentication failure принят; остальные native failures ещё открыты. Следующий12.5.26 — unreachable destination.
## Исправление Next proxy timeout — 2026-10-08
12.5.26 [real frontend500/backend error-history](ux-ui/acceptance/speed-unreachable-proxy-before-2026-10-08.json) выявил30s proxy timeout. Локально proxyTimeout180s; реальная Next proxy regression31s/TypeScript/ESLint passed. Backend сохраняет предыдущий TX42; native can not connect не подтверждён. Runtime8782054 прежний; destination восстановлен/testprobe удалена/temporarycontainers-network-3018 закрыты. Следующий12.5.27 — build/real browser retry/deployment исправленного frontend.
## Новый frontend proxy timeout — 2026-10-08
12.5.27 [real browser timeout502](ux-ui/acceptance/speed-unreachable-error-2026-10-08.json), [frontend deployment](ux-ui/acceptance/deployed-frontend-aa7dbdf-2026-10-08.json), [пять экранов](ux-ui/acceptance/deploy-browser-aa7dbdf-2026-10-08.json) passed. Frontendaa7dbdf/proxy180s, backend8782054healthy прежний; MMAPP_IMAGE_TAG=ux-aa7dbdf/BACKEND_IMAGE_TAG=ux-8782054. Основной DBcontrol совпал. Isolatedhost/probe восстановлены/удалены, temporarycontainers/network/3018 закрыты. Это transport timeout, не native can not connect; техническая подпись timeout остаётся ограничением UX. Следующий12.5.28 — ROS-3 interface/address/after-ping.
## Интерфейс native test и Ping — 2026-10-08
12.5.28 [real ROS-3](ux-ui/acceptance/speed-interface-2026-10-08.json): reverse2→1 done, bandwidth194.226.121.150/nointerfacebinding, Pingether1/0%loss; metadata source195 не доказываетsourceIPpackets. CHR2 имеет dynamic104/static195, явныйdstinterface предпочитаетstatic. Три1→2 попыткиtimeout, причинаauto-path не установлена; они не приняты. КонфигурацияRouterOS не менялась. Основнойruntimebackend8782054/frontendaa7dbdf/history5 сохранён. UIhint/CLIwhereinterface исправлены локально; browserfixture/typecheck/ESLint passed, не развёрнуты. Следующий12.5.29 — real browserform/deploymentподсказок.
## Форма интерфейсов развёрнута — 2026-10-08
12.5.29 [real browser form](ux-ui/acceptance/browser-speed-form-2026-10-08.json), [deployment](ux-ui/acceptance/deployed-frontend-f194e72-2026-10-08.json), [пять экранов](ux-ui/acceptance/deploy-browser-f194e72-2026-10-08.json) passed. Frontendf194e72, backend8782054healthy прежний; MMAPP_IMAGE_TAG=ux-f194e72/BACKEND_IMAGE_TAG=ux-8782054. Настоящий inventory/static-IP195, правильныйCLIinterfacefilter/пояснение/320fits/JS0, без моков/native-команд. Основнойcontrol совпал; fixtureprobe/temporarycontainers/network/3018 удалены. Следующий12.5.30 — read-only forward-native диагностика; timeout1→2 не исправлен этим UI-изменением.
## Read-only forward диагностика — 2026-10-08
12.5.30 [settings/state](ux-ui/acceptance/chr-bandwidth-diagnostics-2026-10-08.json), [jobs](ux-ui/acceptance/chr-job-classification-2026-10-08.json), [TCP2000 сDebian](ux-ui/acceptance/tcp-2000-2026-10-08.json). Server enabled/authtrue/session0, filter/NAT/mangle0, active main default routes, CPU0; TCP2000 reachable сDebian. ПричинаCHR1→CHR2timeout не установлена. Поздние REST401/CHR2-500 ограничивают дополнительные чтения. Native0/configchanges0, temporarycontainers завершены, mainruntimebackend8782054/frontendf194e72/history5 сохранены. Следующий12.5.31 — CLI/REST/соединения1→2, без изменения адресов и маршрутов.
## Текущий доступ CHR2 требует проверки — 2026-10-08
12.5.31 [CLI/REST/SSH comparison](ux-ui/acceptance/cli-rest-2026-10-08.json): CLI3.5s/REST3.0s nativeauthenticationfailed; GETconnections401, SSH2AuthenticationException. Main/testcredentials совпадают, значения не раскрыты. Текущий отказ авторизации подтверждён; причина прежнегоtimeout не доказана. Запрошены актуальные данные или проверкаadmin на104.165.244.7, зависимаяприёмка ожидает ответа. RouterOSconfiguration не менялась, mainruntimebackend8782054/frontendf194e72/history5 сохранён. Независимые12.5 сценарии остаются открытыми.
## Доступ восстановлен пользователем — 2026-10-08
12.5.32 [API/native1→2](ux-ui/acceptance/chr-access-restored-2026-10-08.json), [realbrowserdashboard](ux-ui/acceptance/dashboard-access-restored-2026-10-08.json) passed. Пользователь восстановил парольCHR2; агентне менялRouterOSaccounts/credentialsприложения. Четыре каталога200/failures0, прежниеошибкиUI отсутствуют; nativeTCPtransmit3s1→2 done/HTTP200/53ms0%loss/однаhistorydone. Mainhistory5→6 намеренно; runtimebackend8782054/frontendf194e72 прежний. Старыеисторическиеошибкине переписаны; источник измененияпароля/все прежниеtimeouts не установлены. ОжиданиедоступаCHR2 снято, следующие12.5сценарии ещёоткрыты.
## TCP directions после восстановления — 2026-10-08
12.5.33 [receive/both native/API/history](ux-ui/acceptance/speed-directions-recovered-2026-10-08.json) passed: две TCP3s команды1→2, HTTP200/done testing, receiveTXnull/RXmeasured, bothTXRXmeasured, Ping53ms0%loss. УникальныеGEThistory строки совпали сAPI; mainhistory6→8 намеренно. Это функциональные значения, неbenchmark. Runtimebackend8782054/frontendf194e72/RouterOSconfiguration прежние. Следующий12.5.34 — ограниченныйUDPtest; остальные12.5сценарии открыты.
## UDP native/API/history/UI — 2026-10-08
12.5.34 [UDPtransmit3s](ux-ui/acceptance/speed-udp-2026-10-08.json) passed: HTTP200/native done testing, TXmeasured/RXnull, Ping53ms0%loss; independenthistory/realbrowserUDP/done/unknownRX/320fits/JS0. Mainhistory8→9 намеренно. Rate cap не задавался, ограничение поduration3s; packet-deliveryratio/benchmark не заявлены. КонфигурацияRouterOS/пароли/runtimebackend8782054/frontendf194e72 прежние. Следующий12.5.35 — Q-6 PostgreSQL dedupe без реальнойотправки сообщений. Остальной12.5 открыт.
## Q-6 dedupe — 2026-10-08
12.5.35 [productionenqueue/PG race](ux-ui/acceptance/outbox-dedupe-2026-10-08.json) passed:2blockedINSERTs/receipts true-false/однаpendingстрока/повторfalse. Fixtureудалена/countbaseline восстановлен; dispatcherне запускался/сообщений0, mainruntime прежний. Q-6 принят; следующий12.5.36 — Q-4 unknownretry/version без отправки.
## Q-4 retry/version — 2026-10-08
12.5.36 [realHTTP/PG](ux-ui/acceptance/outbox-retry-2026-10-08.json) passed:2blockedUPDATE/200-409/version0→1; stale409, processing409, ackfalse400, отказанныезапросыне меняютстроку. Fixtureудалена/baselinecount восстановлен, app/pool/containerзакрыты, dispatcherне вызывался/сообщений0. Q-4 принят; Q-5 толькоprocessing-refusal. Runtime/mainhistory9 прежние. Следующий12.5.37 — конкурентныйclaimQ-1; реальныеTelegramdelivery scenarios требуютсогласованногочата/разрешенияна сообщения.
## Malformed retry receipt rollback — 2026-10-08
12.5.36.1 [realPGtrigger/HTTP500/SQLrollback](ux-ui/acceptance/outbox-receipt-rollback-2026-10-08.json) passed: version2 отклонена, unknown/version0 сохранены. Fixture/trigger/functionудалены, app/pool/containerзакрыты, сообщений0. Runtimeпрежний; полнаяQ-7/Telegramприёмка открыта. Следующий12.5.37 — Q-1claim после проверкилимита.
## Q-1 production claim — 2026-10-08
12.5.37 [realPG/productiondispatcher](ux-ui/acceptance/outbox-claim-2026-10-08.json) passed:2blockedclaims/interceptedsender1/sentfixture1/history1/no duplicatecall. Реальныхсообщений0; fakeTelegramsettings/fetchзамена сняты, fixtureудалена/DBcountbaseline восстановлен. Q-1принятдляодногопроцесса/несколькихPGconnections, не реальнаяTelegramдоставка. Runtimeпрежний. Следующий12.5.38 — SQLsettlementfailure послеfixtureacceptedresponse.
## 12.5.38 — ошибки сохранения после принятого ответа отправителя (2026-10-08)
[Отчёт PostgreSQL](ux-ui/acceptance/outbox-settlement-2026-10-08.json): production dispatchPendingOutbox из backend8782054, отдельная БД mmapp_acceptance_20261007. Telegram fetch перехвачен внутри изолированного процесса и возвращает ok=true; реальных сообщений не отправлено.
Реальный BEFORE INSERT trigger отклонил запись истории: транзакция settlement откатилась, outbox перешёл в unknown, история отсутствует. Повторный dispatcher не вызывает отправителя. После явно подтверждённого повторения синтетической записи проверена другая граница: PostgreSQL действительно выполнил COMMIT, затем обёртка node-pg ввела ошибку получения подтверждения. Outbox остался sent с resolution_version=1, история содержит ровно одну строку sent_ok=true; попытка hold не перезаписала подтверждённое состояние. Следующий dispatcher не повторил отправку. Поле result.sent=1 отражает принятый подменённый API-ответ и само по себе не подтверждает сохранение или реальную доставку.
Тестовые outbox/history/trigger/function удалены; исходные настройки Telegram восстановлены из памяти, fetch возвращён, pool и контейнер завершены. Основная БД и runtime не менялись. Это проверка SQL rollback и границы подтверждения COMMIT в одном процессе; физический разрыв соединения и реальная доставка Telegram не проверены.
Следующий блок 12.5.39 — неопределённый ответ отправителя и отказ записи unknown, без реальных сообщений. План, журнал этапа и протокол синхронизированы; локальный коммит без push.
## 12.5.39 — неопределённый ответ отправителя и отказ записи unknown (2026-10-08)
[Отчёт PostgreSQL](ux-ui/acceptance/outbox-unknown-2026-10-08.json): production dispatchPendingOutbox из backend8782054, отдельная БД mmapp_acceptance_20261007. Fetch вместо внешнего запроса бросает исключение: это управляемая проверка отсутствия ответа, а не физический сетевой timeout и не доказательство доставки в Telegram.
В первом случае dispatcher вернул sent=0/failed=0/held=1, строка стала unknown без увеличения retry_count, история отсутствует. Повторный dispatcher не вызывает отправителя. Во втором случае реальный PostgreSQL trigger отклонил UPDATE unknown: строка осталась processing, API результата сообщает, что сохранение не подтверждено и автоматического повтора нет. После удаления триггера повторный dispatcher тоже не отправил сообщение. Два вызова перехваченного отправителя соответствуют двум явно подготовленным синтетическим сценариям; реальных сообщений — ноль.
Тестовые записи и объекты БД удалены, исходные настройки Telegram восстановлены из памяти с сохранением точного updated_at, fetch восстановлен, pool и контейнер закрыты. Отдельный SQL-запрос подтвердил ноль fixture-записей, ноль тестовых триггеров и функций для блоков 38–39. Основной стенд не затрагивался. Q-3 принят только на границе поведения production sender/PG; реальный чат, UI этого состояния и многопроцессное восстановление отдельно не проверены.
Следующий блок 12.5.40 — явный отказ отправителя, задержка повтора и исчерпание попыток, без реальных сообщений. Документы синхронизированы; локальный коммит без push.
## 12.5.40 — подтверждённый отказ и исчерпание попыток отправки (2026-10-08)
[Отчёт PostgreSQL](ux-ui/acceptance/outbox-rejection-2026-10-08.json): production dispatchPendingOutbox из backend8782054, отдельная БД mmapp_acceptance_20261007. Внешний fetch возвращал явный Telegram отказ ok=false/error_code=400; реального запроса и сообщений не было.
Первая отклонённая попытка сохранила pending/retry_count=1, историю не создала и назначила next_attempt_at через 15 секунд. SQL timestamp проверен относительно времени до и после вызова; немедленный dispatcher не отправил повторный запрос. Чтобы не ждать таймер, только в fixture срок следующей попытки затем перенесён на now(). Вторая отклонённая попытка исчерпала maxRetries=2: failed/retry_count=2, одна история с sent_ok=false; последующий dispatcher больше не отправлял. Синтетический токен в description скрыт как [TOKEN] в сохранённой ошибке и ответе dispatcher.
Fixture outbox/history удалены, исходные настройки Telegram восстановлены из памяти с точным updated_at, fetch восстановлен, pool и контейнер завершены. Основной стенд не затрагивался. Это приёмка реального SQL и production-кода с перехваченным отказом; реальный Telegram отказ, нагрузка и многопроцессная работа не заявлены.
Следующий блок 12.5.41 — браузерная проверка unknown/processing через реальные HTTP и PostgreSQL, без отправки сообщений. Документы синхронизированы; локальный коммит без push.
## 12.5.41 — браузерная очередь через реальные HTTP и PostgreSQL (2026-10-08)
[Отчёт браузера](ux-ui/acceptance/browser-outbox-2026-10-08.json): production backend8782054/frontendf194e72, отдельная БД mmapp_acceptance_20261007. Пять синтетических SQL-состояний pending/processing/unknown/sent/failed, по одной строке; настоящий GET overview возвращает согласованные counts/items. HTTP-ответы в браузере не подменялись. Dispatcher не запускался, scheduler admission закрыт; внешний Telegram fetch дополнительно запрещён.
UI показывает понятные подписи и предупреждение об отсутствии автоматического повтора. Для unknown кнопка доступна, для processing отсутствует. Подтверждение риска требуется до постановки в очередь; отмена и Escape не отправляют POST и возвращают фокус. Управляемое исключение backend overview дало настоящий HTTP500: последний снимок сохранился, после восстановления ошибка исчезла. Reload сохранил SQL-состояния. Панель и диалог помещаются в 320px; итоговые снимки сделаны после завершения обновления и просмотрены: [ПК](ux-ui/screens/outbox-real-1280-2026-10-08.png), [телефон](ux-ui/screens/outbox-real-320-2026-10-08.png), [подтверждение](ux-ui/screens/outbox-confirm-real-320-2026-10-08.png). Queue HTTP statuses: 200/500/200/200; JS errors=0, retry POST=0, external sender calls=0.
Первый запуск остановлен проверкой маркера БД: Next rewrites закреплены во время сборки, runtime BACKEND_INTERNAL_URL не изменяет их. Для корректной изоляции frontend подключён только к отдельной Docker-сети с alias backend, разрешающим исключительно тестовый backend. Основной backend/БД не менялись. Временные контейнеры и сеть удалены; backend завершился с exitCode=0, журнал очистки подтвердил senderCalls=0/retryPosts=0, независимый SQL подтвердил ноль fixture-строк. Дополнительный SSH-туннель3018 закрыт; основной3000 сохранён.
Границы: AUTH_REQUIRED=false на изолированном loopback стенде; реальные Portal SSO, доставка Telegram, физический отказ PG и успешный UI retry не проверены этим блоком. Следующий 12.5.42 — настоящие JWT/RBAC чтения и повтора очереди на PostgreSQL. Локальный коммит без push.
## 12.5.42 — настоящие JWT/RBAC очереди на PostgreSQL (2026-10-08)
[Отчёт JWT/RBAC](ux-ui/acceptance/outbox-rbac-2026-10-08.json): production buildApp/handlers/auth из backend8782054, AUTH_REQUIRED=true только внутри изолированного процесса, отдельная БД mmapp_acceptance_20261007. JWT HS256 подписаны серверным ключом в памяти; подпись, issuer и exp проверяет штатный middleware. Fastify inject проходит настоящий путь приложения и SQL, но не является браузерным запросом или удалённым сокетом.
GET outbox: anonymous, неверные issuer/signature, expired и malformed дают401; отсутствие разрешений, settings:admin без alerts и отсутствие доступа к приложению дают403; alerts:read/write/admin дают200 и реальные counts. Все GET сохраняют строки. Девять отказанных POST дают401/403, не меняют snapshot БД и не вызывают production retry boundary. Неподтверждённый риск даёт400 до boundary; неверная ожидаемая версия даёт409 без изменения. Разрешённые write и admin получают200, две fixture-строки становятся pending/retry_count=0/resolution_version=1. Дублирующий POST со старой версией даёт409 и сохраняет SQL snapshot. Ответы проверены на отсутствие JWT и ключа.
Первый запуск harness остановился до создания fixture: jose отсутствует в production-образе как тестовая зависимость. Для генерации стандартной HS256 подписи использован встроенный node:crypto, production middleware и настройки не менялись. Dispatcher не запускался, scheduler admission закрыт, сообщений не отправлено. App/pool/container завершены; fixture удалены, отдельный SQL подтвердил ноль тестовых строк; остались только три основные Compose-службы.
Границы: реальный Portal login/issuer endpoint не вызывался, браузерный RBAC и доставка не заявлены этим тестом. Q-7 подтверждён для API отказа до действия в этих границах. Следующий блок 12.5.43 — успешный UI retry и сохранение checkpoint при потере подтверждения HTTP в отдельной БД, с запретом внешней отправки. Локальный коммит без push.
## 12.5.43 — браузерный повтор и потеря подтверждения после COMMIT (2026-10-08)
[Отчёт браузера](ux-ui/acceptance/browser-outbox-retry-2026-10-08.json): production backend8782054/frontendf194e72, отдельная БД mmapp_acceptance_20261007, два синтетических unknown-сообщения. Реальные браузерные HTTP запросы и production retry transaction; scheduler admission закрыт, dispatcher не запускается, внешний Telegram fetch запрещён. Изолированный frontend использует отдельную Docker-сеть и alias backend.
Первый POST200 подтверждает только постановку в pending/version1, подпись UI прямо сообщает, что отправка и доставка ещё не подтверждены. Во втором сценарии обёртка production retry бросает исключение после завершённой транзакции: настоящий HTTP500 при фактически сохранённом pending/version1. Диалог и checkbox риска остаются, повтор заблокирован. После отмены, refresh и reload предупреждение о неизвестном результате сохраняется; SQL подтверждает две pending-строки/version1/retry_count0 и ноль истории. Явная проверка результата снимает checkpoint без нового POST. Всего POST:200/500, lostReceipts1, senderCalls0, JS errors0; панель и диалог помещаются в320px.
Скриншоты просмотрены: [предупреждение после перезагрузки](ux-ui/screens/outbox-retry-checkpoint-real-320-2026-10-08.png), [диалог после HTTP500](ux-ui/screens/outbox-retry-unknown-real-320-2026-10-08.png). Первое тестовое ожидание внутреннего текста исключения исправлено на штатный production текст «Внутренняя ошибка сервера»; приложение не обязано раскрывать исключение. При пересоздании fixture первый прогон очищен с exitCode0. Итоговые контейнеры/сеть/туннель3018 удалены, backend exitCode0, независимый SQL подтвердил ноль fixture-строк. Основной стенд и RouterOS не менялись.
Границы: управляемый отказ получения receipt после фактического COMMIT, а не физический разрыв сети; AUTH_REQUIRED=false; реальных сообщений и проверки чата нет. Найдена UX-недоработка: внутри открытого диалога generic HTTP500 не объясняет неизвестный исход текущего повтора. Следующий блок 12.5.44 — явное пояснение и профильная проверка диалога. Локальный коммит без push.
## 12.5.44 — понятное пояснение неподтверждённого повтора в диалоге (2026-10-08)
По результатам реального теста12.5.43 уточнён catch в components/alerts-outbox-panel.tsx. При HTTP500, потере ответа или некорректном receipt ошибка прямо в открытом диалоге сообщает: «Результат повтора не подтверждён. Автоматический повтор заблокирован. Проверьте очередь и чат перед новой попыткой», затем показывает подробность ошибки. API400/401/403/409/422 остаются подтверждёнными отказами: checkpoint снимается, исходная ошибка сохраняется. Правила повторной отправки, права и API не менялись.
Профильный Playwright alerts-outbox.spec.ts:8/8, включая новый HTTP500 сценарий, сохранённый checkbox, disabled retry, reload guard и320px; прежние success, malformed receipt, reader, conflict и focus/cancel проходят. Eslint изменённых файлов и tsc --project tmp/tsconfig-speed-check.json --noEmit passed. Scoped config исключает старые копии исходников в tmp; это не утверждение о чистоте обычного полного tsc. [Локальный диалог320px](ux-ui/screens/outbox-retry-explained-local-320-2026-10-08.png) просмотрен. HTTP-ответы в этих локальных браузерных тестах подменены; реальные SQL/HTTP результаты43 сохраняются отдельно.
Применён skill ReUI и MCP get_audit_checklist: композиция, установленные primitives, base-nova и semantic tokens сохранены; новых API/стилей/компонентов нет. Ошибка объявляется существующим role=alert, реальные секреты не добавлены; подтверждение риска и управление фокусом покрыты профильными тестами. Изменение пока локальное, удалённый frontend остаётсяf194e72.
Следующий12.5.45 — production Docker build нового frontend, обновление тестового стенда и повтор сценария HTTP500 после COMMIT на отдельной БД. Локальный коммит без push.
## 12.5.45 — production frontend с пояснением неизвестного исхода (2026-10-08)
[Развёртывание](ux-ui/acceptance/deployed-frontend-b55588f-2026-10-08.json): чистый frontend Git archive из b55588f29be0de02639bc795801e55b89f03aad7, SHA256 f18be60c1dc8c581e26040003d2c655ee2ae1da73044d761b166ac10dca71a7e совпал после передачи. Docker context повторяет frontend staging main workflow, workspaces ограничены packages; production build, полный TypeScript-check внутри образа и export завершились с exit0. Образ mmapp-test/frontend:ux-b55588f, imageId sha256:c3ce5aa8a3dbed7eaab23178cecbce2b2c1a27c31678590b54bc27db5820e5b1; исходный frontendf194e72 сохранён для отката. .env изменён только MMAPP_IMAGE_TAG, backend8782054 прежний и healthy, frontend опубликован исключительно127.0.0.1:3000. Git/image push не выполнялся.
[Повтор реального browser retry](ux-ui/acceptance/browser-outbox-retry-b55588f-2026-10-08.json): новый production frontend и прежний backend на отдельной PostgreSQL БД, без browser HTTP mocks. POST200/500, второй ответ потерян управляемым исключением после фактического COMMIT. Новый текст прямо в диалоге объясняет неподтверждённый исход и необходимость проверки; checkbox/форма/блокировка сохранены. Обе fixture pending/version1/retry_count0; история0, Telegram calls0. Refresh/reload сохраняют checkpoint, явная проверка снимает его без нового POST. Панель/диалог320px помещаются, JS errors0. [Диалог](ux-ui/screens/outbox-retry-explained-real-320-2026-10-08.png) и [checkpoint](ux-ui/screens/outbox-retry-checkpoint-b55588f-real-320-2026-10-08.png) просмотрены.
[Smoke основной схемы](ux-ui/acceptance/deploy-browser-b55588f-2026-10-08.json): dashboard, servers, uptime speed, settings, filters, alerts возвращают200,320px fit, JS errors0/API errors0. Независимый контроль основной БД до/после совпадает: servers2/enabled2, speedHistory9, retention14, migrations9. Новые native тесты или сообщения не запускались. Тестовые контейнеры/сеть/туннель3018 удалены, backend fixture завершился exit0, независимый SQL подтвердил ноль его outbox-строк. Основной туннель3000 сохранён.
Границы: управляемый HTTP500 после COMMIT вместо физического сетевого разрыва; синтетические записи и AUTH_REQUIRED=false в изолированном browser стенде. Реальные Telegram доставка/чат, Portal SSO и multi-instance остаются отдельной приёмкой. Уточнены текущие версии и устаревшая сводка плана/паспорта, исторические записи сохранены. Следующий12.5.46 — браузерные права очереди с настоящими JWT. Локальный коммит без push.
## 12.5.46 — браузерные права очереди с подписанными JWT (2026-10-08)
[Отчёт браузера](ux-ui/acceptance/browser-outbox-jwt-2026-10-08.json): production frontendb55588f/backend8782054, отдельная PostgreSQL БД mmapp_acceptance_20261007. AUTH_REQUIRED=true только в тестовом процессе, отдельные синтетические HS256 key/issuer, два браузерных контекста read/write. Штатный backend проверяет подпись и разрешения; browser HTTP-ответы не подменялись. Основные настройки авторизации и ключи не изменялись, реальный Portal не вызывался.
Reader получает очередь и видит disabled retry. Прямой POST через browser fetch с reader JWT даёт403, SQL snapshot не меняется, mutation boundary не вызывается. JWT с теми же write claims, но неверной подписью, получает401 через настоящий HTTP API; строка и счётчик mutation сохраняются. Writer видит доступную кнопку, обязательное подтверждение риска, после него POST200 переводит fixture unknown/version0 в pending/version1/retry_count0. UI подтверждает только постановку в очередь; API принял0, история0. Reader после reload видит подтверждённое состояние.
Всего retry HTTP requests3 (403/401/200), mutation calls1, external sender calls0, JS errors0;320px fit. [Читатель](ux-ui/screens/outbox-jwt-reader-real-320-2026-10-08.png) и [после разрешённого повтора](ux-ui/screens/outbox-jwt-writer-real-320-2026-10-08.png) сохранены; экран читателя просмотрен. Тестовая запись синтетическая; scheduler admission закрыт, dispatcher не запускался, Telegram fetch дополнительно запрещён. Writer и reader имеют также необходимые read-права окружающей оболочки, но только writer имеет alerts:write.
Тестовые контейнеры/сеть/туннель3018 удалены; backend завершился exitCode0, cleanup подтвердил1mutation/3POST/0send, независимый SQL — ноль fixture-строк. Основной стенд/БД/RouterOS не менялись. Это подтверждение browser и API RBAC, не реального Portal login или Telegram доставки. Следующий12.5.47 — checkpoint и смена источника при незавершённом повторе. Локальный коммит без push.
## 12.5.47 — изоляция checkpoint при смене источника во время повтора (2026-10-08)
[Отчёт браузера](ux-ui/acceptance/browser-outbox-source-2026-10-08.json): текущий frontend sourceb55588f в Next dev с поддерживаемым NEXT_PUBLIC_BACKEND_URL=local, два настоящих backend8782054 и разные PostgreSQL БД: A mmapp_acceptance_20261007, B временная mmapp_acceptance_sourceb_20261008. Browser HTTP-ответы не подменялись. Production frontend остаётся same-origin с закреплённым источником; результат этого блока относится к конфигурации local, не к переключению в production.
Два синтетических сценария: нормальный поздний receipt и ошибка producer после реального retry COMMIT. Перед навигацией независимый SQL через контрольный endpoint подтверждает A pending/version1/retry_count0, ответ удержан. При A→B отображается только запись B unknown/version0, её кнопка доступна, checkpoint A и его подписи отсутствуют; БД B неизменна. При возврате в A предупреждение неизвестного результата сохраняется. Освобождение позднего producer outcome не снимает checkpoint и не показывает устаревший успех/ошибку; reload и refresh сохраняют защиту. Явная проверка результата снимает её без нового POST. По одному retry в A на сценарий, B retry0, Telegram calls0, JS errors0,320px fit.
[Поздний receipt](ux-ui/screens/outbox-source-receipt-real-320-2026-10-08.png) просмотрен; [поздняя ошибка](ux-ui/screens/outbox-source-error-real-320-2026-10-08.png) сохранена. Навигация штатно abort-ит старый клиентский запрос; управляемая задержка producer не является физическим разрывом сети или доказательством доставки сообщения. Scheduler admission закрыт, dispatcher не запускался, внешний Telegram fetch дополнительно запрещён. AUTH_REQUIRED=false на изолированных процессах; реальные Portal login и чат не проверены.
Оба backend завершились exitCode0, cleanup подтвердил A retry2/B retry0 и sender0. Независимые SQL-запросы подтвердили ноль fixture-записей в обеих БД. Контейнеры, локальный Next3101 и туннели8018/8019 удалены. Новая БД B удалена после проверки точного имени, владельца mmapp и отсутствия соединений; PostgreSQL подтвердил отсутствие БД. Основной стенд и БД не менялись. Следующий12.5.48 — профильная доступность очереди/диалога на production frontend. Локальный коммит без push.
## 12.5.48 — доступность production очереди и диалога (2026-10-08)
[Отчёт доступности](ux-ui/acceptance/browser-outbox-a11y-2026-10-08.json): production frontendb55588f/backend8782054, отдельная PostgreSQL БД, browser HTTP-ответы не подменялись. Axe4.11.3 с WCAG2A/AA,2.1A/AA,2.2AA tags: тёмная/светлая темы ×1280/320px, по четыре области/состояния — очередь, диалог без согласия, диалог с согласием, очередь при ошибке GET. Все16 scoped audits: violations0/incomplete0, passed rules14 для очереди и16 для диалога.
Клавиатура открывает диалог через Enter, Space переключает подтверждение риска и доступность submit. По шесть Tab/Shift+Tab проверок в каждом сочетании подтверждают завершённый перенос фокуса внутри modal; Escape закрывает и возвращает фокус trigger. Асинхронные состояния имеют role=status, ошибка GET — role=alert; после восстановления ошибка исчезает. Панель/диалог помещаются в320px. [Светлая тема](ux-ui/screens/outbox-a11y-light-real-320-2026-10-08.png) и [тёмная тема](ux-ui/screens/outbox-a11y-dark-real-320-2026-10-08.png) сохранены и просмотрены.
Уточнены ожидания harness: сначала готовность доступной кнопки после основной загрузки, затем завершение CSS-анимации перед контрастным аудитом и завершение переноса фокуса через Base UI focus guards. Первый аудит поймал промежуточную прозрачность входной анимации; после её завершения контраст прошёл без изменения продукта. Это аудит устойчивых состояний, не проверка всех кадров перехода. HTTP500 создан управляемым backend overview exception; физический отказ БД не моделировался. Реальная screen reader сессия не проводилась, scoped axe/клавиатура не означают полную WCAG сертификацию приложения.
Retry POST0, Telegram calls0, JS errors0, SQL fixture counts сохранялись во всех сценариях. Dispatcher не запускался, scheduler admission закрыт. Временные контейнеры/сеть/туннель3018 удалены, backend exitCode0, отдельный SQL подтвердил ноль fixture-строк. Основной стенд и данные не менялись. Следующий12.5.49 — сводка Q-матрицы и точные оставшиеся условия реальной внешней приёмки. Локальный коммит без push.
## 12.5.49 — сводка очереди и оставшихся внешних условий (2026-10-08)
Сверены сохранённые JSON evidence блоков35–48: отчёты читаются, дата2026-10-08 и backend8782054 согласованы; актуальные browser отчёты используют frontendb55588f. Это сводка уже выполненных проверок, новых отправок или сетевых изменений нет.
| ID | Подтверждённый результат | Что остаётся за пределами проверки |
| --- | --- | --- |
| Q-1 | Два production claim на PG дают один вызов перехваченного отправителя и одну историю: [37](ux-ui/acceptance/outbox-claim-2026-10-08.json) | Несколько процессов/экземпляров, настоящая Telegram доставка |
| Q-2 | Реальный SQL отказ истории откатывает settlement; ошибка подтверждения после COMMIT не перезаписывает sent: [38](ux-ui/acceptance/outbox-settlement-2026-10-08.json) | Принятый ответ настоящего Telegram API, независимая проверка тестового чата |
| Q-3 | Неопределённый sender response удерживает unknown/processing без auto retry; browser checkpoint переживает HTTP500/reload: [39](ux-ui/acceptance/outbox-unknown-2026-10-08.json), [45](ux-ui/acceptance/browser-outbox-retry-b55588f-2026-10-08.json) | Физический timeout/disconnect после возможной реальной отправки и сверка с чатом |
| Q-4 | Конкурентные retry дают200/409 и одно увеличение версии; старый повтор не меняет БД: [36](ux-ui/acceptance/outbox-retry-2026-10-08.json), [46](ux-ui/acceptance/browser-outbox-jwt-2026-10-08.json) | Queue receipt не означает доставку |
| Q-5 | Processing отвергается, обязательное подтверждение риска и блокировка неизвестного исхода работают: [36](ux-ui/acceptance/outbox-retry-2026-10-08.json), [45](ux-ui/acceptance/browser-outbox-retry-b55588f-2026-10-08.json) | Операционная процедура остановки всех реальных senders, включая несколько экземпляров, перед осознанным повтором |
| Q-6 | Два конкурентных enqueue создают одну строку, повтор возвращаетfalse: [35](ux-ui/acceptance/outbox-dedupe-2026-10-08.json) | Не отдельное доказательство Telegram delivery |
| Q-7 | Malformed receipt откатывает реальную транзакцию; JWT/read/write защищают API и UI; ABA source isolation сохраняет checkpoint: [36.1](ux-ui/acceptance/outbox-receipt-rollback-2026-10-08.json), [46](ux-ui/acceptance/browser-outbox-jwt-2026-10-08.json), [47](ux-ui/acceptance/browser-outbox-source-2026-10-08.json) | Настоящий Portal login; source switching проверен в поддерживаемой local-конфигурации, production закреплён same-origin |
| UX/a11y | Dark/light1280/320,16 scoped axe audits, keyboard/focus/error states: [48](ux-ui/acceptance/browser-outbox-a11y-2026-10-08.json) | Ручная screen reader приёмка и полная WCAG оценка приложения |
[Готовность Telegram](ux-ui/acceptance/telegram-readiness-2026-10-08.json): штатный GET alerts на основном тестовом стенде, сохранены только признаки tokenConfigured=false/chatConfigured=false/threadConfigured=false. Токен, chat ID и исходный ответ не сохранялись. Telegram пока не настроен; real-message сценарии не могут быть приняты по подменённым ответам. Для этой ветки нужен отдельный тестовый бот/чат в приложении и явное разрешение на одно конкретное тестовое сообщение; до этого внешние сообщения не отправлять.
Этап12.5 остаётся открытым. Проверенные группы не заменяют остальные PG/ROS/Portal/интеграционные сценарии протокола. Следующий12.5.50 — read-only инвентаризация двух CHR для определения доступных VPN/маршрутизации/диагностики и подготовки оставшихся сетевых проверок; конфигурацию устройств этим шагом не менять. План/паспорт/протокол синхронизированы. Локальный коммит без push.
## 12.5.50 — инвентаризация двух CHR без изменения конфигурации (2026-10-08)
[Отчёт CHR](ux-ui/acceptance/chr-network-inventory-2026-10-08.json): штатный MikrotikClient из backend8782054, соединения из существующих записей основной тестовой БД, только enabled устройства194.226.121.150/id1 и104.165.244.7/id2. Использованы исключительно GET; post/put/patch/delete в тестовом процессе дополнительно запрещены. Не запускались Ping/bandwidth, scheduler или buildApp. Сырые VPN ответы, ключи и пароли оставались в памяти и не сохранялись/не выводились.
Оба устройства отвечают, RouterOS7.24.5 stable, CHR; оба имеют appType home-router. На каждом прочитаны19 разделов и повторно сверены выбранные конфигурационные поля; вместе с resource78 GET. Все разделы доступны, selectedConfigurationUnchanged=true. Сверка ограничена перечисленными в harness полями, не является полным export или доказательством отсутствия любых внешних изменений.
| Раздел | CHR1 / CHR2 | Следствие для приёмки |
| --- | --- | --- |
| Интерфейсы | 2/2: ether и loopback | Нет VPN-интерфейсов для действий над существующим туннелем |
| IPv4 адреса / маршруты | 1/2 адреса,4/5 маршрутов | Существующая адресация и маршруты сохранены; connectivity этим GET не доказана |
| WireGuard / peers, GRE, VXLAN | 0/0 в каждом разделе | Можно проверить истинное пустое состояние; ROS6 lifecycle/connectivity требует отдельного тестового объекта |
| IPsec | Peers0,active-peers0; на каждом1policy/template | Стандартный template не считать действующим VPN |
| BGP connections/sessions | 0/0 | Для реального сценария нужны тестовый peer и сессия |
| OSPF instances/templates/neighbors | 0/0 | Preview/apply/factual cost в ROS5 пока проверить не на чем |
| IPv4 Firewall filter/NAT/mangle, routing filters | 0/0 | Пустая конфигурация подтверждена; IPv6 и реальные изменения правил не приняты |
| Роли приложения | home-router/home-router | Home→JH и JH↔Exit в ROS4 не подтверждены текущей парой ролей |
Контроль основной БД до/после совпадает: servers2, speedHistory9, retention14. Дополнительный SELECT подтвердил роли home-router. Эфемерный контейнер завершён/удалён, pool закрыт; остались только три основные Compose-службы. Пароли, адресация и правила устройств не менялись. Эта инвентаризация не закрывает ROS4/5/6 или остальные внешние ограничения.
Следующий12.5.51 — проверить реальные пустые состояния, выбор устройства/URL-контекст и доступность форм сетевых экранов на production frontend, без изменения RouterOS. После этого конкретный план создания изолированных тестовых объектов должен сохранять административный доступ и существующую конфигурацию. План/паспорт/протокол синхронизированы; локальный коммит без push.
## 12.5.51 — реальная GRE пара, связность и lifecycle (2026-10-08)
По прямому поручению пользователя VPN-приёмка продолжается с созданием реальных тестовых туннелей, особенно GRE. [Lifecycle](ux-ui/acceptance/gre-real-lifecycle-2026-10-08.json): production backend8782054, два CHR7.24.5, собственные имена mm-acceptance-gre-* и комментарий владения. Перед записью проверены локальные внешние адреса и отсутствие пересечения198.18.255.248/30 с существующей адресацией/недефолтными маршрутами. POST application API создал обе GRE стороны и /ip/address:201/201. Внешние endpoints194.226.121.150 ↔104.165.244.7, внутренние198.18.255.249/30 ↔198.18.255.250/30, MTU1400,keepalive2s/3. Дополнительных static/default routes и Firewall правил не создавалось.
После running=true независимый RouterOS Ping через указанный GRE интерфейс:3/3 в каждом направлении,0%loss,~54ms. Это реальная point-to-point связность, не benchmark и не шифрованный IPsec. PATCH MTU первого конца1360, disable и enable дали200 и подтверждены отдельным чтением RouterOS. [Browser](ux-ui/acceptance/browser-gre-real-2026-10-08.json): настоящие созданные объекты, формы обоих устройств, local IP и server/tunnel URL-контекст/reload/320px, JS errors0; browser проход читает/отменяет формы, создание/изменение выполнял production API. [ФормаCHR1](ux-ui/screens/gre-real-form-server1-320-2026-10-08.png) просмотрена, [CHR2](ux-ui/screens/gre-real-form-server2-320-2026-10-08.png) сохранена.
Первый запуск Ping до готовности получил timeout; [повтор после running](ux-ui/acceptance/gre-ready-ping-2026-10-08.json) подтвердил3/3. Первый harness остановил свою очистку на слишком строгом сравнении baseline, включавшем runtime IDs; причина конкретного несовпадения не была сохранена полностью. [Независимая очистка](ux-ui/acceptance/gre-cleanup-recovery-2026-10-08.json) удалила оставшуюся собственную сторону и подтвердила отсутствие интерфейсов/IP/connected route, исходные количества0GRE/1–2addresses/4–5routes. Harness исправлен: сначала очистить обе стороны, сравнивать конфигурационные поля без runtime IDs, сохранить evidence до assertion. Повторный полный lifecycle прошёл с exitCode0: DELETE200/200, все выбранные поля GRE/IP/route/IPv4 Firewall совпали с baseline. Прямое административное восстановление чужих объектов не выполнялось.
Обнаружен настоящий дефект: принятый remoteInnerIp возвращается пустым, затем теряется в форме редактирования. Связность обеспечивается настройкой обоих реальных /ip/address, но сохранение формы этим не считается исправленным. Следующий12.5.52 — исправить metadata persistence/restore peer IP и профильные тесты, затем развернуть и повторить настоящий GRE цикл. Ограничения ROS6 для остальных VPN/прав/частичных отказов остаются. Control main2servers/9speed/retention14 сохранён; application GRE revisions намеренно остаются журналом выполненных действий. Временный контейнер/туннель8018 удалены; RouterOS тестовые объекты очищены. Локальный коммит без push.
Официальная схема пары и keepalive: [MikroTik GRE](https://manual.mikrotik.com/docs/virtual-private-networks/gre/). Документация текущей версии проверена, реальные команды/ответы — RouterOS7.24.5.
## 12.5.52 — сохранение удалённого внутреннего IP GRE (2026-10-08)
Исправлен дефект, обнаруженный на настоящей GRE паре в12.5.51. Новый backend services/gre-comment.ts хранит remoteInnerIp в версионированном base64url JSON suffix комментария RouterOS. Это метаданные приложения, не маршруты и не /ip/address на удалённом устройстве. greInterfaceBody сохраняет peer, mapGreLive возвращает его и чистый пользовательский комментарий; snapshot содержит peer и исходный raw comment для корректного restore. PATCH без remoteInnerIp сохраняет текущий peer; явная пустая строка очищает. Форма теперь передаёт пустую строку при очистке вместо пропуска поля.
Старые gateway/network комментарии читаются и сохраняются при restore; непонятный/повреждённый suffix остаётся обычным пользовательским текстом. Явная очистка legacy peer записывает пустое metadata значение, чтобы прежняя подсказка комментария не возвращала удалённое поле. Метаданные не создают сетевые маршруты и не содержат PSK/паролей; GRE/IPsec secret logic не менялась. Raw metadata видна в прямом RouterOS comment, в API/UI служебный suffix отделён от пользовательского текста.
gre-comment.test.ts проверил create plan→native comment→map→snapshot→restore, Unicode/несколько строк, idempotence, legacy, invalid suffix и explicit clear; планы ограничены GRE/IP, без /ip/route. Прежний entity-snapshots.test.ts passed. Playwright gre-form+gre-toggle5/5: создание/DTO/edit, сохранённый ввод при отказе и неверном receipt, explicit empty remoteInnerIp, подтверждение переключения. Browser ответы локальных проверок подменены; новое metadata на реальном RouterOS этим блоком не принято. Backend tsc --noEmit и scoped frontend typecheck passed. Eslint без ошибок, одно прежнее unused bool предупреждение в entity-snapshots.ts:258; дифф не меняет этот helper.
Код и тесты готовы к сборке; удалённый runtime пока backend8782054/frontendb55588f, реальные GRE объекты из51 удалены. Следующий12.5.53 — production Docker build/deploy backend и frontend, новая собственная GRE пара с независимой проверкой peer read/MTU-toggle/clear/restore, реальный UI и двусторонний Ping, очистка по имени и decoded ownership comment. Пользовательское требование реальных VPN объектов сохраняется. Локальный коммит без push.
## 12.5.53 — развёртывание peer metadata и реальный GRE regression (2026-10-08)
[Развёртывание](ux-ui/acceptance/deployed-bd3f996-2026-10-08.json): backend и frontend из bd3f996f55cccd312dfe5861900849ca21791be8, чистый Git archive SHA256 c154aa8c706d083a791ed04f26bad433cb1ab9a5d9a6c6ec08b5751d7977d46f совпал после передачи. Docker staging повторяет main workflow; обе сборки exit0, Next production compile/full TypeScript passed. Backend imageId sha256:6bb78eaeb922de577d399633ed6fcc821a47ae8abbb947ce6971bb453bfcf6d8, frontend sha256:1f22f4a2900b13bb5b1202e4a98a4c679b57d6453599318b52cbc988a63cc4053. Только две image tag переменные .env обновлены, compose validation/health passed, version1.0.0-test.bd3f996. Прежние образы сохранены. Приватный PG backup1433491bytes/PGDMP/pg_restore --list passed остаётся только на сервере; дамп и секреты в Git не передавались. Push не выполнялся.
[Настоящий GRE lifecycle](ux-ui/acceptance/gre-real-metadata-bd3f996-2026-10-08.json): новая собственная пара на двух CHR, предварительно GRE разделы пусты и подсеть198.18.255.248/30 свободна. POST201/201 вернули запрошенный peer IP и чистый пользовательский комментарий. Независимое чтение native comment подтвердило metadata, MTU1360 и disable/enable сохранили peer; explicit clear и restore собственной первой apply-ревизии подтвердились. Snapshot проверен по имени, одному объекту и peer до restore, текущий GRE state ограничен собственным fixture. Двусторонний Ping после running:true —3/3,0%loss,~54ms. Это plain GRE/point-to-point ICMP, не IPsec или throughput benchmark.
[Browser regression](ux-ui/acceptance/browser-gre-metadata-2026-10-08.json): production frontend/API без HTTP mocks, peer и local IP в формах обоих устройств, comment без служебного suffix, server/tunnel URL и reload сохранены,320px fits. НаCHR1 очистка и повторное сохранение peer через форму дали PATCH200/200, результат перечитан непосредственно с RouterOS. JS errors0. [CHR1](ux-ui/screens/gre-metadata-real-form-server1-320-2026-10-08.png) просмотрен, [CHR2](ux-ui/screens/gre-metadata-real-form-server2-320-2026-10-08.png) сохранён. [Smoke](ux-ui/acceptance/deploy-browser-bd3f996-2026-10-08.json): dashboard/servers/uptime/settings/filters/alerts200,320px fit, JS/API errors0.
Первые browser попытки остановились на меню, которое исчезало при перерисовке. Таймер первой пары удалил собственные объекты. Немедленная сверка /ip/route дала mismatch; финальный harness добавил ограниченное ожидание сходимости маршрутов, не меняя их вручную. Итоговый запуск exit0: DELETE200/200, все выбранные поля GRE/IP/routes/IPv4 Firewall совпали с baseline; CHR1 потребовал одно повторное чтение через250ms, CHR2 совпал сразу. Тестовое меню в успешном проходе пришлось открыть повторно1раз: это не исправленный UX, а отдельная выявленная недоработка для54. Проверка не является доказательством неизменности всех runtime параметров/полного export.
Own GRE интерфейсы, адреса и connected route удалены; эфемерный контейнер и туннель8018 закрыты, остались три основные Compose-службы. Main controls до/после: servers2/speedHistory9/retention14/migrations9 совпадают; GRE audit revisions намеренно сохранены. Следующий12.5.54 — сохранить устойчивость меню действий GRE при перерисовке и проверить профильный сценарий; затем продолжать настоящие VPN объекты. Права, частичные отказы остальных VPN, Portal/Telegram и прочие внешние ограничения остаются открытыми. Локальный коммит без push.
## 12.5.54 — устойчивость меню GRE при обновлении таблицы (2026-10-08)
При обновлении callbacks/прав пересоздавался inline renderer actions column; React монтировал ячейку заново и закрывал Base UI меню. В components/data-grids/gre-tunnels-data-grid.tsx вынесен стабильный GreActionsCell, текущие callbacks/permissions передаются через типизированный React context. ReUI composition, оформление, API таблицы и ключ строки serverId/id сохранены. Политика блокировки операций при загрузке и отсутствии доступа сохранена.
Проверки: новый tests/e2e/gre-menu-refresh.spec.ts открывает меню, запускает GET без outside pointer event, проверяет сохранение меню, disabled во время загрузки, восстановление enabled и свежий peer IP в форме. На прежнем HEAD тест падает именно из-за исчезнувшего menuitem; исправленный код проходит. Вместе с gre-toggle.spec.ts — 3/3 passed. Scoped TypeScript (tmp/tsconfig-speed-check.json) и ESLint изменённых файлов passed. Первую фикстуру скорректировали: инициализация источника допускает несколько GET, задержка включается только при проверяемом refresh. ReUI data-grid checklist проверен, общие компоненты не менялись.
Это локальное исправление. На тестовом сервере backend/frontend bd3f996; live CHR сценарий стабильности меню пока не проверен. Следующий12.5.55 — собрать и развернуть frontend, создать собственную реальную GRE пару, проверить меню при обновлении и форму, затем удалить только собственные интерфейсы/IP и проверить baseline. Реальные VPN объекты обязательны по указанию пользователя. Telegram/Portal/multi-instance и остальные внешние ограничения остаются открытыми. Локальный коммит без push.
## 12.5.55 — развёртывание устойчивого меню и повторная реальная GRE проверка (2026-10-08)
[Развёртывание](ux-ui/acceptance/deployed-731803b-2026-10-08.json): frontend731803bade672e4e5bd58ffbc223563f3318d4a9/version1.0.0-test.731803b. Архив Git SHA256 b6ff604a03e65151b4f2fc1406885b97f40240646f651a371fd603c00e1e867b совпал после передачи. Staging предыдущей main-совместимой сборки обновлён единственным изменённым production input — gre-tunnels-data-grid.tsx; package-lock/Dockerfile совпали. Docker build exit0, Next production compile/full TypeScript passed. Обновлена только MMAPP_IMAGE_TAG, compose validation passed; перезапущен только frontend, прежний образ оставлен для rollback. Backendbd3f996 не менялся и healthy. Контрольные значения БД до/после: servers2/speedHistory9/retention14/migrations9 совпали. Push не выполнялся.
[GRE native lifecycle](ux-ui/acceptance/gre-real-menu-731803b-2026-10-08.json): собственная новая пара mm-acceptance-gre-1791468767519, подсеть198.18.255.248/30 проверена на пересечение, оба GRE раздела исходно пусты. POST201/201, native peer metadata, snapshot/restore, MTU/disable/enable/clear подтверждены; Ping3/3 в обе стороны,0%loss. [Production browser](ux-ui/acceptance/browser-gre-menu-731803b-2026-10-08.json): никаких HTTP mocks, на каждом CHR меню открыто один раз и пережило live GET200 при1280 и320px; menuReopens0. Форма совпала с native local/remote inner IP и чистым пользовательским comment; URL/reload сохранён, JS/API errors0. Toolbar refresh вызван без outside pointer event: обычный клик вне меню должен его закрывать. Controlled pending permissions проверены локально в54, здесь подтверждено реальное обновление данных.
[CHR1 mobile](ux-ui/screens/gre-menu-real-server1-320-2026-10-08.png) визуально просмотрен, [CHR2](ux-ui/screens/gre-menu-real-server2-320-2026-10-08.png) сохранён. Первое измерение ширины произошло во время анимации Sheet и остановило browser harness; повторный проход с ожиданием сходимости layout прошёл, продуктовый код не менялся. Выявлена отдельная UX-недоработка: два внутренних IP поля слишком узкие для чтения полной записи при320px. Это следующий56, а не заявленный исправленный результат55.
DELETE200/200, own интерфейсы/IP и connected routes удалены; выбранные GRE/IP/routes/IPv4 Firewall поля совпали с baseline (CHR1 — одно повторное чтение маршрутов через250ms). Эфемерный контейнер удалён, работают только три основные Compose-службы. GRE revisions намеренно остались как история операций. [Smoke](ux-ui/acceptance/deploy-browser-731803b-2026-10-08.json): dashboard/servers/uptime/settings/filters/alerts200,320px fit, JS/API errors0. Это plain GRE и point-to-point ICMP, не IPsec/throughput/остальные VPN. Telegram/Portal/multi-instance и другие внешние ограничения остаются открытыми. Следующий12.5.56 — мобильная форма GRE; пользовательское правило создавать и очищать реальные VPN объекты сохраняется. Локальный коммит без push.
## 12.5.56 — читаемые внутренние IP в мобильной форме GRE (2026-10-08)
В app/(main)/gre/page.tsx адаптирована только сетка существующих полей: grid-cols-1 gap-3 sm:grid-cols-2. До640px локальный и удалённый IP идут друг под другом; начиная соsm — рядом. Input/Sheet, подписи, значения и API сохранения не менялись, общие ReUI primitives и оформление сохранены. Доступные249px на320px позволяют показать полный255.255.255.254/32 (измеренная ширина текста≈173px); в двух колонках на640px доступно204px.
Локальная визуальная проверка через временный Playwright harness: [светлая тема](ux-ui/acceptance/gre-mobile-inner-ip-light-2026-10-08.json), [тёмная тема](ux-ui/acceptance/gre-mobile-inner-ip-dark-2026-10-08.json). Два прохода/шесть комбинаций320/640/1280px passed: расположение полей, полный IPv4/CIDR в текущем шрифте, Tab локальный→удалённый, сохранение значения, доступность footer и отсутствие page overflow. [Светлый320px](ux-ui/screens/gre-mobile-inner-ip-light-320-2026-10-08.png) и [тёмный320px](ux-ui/screens/gre-mobile-inner-ip-dark-320-2026-10-08.png) просмотрены. API в этих проверках подменён; это доказательство локального layout, а не внешняя CHR приёмка. Первые настройки временного harness исправлены: cwd для Next и фактический ключ темы rl-theme; продуктовых ошибок это не выявило.
Итоговая профильная регрессия gre-form.spec.ts + gre-menu-refresh.spec.ts —4/4 passed: create/DTO/edit, API ошибки и неподтверждённые ответы, сохранение ввода, защита от повторной отправки, открытое меню после refresh. Scoped TypeScript (tmp/tsconfig-speed-check.json), ESLint изменённого page и ReUI checklist passed. Общая регрессия не повторялась для одной адаптивной сетки.
Изменение локальное, удалённый runtime backendbd3f996/frontend731803b не менялся. Следующий12.5.57 — frontend production Docker build/deploy и мобильная форма на новой собственной реальной GRE паре/API/RouterOS, затем очистка и baseline. Пользовательское требование настоящих VPN объектов сохраняется. Telegram/Portal/multi-instance и остальные внешние ограничения остаются открытыми. Локальный коммит без push.
## 12.5.57 — развёртывание мобильной формы и реальная GRE приёмка (2026-10-08)
[Развёртывание](ux-ui/acceptance/deployed-fd521f6-2026-10-08.json): frontendfd521f6ef892ff3f7e8bc25878d80fb13817dda8/version1.0.0-test.fd521f6, backendbd3f996 healthy. Архив Git SHA2563187feed4f9346045ccf5d878b2965093b4b115f305d1da183523d1b7988204a совпал после передачи. В main-совместимом staging предыдущей сборки обновлён единственный изменённый production input — app/(main)/gre/page.tsx; package-lock и Dockerfile совпали. Docker build exit0/production TypeScript passed. Изменена только MMAPP_IMAGE_TAG, compose validation passed; перезапущен только frontend, предыдущий731803b образ сохранён для rollback. Контрольные значения БД до/после: servers2/speedHistory9/retention14/migrations9 совпали. Push не выполнялся.
[GRE lifecycle](ux-ui/acceptance/gre-real-mobile-fd521f6-2026-10-08.json): новая собственная пара mm-acceptance-gre-1791469984747, исходные GRE разделы пусты,198.18.255.248/30 не пересекается с недефолтными маршрутами/адресами. POST201/201, native peer metadata, MTU/disable/enable/clear и snapshot restore подтверждены; Ping3/3 в обе стороны,0%loss. Это plain GRE и ICMP, не IPsec/throughput.
[Production browser](ux-ui/acceptance/browser-gre-mobile-fd521f6-2026-10-08.json): оба CHR × две темы ×320/640/1280px —12 комбинаций без HTTP mocks. Native local/remote inner IP читаются полностью; на320px одна колонка, на640/1280 две; Tab local→remote и отсутствие page overflow подтверждены. Меню сохраняется после live GET200 при1280/320px, повторных открытий0. В тёмной теме формы обоих CHR сохранены с неизменёнными значениями: PATCH200/200, независимое native чтение подтвердило адреса, peer IP и comment. Светлая тема проверена без записи. Server URL context/reload сохранён. JS/API errors0. Browser refresh вызывается без outside pointer event; локальная проверка pending/прав остаётся доказательством54.
Скриншоты320px: [CHR1 dark](ux-ui/screens/gre-mobile-real-server1-dark-320-2026-10-08.png), [CHR1 light](ux-ui/screens/gre-mobile-real-server1-light-320-2026-10-08.png), [CHR2 dark](ux-ui/screens/gre-mobile-real-server2-dark-320-2026-10-08.png), [CHR2 light](ux-ui/screens/gre-mobile-real-server2-light-320-2026-10-08.png). CHR1 dark и CHR2 light визуально просмотрены: внутренние IP целиком видны. [Smoke](ux-ui/acceptance/deploy-browser-fd521f6-2026-10-08.json): dashboard/servers/uptime/settings/filters/alerts200,320px fit, JS/API errors0.
DELETE200/200, собственные GRE/IP/connected routes удалены; выбранные GRE/IP/routes/IPv4 Firewall поля совпали с baseline, CHR1 — одно повторное чтение маршрутов через250ms. Эфемерный контейнер удалён; остались три основные Compose-службы. GRE revisions намеренно сохранены как история операций. Следующий12.5.58 — реальная собственная WireGuard пара, API/native/UI, handshake/связность, очистка и baseline; private/preshared keys не включать в публичные отчёты. Требование пользователя о настоящих VPN объектах сохраняется. Telegram/Portal/multi-instance и другие внешние ограничения остаются открытыми. Локальный коммит без push.
## 12.5.58 — настоящая WireGuard пара, handshake и UI (2026-10-08)
[Итоговый реальный lifecycle](ux-ui/acceptance/wg-real-lifecycle-2026-10-08.json): собственная пара mm-acceptance-wg-1791470702451 на двух CHR, UDP51879 и198.18.255.240/30 проверены на коллизии/пересечения. POST interfaces201/201 создали интерфейсы и IP; native чтение подтвердило автоматические ключи и адреса, POST peers201/201 — связь с публичным ключом другого устройства. Ключи проверялись в памяти и не записывались в публичные артефакты. Allowed адреса ограничены IP другого конца /32, persistent keepalive5s. Default routes/Firewall не менялись. Параметры и смысл last-handshake сверены с [официальной документацией MikroTik](https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard).
На обоих peers появился native handshake и RX>0; двусторонний Ping3/3,0%loss, около54–56ms. PATCH MTU1380 и возврат1420 подтверждены native чтением. Каталог приложения совпал с адресами/peers/handshake и не содержал privateKey по умолчанию. Это короткая проверка защищённой WireGuard связности; throughput, RBAC, interrupted mutation, экспорт и import не проверены.
[Production browser](ux-ui/acceptance/browser-wg-real-2026-10-08.json): два CHR × две темы,1280/320px без HTTP mocks. В деталях видны own peer name, Allowed IPs, endpoint, handshake и известные RX/TX; server/interface URL и вкладка peers пережили reload, page overflow отсутствует. На320px длинные имя и CIDR переносятся; исходная таблица сохраняет собственный горизонтальный scroll. Создание/изменение/удаление через UI не проверялись. JS/API errors0. Скриншоты: [CHR1 dark](ux-ui/screens/wg-real-server1-dark-320-2026-10-08.png), [CHR1 light](ux-ui/screens/wg-real-server1-light-320-2026-10-08.png), [CHR2 dark](ux-ui/screens/wg-real-server2-dark-320-2026-10-08.png), [CHR2 light](ux-ui/screens/wg-real-server2-light-320-2026-10-08.png); итоговыйCHR2 light просмотрен. Первый browser locator одновременно находил sr-only и родительскую подпись handshake, уточнение локатора дало успешный проход без изменения продукта.
[Первый проход](ux-ui/acceptance/wg-real-first-attempt-2026-10-08.json) подтвердил связность/UI, но cleanup harness получил DELETE400: Content-Type application/json был передан без тела. Это ошибка harness, не доказательство ошибки приложения. [Восстановительная очистка](ux-ui/acceptance/wg-first-cleanup-recovery-2026-10-08.json) через правильные DELETE проверила ownership comment/name и отсутствие own interfaces/peers/IP/routes. Baseline первого прохода был только в памяти и после выхода потерян; точная сверка первого baseline не заявляется. Harness исправлен, создана новая пара и повторён полный lifecycle/browser; итоговый exit0 и все выбранные baseline поля совпали.
В финальном cleanup собственные peers удалены API200/200, собственные IP явно удалены native API до удаления interfaces API200/200. Автоматическая очистка IP/peers при обычном удалении интерфейса НЕ проверена и остаётся следующим12.5.59. WireGuard/IP/routes/IPv4 Firewall выбранные настройки совпали с baseline; эфемерный контейнер удалён, работают только три основные Compose-службы. DB controls до/после servers2/speedHistory9/retention14/migrations9 совпали, backend healthy. WG revisions намеренно сохранены как история операций. Runtime backendbd3f996/frontendfd521f6 не менялся. Telegram/Portal/multi-instance и остальные внешние ограничения остаются открытыми. Локальный коммит без push.
## 12.5.59 — удаление WireGuard оставляло peer и IP; локальное исправление (2026-10-08)
[Production UI](ux-ui/acceptance/browser-wg-delete-2026-10-08.json): собственная новая пара mm-acceptance-wg-1791471219775, подтверждённые handshake/двусторонний Ping. Интерфейсы удалены через стандартные меню и AlertDialog приложения на обоих CHR (ПК/320px). DELETE200/200 закрыли диалоги, но независимое native чтение обнаружило на каждом устройстве оставшийся peer и собственный IPv4 адрес. Это подтверждённая ошибка backendbd3f996: route удалял только /interface/wireguard/id, RouterOS сохранил связанные записи.
[Native проверка и восстановительная очистка](ux-ui/acceptance/wg-real-delete-2026-10-08.json): afterBrowserDelete содержит interface:null, peerCount1 и собственный адрес на каждом CHR. Harness сохранил исходные идентификаторы own peers/IP и удалил только эти остатки, даже после исчезновения интерфейса. Финальный exit0, выбранные WG/peers/IP/routes/IPv4 Firewall поля совпали с baseline; ephemeral контейнер удалён, остались три основные службы. Это очистка теста, а не успешная приёмка стандартного удаления. Ключи не включены в публичные отчёты; WG revisions намеренно сохранены.
Локально добавлен backend/src/services/wireguard-delete.ts и подключён к DELETE route: идентификация интерфейса по rosId, чтение peers и IPv4 адресов до первой записи, отбор только связанных с именем/rosId объектов, удаление peers→addresses→interface, независимое перечитывание и ошибка при оставшихся объектах. При read failure запись не начинается; при промежуточной ошибке дальнейшее удаление прекращается, ошибка возвращается вместо ok. Успех и apply revision происходят только после проверки отсутствия объектов. Это последовательные RouterOS операции, не транзакция: частичный сбой может оставить частично удалённые данные, потребуется повтор/обновление. Текст подтверждения в WireGuard page теперь указывает связанные пиры и IP-адреса.
Проверки backend/src/services/wireguard-delete.test.ts —9/9: чужие объекты сохранены, связи по имени/rosId, encoded ID, ошибки всех предварительных чтений, неизвестный интерфейс, частичная ошибка/повтор, неподтверждённое удаление каждой группы. Profile UI tests wireguard-links.spec.ts --grep deletion/удал —2/2: подтверждение удаления интерфейса/пира, запрет повторного нажатия и повтор после API ошибки. Backend TypeScript, scoped frontend TypeScript (tmp/tsconfig-speed-check.json), ESLint изменённых файлов и ReUI checklist passed. Примитивы/таблицы не менялись.
Исправление пока локальное: удалённый backendbd3f996/frontendfd521f6 остаётся прежним. Следующий12.5.60 — production Docker build/deploy обеих частей, новая собственная WireGuard пара и обычное UI/API удаление без предварительного удаления peer/IP, независимая проверка отсутствия остатков и baseline, очистка fallback только own объектов. IPv6 address lifecycle, concurrency/multi-instance, Telegram/Portal и другие внешние ограничения не проверены. Пользовательское правило настоящих VPN объектов сохраняется. Локальный коммит без push.
## 12.5.60 — развёртывание и реальное полное удаление WireGuard (2026-10-08)
[Развёртывание](ux-ui/acceptance/deployed-3722fad-2026-10-08.json): backend/frontend3722fad329a68a8721ebfda8e044ab6cb5830cca/version1.0.0-test.3722fad. Чистый Git archive SHA256ec8084a0acbd0f26886a4c54072b65943d835b42a6a314c28e58b1b2bed791c6 совпал после передачи. Main-совместимые staging contexts предыдущих сборок обновлены только изменившимися production inputs: WireGuard route/service backend и frontend page. Docker builds exit0, backend/full Next TypeScript passed. Только BACKEND_IMAGE_TAG и MMAPP_IMAGE_TAG обновлены, compose validation passed, перезапущены backend/frontend. Прежние backendbd3f996/frontendfd521f6 образы оставлены для rollback. Приватный pre-3722fad PG backup1771860bytes/0600 с проверкой pg_restore --list остаётся только на сервере; дамп и ключи не передавались. DB controls до/после servers2/speedHistory9/retention14/migrations9 совпали, backend healthy, версия API подтверждена. Push не выполнялся.
[Настоящая пара и native проверка](ux-ui/acceptance/wg-real-delete-3722fad-2026-10-08.json): новый own fixture mm-acceptance-wg-1791472117395, свободные UDP51879 и198.18.255.240/30. Создание interfaces/peers API201, native key association, handshake/RX, короткий двусторонний Ping3/3 и MTU подтверждены до удаления. Пиры и адреса оставались прикреплены к интерфейсам до действий пользователя в тесте; предварительного удаления peers/IP harness не делал.
[Production UI delete](ux-ui/acceptance/browser-wg-delete-3722fad-2026-10-08.json): собственные интерфейсы удалены через стандартное меню и подтверждение на обоих CHR (ПК/320px), текст указывает связанные пиры и IP-адреса. DELETE200/200 закрыли диалоги; независимое native чтение сразу после каждого ответа показало interface:null, peers0, addresses[]. Проверка выполнена ДО finish/fallback cleanup. Это подтверждает исправление59 на живом RouterOS, а не маскирующую очистку harness. JS errors0; HTTP mocks отсутствуют.
Итоговый harness exit0: afterBrowserDelete пуст на обеих сторонах, выбранные WG/peers/IP/routes/IPv4 Firewall поля совпали с baseline. Fallback не понадобился для peers/IP/interfaces; ephemeral контейнер удалён, остались три основные Compose-службы. WireGuard revisions намеренно сохранены как история операций. [Smoke](ux-ui/acceptance/deploy-browser-3722fad-2026-10-08.json): dashboard/servers/uptime/settings/filters/alerts200,320px fit, JS/API errors0.
Приняты успешное обычное удаление own интерфейса с IPv4 адресом и пиром и соответствующий UI результат. Partial failures/read errors/сохранение чужих WG объектов проверены локальными тестами59; на этом стенде такие отказы не инжектировались. IPv6 lifecycle, concurrency/multi-instance, throughput, Telegram/Portal и остальные внешние ограничения остаются открытыми. Следующий12.5.61 — реальные WireGuard действия через UI: создание интерфейса и пира, переключение и очистка собственной пары; ключи не публиковать. Пользовательское правило настоящих VPN объектов сохраняется. Локальный коммит без push.
## 12.5.61 — UI создание WireGuard и локальное исправление нестабильного меню (2026-10-08)
[Первый native observer](ux-ui/acceptance/wg-ui-first-attempt-native-2026-10-08.json): собственная пара mm-acceptance-wg-ui-1791472667527, свободные UDP51879/198.18.255.240/30, интерфейсы и пиры созданы только через production формы приложения. Observer не создавал конфигурацию. Оба интерфейса/IP/native key generation и поля peers/endpoint/allowed/keepalive/comment подтвердились, native peer key association и первый двусторонний Ping3/3 прошли. Публичные ключи переданы в форму в памяти, ключи не включены в отчёты. Создание интерфейса наCHR1 выполнено наПК, наCHR2 при320px. [Мобильная форма](ux-ui/screens/wg-ui-create-server2-320-2026-10-08.png) сохранена без ключей и визуально просмотрена; этот снимок второй попытки, не доказательство переключения.
Полный сценарий НЕ завершён: первая попытка не получила PATCH переключения; вторая, mm-acceptance-wg-ui-1791472879650, после создания интерфейсов остановилась на Добавить пира. Playwright зафиксировал unstable→detached DOM menuitem при перерисовке. Callback props пересоздавали columns/inline actions cell, React сбрасывал Base UI menu. Временные browser harness имеют эти ограничения; успешный финальный browser report не создавался и не заявляется.
Локально components/data-grids/wireguard-data-grid.tsx адаптирован по уже принятому GRE образцу: стабильный WireguardActionsCell и типизированный context передают свежие onExport/onAddPeer/onToggle/onDelete/toggleBusy. Данные строки остаются текущими; composition, styles, row key и installed ReUI APIs сохранены. Tests/e2e/wireguard-menu-refresh.spec.ts воспроизвёл исчезнувшее меню на прежнем коде; после исправления меню переживает pending refresh, показывает новое enabled state и вызывает PATCH с актуальным disabled=false. Вместе с wireguard-tables.spec.ts —6/6 passed. ESLint и scoped TypeScript passed. Первый TypeScript запуск совпал с генерацией .next/dev/types и получил временные syntax errors; повтор после остановки Next прошёл. ReUI checklist проверен, общие primitives не менялись.
Первая пара очищена observer, выбранный baseline полностью совпал. Во второй попытке [observer получил401](ux-ui/acceptance/wg-ui-second-observer-error-2026-10-08.json) на завершающем native чтении до cleanup; причина не установлена, пароли не менялись. Повторное чтение через приложение успешно. [Штатный API cleanup](ux-ui/acceptance/wg-ui-second-api-cleanup-2026-10-08.json) проверил точные name/ownership comment и удалил оба own интерфейса DELETE200/200. [Независимая native проверка](ux-ui/acceptance/wg-ui-final-native-cleanup-2026-10-08.json) подтвердила отсутствие own WG/peers/IP/routes на обоих CHR, total IPv4 addresses1/2 и routes4/5; WG interfaces/peers0. Второй baseline был только в памяти и потерян при выходе observer: точное равенство его baseline не заявляется. [DB controls](ux-ui/acceptance/wg-ui-db-controls-2026-10-08.json) servers2/speedHistory9/retention14/migrations9 совпали. Эфемерные контейнеры завершены, остались три основные службы, backend healthy. Audit revisions намеренно сохранены.
Runtime backend/frontend3722fad, локальное меню ещё не развёрнуто. Следующий12.5.62 — frontend Docker deploy и полный UI create interface/peer→disable/enable→повторный handshake/Ping→delete на новой реальной паре, без повторных открытий меню. Перед повтором observer должен сохранить приватный baseline на сервере и продолжать независимую cleanup каждого устройства при ошибке финального state read; запуск browser только после подтверждения готовности нового observer. Переключение, экспорт/import, throughput/RBAC и прочие внешние ограничения остаются открытыми. Пользовательское правило настоящих VPN объектов сохраняется. Локальный коммит без push.
## 12.5.62 — развёртывание стабильного меню и полный WireGuard UI lifecycle (2026-10-08)
[Развёртывание](ux-ui/acceptance/deployed-6a46fb1-2026-10-08.json): frontend6a46fb1e40291024202455460dfc233f05e9e5d5/version1.0.0-test.6a46fb1, backend3722fad не перезапускался и healthy. Git archive SHA2560c25ec8215b25446d2a9ad1555244af94afff32194d2a0768ee727b1ca810db8 совпал после передачи. Main-совместимый staging обновлён единственным изменённым production input — WireGuard data grid; package-lock и Dockerfile совпали. Docker build exit0, Next full TypeScript passed. Изменена только MMAPP_IMAGE_TAG, compose validation прошла, предыдущий frontend3722fad образ сохранён. Push не выполнялся.
[Production UI](ux-ui/acceptance/browser-wg-ui-lifecycle-6a46fb1-2026-10-08.json): новый fixture mm-acceptance-wg-ui-1791473944233, оба CHR, ПК/320px, HTTP mocks отсутствуют. Интерфейсы/IP созданы формами UI: POST201/201; peer формы дали201/201. Native проверка подтвердила поля, автоматическую генерацию ключей и соответствие публичного ключа другого конца (ключи только в памяти). Отключение/включение каждого устройства через меню дало PATCH200×4; disabled совпал с RouterOS, peer и IP сохранились. UI DELETE200/200 полностью удалили interfaces/peers/IP; native отсутствие остатков проверено до finish/fallback. Каждое меню открывалось один раз, menuReopens0. JS/API errors0. Это завершает незаконченный сценарий61 на исправленном production frontend.
[Native observer](ux-ui/acceptance/wg-ui-native-6a46fb1-2026-10-08.json): два раунда handshake/Ping — до и после переключения, каждый3/3 на обоих CHR,0%loss,≈55ms. Существующая конфигурация/коллизии UDP51879 и198.18.255.240/30 проверены до UI создания. Observer сохранил приватный baseline на сервере с0600, повторное чтение401 ограничено тремя попытками и отражается в readRetries; ошибка финального state read теперь перехватывается перед независимой cleanup каждого устройства. В этом проходе retries0/final state errors0; failure ветки не инжектировались. Browser запускался только после READY и сверял name fixture с зафиксированным новым observer.
Итоговый observer exit0, afterBrowser пуст на обеих сторонах; selected WG/peers/IP/routes/IPv4 Firewall baseline совпал. Fallback удаления не понадобился; эфемерный контейнер удалён, остались три основные Compose-службы. DB controls до/после servers2/speedHistory9/retention14/migrations9 совпали, audit revisions намеренно сохранены. Приватный baseline с возможными ключами чужой конфигурации не скачивался и не коммитился. [Smoke](ux-ui/acceptance/deploy-browser-6a46fb1-2026-10-08.json): dashboard/servers/uptime/settings/filters/alerts200,320px fit, JS/API errors0.
[Мобильная форма создания](ux-ui/screens/wg-ui-create-server2-6a46fb1-320-2026-10-08.png) просмотрена, без ключей. Выявлена отдельная UX-недоработка: WireGuard create/peer/import используют обычный w-full, который не переопределяет data-side width общего Sheet; мобильная панель фактически240px при320px, footer сжат. Следующий12.5.63 — точные responsive width overrides по существующему GRE образцу, проверка полной ширины/кнопок в обеих темах и профильные UI проверки. Export/import, throughput, IPv6, внешние failures/RBAC/multi-instance, Telegram/Portal и остальные интеграционные ограничения остаются открытыми. Пользовательское правило настоящих VPN объектов сохраняется. Локальный коммит без push.
## 12.5.63 — полная ширина мобильных WireGuard Sheets (2026-10-08)
В components/wireguard/wg-create-sheet.tsx, wg-peer-sheet.tsx и wg-import-sheet.tsx заменены только width utilities на data-[side=right]:w-full и data-[side=right]:sm:max-w-md/lg. Это существующий GRE образец: одинаковые data-side modifiers корректно переопределяют default ширину установленного Sheet. Создание/пир наsm имеют448px, импорт512px; доsm панели занимают полную ширину экрана. Содержимое форм, API, footer composition и общие primitives не менялись.
[Светлая тема](ux-ui/acceptance/wg-sheets-layout-light-2026-10-08.json), [тёмная тема](ux-ui/acceptance/wg-sheets-layout-dark-2026-10-08.json): временный локальный Playwright visual harness, три панели ×320/640/1280px × две темы —18 комбинаций passed. Actual bounding width равна320/448/512px; все footer buttons находятся внутри панели, scrollWidth не превышает clientWidth, page overflow отсутствует. Tab идёт по ожидаемым полям, Escape закрывает панель. HTTP API подменён, реальные RouterOS операции в этой проверке не выполнялись.
Мобильные скриншоты: [создание dark](ux-ui/screens/wg-create-dark-full-width-320-2026-10-08.png), [создание light](ux-ui/screens/wg-create-light-full-width-320-2026-10-08.png), [пир dark](ux-ui/screens/wg-peer-dark-full-width-320-2026-10-08.png), [пир light](ux-ui/screens/wg-peer-light-full-width-320-2026-10-08.png), [импорт light](ux-ui/screens/wg-import-light-full-width-320-2026-10-08.png), [импорт dark](ux-ui/screens/wg-import-dark-full-width-320-2026-10-08.png). Create dark/peer dark/import light визуально просмотрены: текст действий читается полностью, IP/endpoint имеют достаточную ширину; ключи в снимках не заполнялись.
Profile wireguard-links.spec.ts --grep импорт/создание сохраняет форму —5/5 passed: interface,interface DTO,peer, импорт без подтверждённого результата и pending/retry. Сохранение ввода, API ошибки/неподтверждённые ответы и ожидание результата сохранились. Scoped TypeScript выполнен после остановки Next, ESLint трёх изменённых компонентов и ReUI checklist passed. Полная регрессия не повторялась для трёх responsive class overrides.
Изменение локальное: удалённый runtime backend3722fad/frontend6a46fb1 healthy остаётся прежним. Следующий12.5.64 — frontend production Docker deploy и live мобильные create/peer/import панели на новой собственной WG паре; real UI lifecycle/связность и очистка, baseline. Просмотр импортной формы не будет заявляться как проверенный настоящий import. Import/export, throughput/IPv6/внешние failures/RBAC/multi-instance/Telegram/Portal и другие внешние ограничения открыты. Правило пользователя создавать настоящие VPN объекты сохраняется. Локальный коммит без push.
## 12.5.64 — развёртывание и live приёмка мобильных WireGuard панелей (2026-10-08)
[Развёртывание](ux-ui/acceptance/deployed-bf43263-2026-10-08.json): frontendbf43263e43ae375651237e019fe1aae55e848308/version1.0.0-test.bf43263, backend3722fad healthy и не перезапускался. Чистый Git archive SHA256c42edf2983262b62bcc427f7e2922f1c6bf56754abe3b583be73fd71712bd074 совпал после передачи. Main-совместимый staging обновлён только тремя изменёнными WireGuard Sheets; lockfile/Dockerfile совпали. Docker build exit0, full Next TypeScript passed. Изменена только MMAPP_IMAGE_TAG, compose validation прошла, предыдущий frontend6a46fb1 образ оставлен для rollback. Push не выполнялся.
[Production UI и формы](ux-ui/acceptance/browser-wg-ui-mobile-bf43263-2026-10-08.json): собственная новая пара mm-acceptance-wg-ui-1791475047653, оба CHR × две темы × три панели(create/peer/import) ×1280/320px —24 live сочетания без HTTP mocks. Ширина320px на телефоне, create/peer448px и import512px наПК, footer buttons внутри панели и без обрезания, page overflow отсутствует, Escape закрывает каждую форму. Формы просматривались на реально созданной собственной WG паре; в визуальных снимках ключи не вводились. Импортная форма только открывалась и закрывалась: применение/preview импорта не проверены.
Основной UI lifecycle выполнен отдельно от просмотров форм: создание interfaces201/201 и peers201/201 через реальные формы, native поля/key generation/peer association подтверждены; disable/enable каждого CHR PATCH200×4 сохранили peers/IP; Ping3/3 на обоих устройствах до и после переключения. DELETE200/200 удалили interfaces/peers/IP до finish/fallback. MenuReopens0, JS/API errors0. [Native observer](ux-ui/acceptance/wg-ui-native-bf43263-2026-10-08.json): приватный baseline0600 на сервере, два Ping раунда passed, retries0, final state без own объектов, выбранный WG/peers/IP/routes/IPv4 Firewall baseline совпал. Эфемерный контейнер удалён; остались три основные службы. Audit revisions намеренно сохранены, DB controls до/после servers2/speedHistory9/retention14/migrations9 совпали.
СкриншотыCHR2/320px: [create dark](ux-ui/screens/wg-live-create-dark-bf43263-320-2026-10-08.png), [create light](ux-ui/screens/wg-live-create-light-bf43263-320-2026-10-08.png), [peer dark](ux-ui/screens/wg-live-peer-dark-bf43263-320-2026-10-08.png), [peer light](ux-ui/screens/wg-live-peer-light-bf43263-320-2026-10-08.png), [import dark](ux-ui/screens/wg-live-import-dark-bf43263-320-2026-10-08.png), [import light](ux-ui/screens/wg-live-import-light-bf43263-320-2026-10-08.png). Create dark/import light визуально просмотрены: панель и footer занимают доступную ширину, текст действий виден целиком. [Smoke](ux-ui/acceptance/deploy-browser-bf43263-2026-10-08.json): dashboard/servers/uptime/settings/filters/alerts200,320px fit, JS/API errors0.
Следующий12.5.65 — настоящий экспорт WireGuard без private keys на новой собственной паре: RSC/CONF, выбранный interface/peer и независимое сравнение параметров; ключи/конфиги с секретами в публичные отчёты не включать. Настоящий import roundtrip — отдельный блок. Throughput, IPv6, внешние failures/RBAC/multi-instance, Telegram/Portal и другие протоколы/интеграции остаются открытыми. Пользовательское правило настоящих VPN объектов сохраняется. Локальный коммит без push.
## 12.5.65 — экспорт WireGuard без приватных ключей и ошибка client endpoint (2026-10-08)
[Реальный API export/native](ux-ui/acceptance/wg-export-native-2026-10-08.json): новая собственная пара mm-acceptance-wg-1791475605238 на двух CHR, свободные UDP51879/198.18.255.240/30. До export подтверждены API creation/native peer key association/handshake/Ping. Для каждого устройства POST /api/wireguard/export запрошены rsc/conf/peer-conf с includePrivateKey:false и явным собственным peerId —6 ответов200. Содержимое разобрано и сверено в памяти, реальные native private keys и активные private-key/PrivateKey assignments не обнаружены. Конфиги, публичные/приватные ключи и содержимое export в отчёты/файлы не записывались.
RSC/CONF совпали с native address/listenPort/MTU и выбранным peer(public-key association,allowed address,endpoint,keepalive). Это конфигурационные снимки без приватного ключа, не заявленные готовые импортируемые туннели. Peer-conf подтвердил выбранный interface public key и peer selection, однако клиентская конфигурация не принята: endpoint равен адресу удалённого пира, а не экспортирующего устройства, client Address отсутствует без client metadata. В fixture A→B клиентский шаблон дляB использует keyA, но endpointB — разные стороны соединения. В [официальной документации](https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard) client-endpoint обозначает адрес/порт WireGuard устройства, к которому подключается клиент; клиентские metadata нужно отличать от серверного peer endpoint/allowed-address.
Кодовая причина подтверждена чтением backend WireGuard export route и frontend wg-export-sheet.tsx: fallback peer.clientEndpoint || peer.endpoint. API и локальный preview требуют согласованного исправления; отсутствие client Address/явных client маршрутов нельзя скрывать готовым конфигом. Следующий12.5.66 — корректный client endpoint/defaults, явные поля/состояние шаблона, сохранение client metadata overrides, профильная регрессия. Точное правило client routes/address определить из имеющихся metadata; не выводить клиентские маршруты автоматически из server allowed-address.
UI live export не запускался: его текущий handler запрашивает includePrivateKey:true дляRSC/CONF. Этот блок доказывает API false redaction и выбранные параметры, не безопасность всех UI/export режимов. Native/API snapshot GET, plaintext memory сравнения и отсутствие чувствительных полей в публичном JSON проверены. Product source не менялся, общая регрессия не запускалась для внешней read-only проверки.
Финальный fixture cleanup exit0, selected WG/peers/IP/routes/IPv4 Firewall baseline совпал. Own peers/IP явно удалялись harness перед интерфейсом; полное обычное UI удаление уже отдельно подтверждено в60/62/64. Эфемерный контейнер удалён, остались три основные службы, backend healthy. [DB controls](ux-ui/acceptance/wg-export-db-controls-2026-10-08.json) до/после servers2/speedHistory9/retention14/migrations9 совпали, audit revisions намеренно сохранены. Runtime backend3722fad/frontendbf43263 не менялся. Настоящий import roundtrip, export private-key modes/UI download, throughput/IPv6/RBAC/внешние failures/multi-instance/Telegram/Portal и остальные протоколы/интеграции остаются открытыми. Пользовательское правило настоящих VPN объектов сохраняется. Локальный коммит без push.
## 12.5.66 — правильный client endpoint и явный шаблон Peer .conf (2026-10-08)
Ошибка65 исправлена локально в backend и preview. Общий resolveWgClientEndpoint в packages/contracts/src/wireguard.ts приоритетно использует явный client-endpoint, добавляет listenPort для hostname/IPv4 без порта и brackets для IPv6; иначе берёт host/listenPort экспортирующего устройства. Неизвестный host/неподходящий формат оставляют Endpoint placeholder. Backend export route больше не использует peer.endpoint; frontend WgExportSheet получает host выбранного устройства из текущего каталога серверов и использует тот же resolver.
Server allowed-address не обозначает клиентские маршруты: API/preview больше не передают его в Peer .conf. Оба codec generatePeerClientConf сохраняют явно переданные client параметры, но без client Address/AllowedIPs/Endpoint выводят комментарии-подсказки вместо активных выдуманных значений; default0.0.0.0/0 не создаётся. PrivateKey клиента остаётся placeholder. Существующие client-address/client-dns/client-endpoint overrides сохраняются. UI сообщает, что Peer .conf — шаблон: заполнить собственный ключ/адрес/сети и проверить endpoint заNAT. Политика поддерживаемых client routes не расширена новыми RouterOS полями; ready client config без этих данных не обещается.
Схема после исправления: экспорт интерфейсаA для клиентаB → PublicKey интерфейсаA + Endpoint устройстваA:listenPort; Address клиентаB и его AllowedIPs задаются явно. Backend/frontend изменения согласованы через общий contracts helper, Zod wire format и HTTP response shape не менялись. Общие ReUI primitives не менялись; beforeCode — существующий slot CodeExportSheet.
Проверки lib/wg-client-template.test.ts —5/5: endpoint exporting server/явный override/hostname/IPv6/неизвестные значения, одинаковые backend/frontend placeholders, отсутствие активного Address/AllowedIPs и default route без явных данных, сохранение явно заданных client параметров. Existing backend wireguard-config.test.ts passed; contracts build, backend TypeScript, scoped frontend TypeScript и ESLint всех изменённых файлов passed. Profile wireguard-links.spec.ts --grep экспорт —4/4: late response isolation/error, неправильный формат, выбор второго peer/ROS ID, его client-address/client-endpoint и отсутствие remote endpoint/server allowed-address в preview. Первый запуск старого теста ожидал ошибочно скопированные peer.allowedIps; fixture и assertions заменены на отличающиеся client metadata, защита выбора второго пира сохранена. ReUI checklist checked.
Исправление локальное: runtime backend3722fad/frontendbf43263 не менялся. Следующий12.5.67 — production Docker build/deploy backend и frontend с обновлённым contracts source, новая собственная WG пара, native/API export false redaction и правильный endpoint/шаблон, browser preview соответствие, cleanup/baseline. Поддержка client-allowed-address, настоящий client import/connectivity, import roundtrip/private-key modes, throughput/IPv6/RBAC/внешние failures/multi-instance/Telegram/Portal и другие протоколы/интеграции остаются открытыми. Пользовательское правило настоящих VPN объектов сохраняется. Локальный коммит без push.
## 12.5.67 — Docker deploy и реальный экспорт клиентского шаблона WireGuard (2026-10-09)
Обе production Docker сборки c16fc0c завершились успешно. Межслойный unit test перенесён из lib в tests/unit/wg-client-template.test.ts отдельным локальным коммитом c16fc0c: frontend Docker context не содержит backend source. Предварительный frontend staging c82e8fa не включал этот новый тест и не используется как доказательство чистой сборки исходного c82e8fa. Окончательные staging lib/backend src/contracts совпали с архивом c16fc0c; финальные образы обеих частей имеют OCI revision c16fc0c5b53ba8fcb6690ef6f0a695f59875f171. Network-none assertion backend образа проверил общий resolver и отсутствие активных клиентских Address/AllowedIPs без явных данных.
Перед обновлением сохранён приватный PG dump pre-c16fc0c.dump,2314923bytes,mode0600; pg_restore --list passed. Backend/frontend обновлены до1.0.0-test.c16fc0c, backend healthy, frontend /wireguard HTTP200. Образы: backend sha256:fb9f9279df07481d960f5799338e15a0fc9162a8baca3be7789a89f28a5f56dc, frontend sha256:bc70ee3203b4fd3f269ab6554493f0fb1ec2e60ef515ced2dcd6c6c7428064bc. Резервная .env хранится только на сервере. SSH161.104.46.222 и RouterOS REST194.226.121.150/104.165.244.7 доступны с прежними учётными данными; пароли не изменялись.
Создана собственная временная WG пара с адресами198.18.255.241/30 и198.18.255.242/30,port51879,MTU1420,уникальными name/comment. Native key generation/peer association проверены в памяти, handshake и Ping3/3 в обе стороны passed. Шесть настоящих API export запросов (rsc/conf/peer-conf на обоих устройствах) вернули200 с includePrivateKey=false. RSC/CONF параметры совпали с native; ключи и конфигурации не сохранялись. Peer .conf содержит PublicKey экспортирующего интерфейса и Endpoint экспортирующего устройства:51879; client Address/AllowedIPs остаются comment placeholders, активного default route нет. Это шаблон, готовность к импорту клиента не заявлена.
[Native/API evidence](ux-ui/acceptance/wg-export-native-2026-10-09.json), [browser evidence](ux-ui/acceptance/browser-wg-peer-export-c16fc0c-2026-10-09.json), [deploy/DB controls](ux-ui/acceptance/wg-export-deploy-controls-2026-10-09.json). Четыре настоящих browser сценария без HTTP mocks: оба CHR ×1280/320px. Local preview и live Peer export совпали по server endpoint/client placeholders; POST включает выбранный ROS peer ID и includePrivateKey=false. Нет page errors/API errors/page overflow. Export содержимое и ключи не попали в отчёты/скриншоты; UI download не выполнялся.
Fixture завершён exit0 и удалён. Проверенные WG interfaces/peers/IP/routes/IPv4 filter/nat/mangle совпали с baseline на обоих CHR. Очистка только собственных объектов; audit revisions намеренно сохранены. DB controls до/после совпали:servers2,speedHistory9,retentionDays14,migrations9. Дополнительно сохранён ранее полученный screenshot создания на CHR2 в12.5.64 с исходной датой2026-10-08. Product code в этом блоке не менялся после уже проверенного c16fc0c; общая регрессия не повторялась.
Следующий12.5.68 — import roundtrip собственного конфигурационного файла с независимой проверкой параметров и очисткой. Client-allowed-address/готовый client import, private-key export modes/UI download,throughput/IPv6/RBAC/внешние failures/multi-instance/Telegram/Portal и остальные протоколы/интеграции остаются открытыми. Локальный коммит без push.
## 12.5.68 — реальный .rsc roundtrip WireGuard через UI (2026-10-09)
Runtime backend/frontend c16fc0c не менялся. На обоих CHR создана собственная временная WG пара с уникальными name/comment,port51879,MTU1420 и198.18.255.241/30↔198.18.255.242/30. Исходный handshake/Ping3/3 подтверждены. POST export rsc с includePrivateKey=true получен только в памяти; исходные native keys и содержимое конфигураций не записывались в файлы, screenshots, traces или Git. Это собственные ключи тестовой пары, доступы серверов не менялись.
На обоих устройствах POST import dryRun=true вернул200; native интерфейс/пир/IP остались прежними. Затем обычный API DELETE удалил собственный исходный интерфейс и связанные объекты без остатков. Реальный UI импорт восстановил RSC на CHR1 при1280px и CHR2 при320px без HTTP mocks: server context изURL сохранился, локальный preview распознал собственное имя и одного пира, POST import dryRun=false вернул200 с applied.interfaceName и peersCreated=1, Sheet закрылся после подтверждения, интерфейс появился в таблице. Page errors/API errors/горизонтального page overflow нет.
Native проверка после UI восстановила name/comment,listen-port,MTU,один IPv4 address,одного peer,allowed-address,configured endpoint/port,keepalive и peer comment. Публичные ключи интерфейсов/пиров совпали с исходными. На CHR2 текстовая private-key запись после импорта отличается; нормализованные32байтные Curve25519 scalar совпали, а public identity сохранилась. Приёмка сравнивает эквивалентность scalar и public key, не обещает byte-for-byte неизменность raw encoding. Правило clamping проверено по [официальному исходнику WireGuard](https://git.zx2c4.com/wireguard-tools/tree/src/curve25519.h): изменения затрагивают предусмотренные биты. После восстановления настоящий handshake и Ping3/3 в обе стороны passed.
[Final native report](ux-ui/acceptance/wg-import-rsc-native-2026-10-09.json), [browser report](ux-ui/acceptance/browser-wg-import-rsc-c16fc0c-2026-10-09.json), [предыдущая диагностика raw-key](ux-ui/acceptance/wg-import-rsc-raw-key-check-2026-10-09.json), [DB controls](ux-ui/acceptance/wg-import-db-controls-2026-10-09.json). Первый browser запуск не завершил import; следующая native проверка отклонила raw private-key equality наCHR2. Каждая попытка очищена с совпавшим baseline; диагностическая проверка не объявлена успешной. В окончательном запуске поэлементные native checks passed на обоих устройствах и fixture exit0. Readiness ожидание наблюдателя добавлено в тестовый harness, данные конфигов не выводились при ошибках.
Own interfaces/peers/IP/connected routes удалены; WG/peers/IP/routes/IPv4 filter/nat/mangle совпали с исходным baseline на обоих CHR. Остались три основные службы, backend healthy. Business DB controls совпадают с контрольной точкой67:servers2,speedHistory9,retentionDays14,migrations9; audit revisions намеренно сохранены. Публичные JSON проверены на отсутствие ключей/конфигураций/паролей. Общие ReUI компоненты и product source не менялись; общая регрессия не повторялась для внешней приёмки.
Граница результата: правильный RSC собственного туннеля, preview и успешное применение с независимой связностью. Импорт .conf не принят: exporter не сохраняет имя/комментарии, parser использует wg0 по умолчанию; incomplete Peer .conf template требует отдельной проверки до применения. Partial failure/rollback, повторный import/коллизии, private-key UI download,IPv6/throughput/RBAC/внешние failures/multi-instance/Telegram/Portal и остальные протоколы/интеграции остаются открытыми. Следующий12.5.69 — preflight/ошибки .conf и затем безопасный собственный roundtrip. Локальный коммит без push.
## 12.5.69 — preflight импорта WireGuard без выдуманных маршрутов (2026-10-09)
Обнаружено локально: parse/apply могли принять клиентский шаблон без PrivateKey и подставить0.0.0.0/0 вместо отсутствующих allowed-address. Добавлен backend/src/services/wireguard-import.ts; route использует его до dry-run, поиска сервера и любых RouterOS mutations. .conf должен содержать ровно одну Interface секцию и PrivateKey; каждый объявленный Peer должен иметь PublicKey и явные корректные AllowedIPs. Проверяются32байтные base64 ключи, IPv4/IPv6 CIDR, порты, положительный MTU и неотрицательный keepalive. Неподдерживаемые несколько Address и PresharedKey отклоняются явно вместо потери данных. Ошибки ключей не выводят их значения.
Backend/frontend RSC parsers больше не подставляют default route и требуют interface command; applyParsedConfig использует только проверенные явные сети. Явно заданный0.0.0.0/0 остаётся допустимым. Числа сохраняются для проверки вместо parseInt/undefined defaults, включая0 иNaN. Перед обычным apply route читает список интерфейсов и возвращает409 при занятом имени; это предварительная проверка, не блокировка конкурентных запросов. Dry-run проверяет формат, но не обещает доступность сервера или отсутствие конфликтов на момент применения.
В существующем WgImportSheet добавлено короткое пояснение: .conf безName использует wg0; ключ/сети надо заполнить, совпадение имени остановит import. Структура Sheet/base-nova, формы, aria labels/status/alert и управление busy не менялись. Локальный preview остаётся разбором формата; обязательная preflight проверка выполняется backend. Новых API полей/зависимостей нет. Полный протокол .conf или поддержку PSK этот блок не добавляет.
Проверки: wireguard-import unit22/22 (готовый conf и explicit default route, template, Interface/Peer/key errors, CIDR, отсутствие маршрутов, несколькоAddress/PSK, числовые ошибки и RSC); настоящий Fastify inject4 invalid apply/dryRun случая →400, PUT mutations0. Backend test:wireguard теперь включает новые service/route tests; исходный codec passed. Client-template cross-layer5/5 passed. Browser3/3: доступ/неподтверждённый receipt, ожидание/повтор,400 incomplete conf с сохранением текста и выбранного сервера2. Последний test не попал в первый grep импорт; отдельно запущен и прошёл. Backend/scoped frontend TypeScript, ESLint и diff check passed. ReUI checklist checked; installed primitives не менялись.
Исправление локальное, стенд по-прежнему c16fc0c. Реальные preflight400/409, отсутствие native изменений при отказе, production build и новый .conf roundtrip ещё не приняты. Проверка коллизии409 добавлена в code, отдельно не доказана RouterOS fixture в этом блоке. Следующий12.5.70 — собрать/развернуть, проверить отказы и собственную пару на обоих CHR, native параметры/идентичность/связность, затем cleanup/baseline. Конкуренция, повторный import/partial failure/rollback, неизвестные/повторные поля .conf и остальные внешние ограничения остаются открытыми. Пароли и RouterOS настройки в этом блоке не менялись. Локальный коммит без push.
## 12.5.70 — deploy preflight и собственный .conf roundtrip WireGuard (2026-10-09)
Production Docker backend/frontend479f2ad успешно собраны и развёрнуты. Зафиксированный source commit479f2adc78b162d7694d9897d201704b51082968 передан Git archive, SHA25661e1dfeb413d80ee3b463f14abf539739203f31b886a1e248fce869fa4e9aba1. Backend src и frontend lib/components/app/contracts в staging совпали с source. OCI revision labels479f2ad,version1.0.0-test.479f2ad; backend image inspect IDsha256:48f85bf9863fcec8f3a1df39e2e9e06835b7a7aaf1c59a5e73f00e0181ab3eff7,frontend sha256:346c0df48cc49314045f54e3e6e6efe826524e279bb3652a515c2d37c7295678. Новый backend-образ без сети отклонил неполный conf/peers-only RSC; backend healthy, frontend HTTP200.
Перед обновлением сохранён private PG dump pre-479f2ad.dump,2343134bytes,mode0600; pg_restore --list passed. Предыдущая .env сохранена только на сервере, прежние c16fc0c images доступны для отката. SSH161.104.46.222 и RouterOS REST обоих CHR доступны с прежними доступами. Пароли устройств не менялись.
На каждом CHR настоящий API отклонил неполный conf шаблон с400 для dryRun=false иtrue: всего4 запроса, выбранные WG/peers/IP/routes/IPv4 Firewall ресурсы native не изменились. Затем создана собственная WG пара с уникальным name/comment,51879/1420 и198.18.255.241/30↔198.18.255.242/30; native handshake/Ping3/3 подтверждены. Private .conf exports получены только в памяти; в каждый добавлен явный Name для приложения. Валидный dry-run200 не изменил интерфейс/пир/IP, попытка применить конфиг поверх занятого собственного имени вернула409 на обоих CHR без native изменений. Остальные отрицательные варианты69 проверены локально, не объявлены всеми выполненными на RouterOS в70.
Обычный DELETE удалил исходную пару с peers/IP. UI восстановил conf наCHR1 при1280px иCHR2 при320px без HTTP mocks. Перед успешным import каждому серверу отправлен неполный шаблон → ожидаемый400; Sheet остался открыт, textarea и server selection сохранены, на выбранном устройстве не появились native объекты. Затем local preview показал CONF/явное имя/одного пира, apply200 подтвердил applied.interfaceName/peersCreated=1, Sheet закрылся и объект появился в таблице. В этих browser сценариях2 ожидаемых400 и0 неожиданных API/page errors, page overflow нет.
Native checks подтверждают name,ключевую идентичность,listen-port,MTU,адрес,peer public identity,allowed-address,configured endpoint/port/keepalive. Как в68, raw private encoding наCHR2 нормализован при импорте: Curve25519 scalar equivalent и public key unchanged; raw byte equality не требуется. Настоящий handshake иPing3/3 восстановленной пары прошли в обе стороны. Conf не сохраняет interface/peer comments и peer names; Name здесь расширение parser приложения, не стандартная директива wg-quick. Поэтому результат — network/key roundtrip с явно заданным именем, не побайтовое восстановление исходной RouterOS конфигурации. Для metadata-preserving восстановления ранее принят RSC68. Ключи и конфиги не сохранялись в отчёты/файлы/screenshots/traces.
[Native/API](ux-ui/acceptance/wg-import-conf-native-2026-10-09.json), [browser](ux-ui/acceptance/browser-wg-import-conf-479f2ad-2026-10-09.json), [smoke6 страниц](ux-ui/acceptance/deploy-browser-479f2ad-2026-10-09.json), [deploy/DB controls](ux-ui/acceptance/wg-import-conf-deploy-controls-2026-10-09.json). Первый browser run остановлен ошибочной проверкой harness: после importCHR1 она ожидала отсутствие объектов на обоих CHR перед отказомCHR2. Ошибка исправлена на проверку выбранного устройства; product source не менялся. [Прерванная попытка](ux-ui/acceptance/wg-import-conf-browser-check-aborted-2026-10-09.json) не объявлена принятой; её cleanup/baseline также passed. Финальный fixture exit0.
Все собственные объекты удалены; выбранные WG/peers/IP/routes/IPv4 filter/nat/mangle совпали с baseline на обоих CHR. Для imported conf без comment ownership подтверждалась уникальным fixture name и ожидаемой native public identity, используемой только в памяти. Остались3 основные службы, backend healthy. DB controls до/после:servers2,speedHistory9,retentionDays14,migrations9. Audit revisions намеренно сохранены. Production smoke /dashboard,/servers,/uptime?tab=speed,/settings,/filters,/wireguard →HTTP200,320px fits,0 page/API errors. Публичные JSON проверены на отсутствие ключей/конфигов/паролей. Дополнительная общая локальная регрессия не повторялась после уже проверенного69; production build/typecheck и реальные scoped сценарии выполнены.
Следующий12.5.71 — partial apply failures/компенсация и повторный import. Concurrent collision races, rollback/interrupted mutation, неизвестные/повторные поляconf,PSK/multi-address поддержка, ready Peer client template import,private-key UI download,IPv6/throughput/RBAC/multi-instance/Telegram/Portal и остальные внешние протоколы/интеграции остаются открытыми. Локальный коммит без push.
## 12.5.71 — подтверждённая очистка частичного импорта WireGuard (2026-10-09)
Локально обнаружено по code: прежний последовательный apply оставлял интерфейс/IP, если поздний peer PUT отклонялся. Добавлен backend/src/services/wireguard-import-apply.ts; route использует сервис вместо встроенного applyParsedConfig. До mutations читаются interface/IP/peer baseline; занятое имя возвращает409. Каждый успешный create должен дать один строковый ROS .id, отсутствовавший в baseline; identity записывается в памяти. Native GET после всех PUT подтверждает созданные ID и name/interface/public-key/address association перед success receipt. Полное сравнение всех настроек/связности остаётся внешней проверкой, не подменяется этим identity check.
При подтверждённом RouterOS rejection (явные400/401/403/404/405/409/422) сервис читает текущее состояние, проверяет принадлежность всех receipt-owned объектов и отсутствие чужих связанных объектов. Только затем удаляет собственные peers →IP →interface в обратном порядке и перечитывает ресурсы. Подтверждённое отсутствие объектов →502,state rolled-back с понятным сообщением и возможностью исправить/повторить. Удаление существующих baseline IDs, чужих child rows и cleanup только по имени запрещены. Это компенсация текущего запроса, не RouterOS транзакция.
Потеря ответа после commit,HTTP408/500,неполный create receipt или несовпадение native identity →needs-review; автоматическое удаление не выполняется при неподтверждённом create outcome. Ошибка cleanup/read/изменённая identity/чужой concurrent child →needs-review, успешный rollback не обещается. Если DELETE оборвался после части удалений, состояние надо проверить вручную. Ответы не пересказывают native body с потенциальными ключами. Между ownership GET и DELETE нет распределённой блокировки; конкурентные изменения и потеря процесса требуют отдельной приёмки.
Route отдельно обрабатывает audit revision failure после успешного apply:502,state applied и сообщение, что конфигурация уже применена, но ревизия не сохранена; сеть не объявляется неприменённой и автоматический rollback уже подтверждённых изменений не запускается. Этот backend audit branch реализован, но отказ реальной БД после apply в71 не воспроизведён. Success HTTP shape прежний; error state добавлен как уточнение, текущий UI показывает message и сохраняет форму.
Проверки apply unit16/16: native receipt успех, baseline read failure0writes, несовпавшая native identity, повтор после успеха409 без mutations, отказ второго peer/адреса с восстановлением baseline, успешный повтор после rollback, lost reply после iface/IP/peer commit,HTTP408/500,missing/foreign receipt,concurrent чужой peer,изменённая identity,отказ/неподтверждённый DELETE. Исходные preflight22/22 и codec/HTTP4 invalid cases passed; новые apply tests включены в backend test:wireguard. Browser6/6: прежние import сценарии и три новых502 состояния rolled-back/needs-review/applied сохраняют текст/server/error; автоматического повторного POST нет; ручной retry после rolled-back принят успешным receipt. HTTP ответы browser подменены, это не real RouterOS cleanup. Backend и scoped frontend TypeScript, ESLint и diff check passed. UI primitives/ReUI composition не менялись.
Исправление локальное: runtime backend/frontend479f2ad из70 не обновлялся; production frontend source не менялся. Следующий12.5.72 — production build/deploy только backend, реальная проверка ROS PUT receipts, поздний native rejection на собственных объектах,cleanup/baseline и исправленный повтор с связностью. Прерванный HTTP/процесс,подлинный audit DB failure,конкуренция/multi-instance,IPv6/throughput/RBAC,PSK/multi-address/unknown-conf поля,интеграции и остальные внешние протоколы остаются открытыми. Пароли/RouterOS конфигурация в этом локальном блоке не менялись. Локальный коммит без push.
## 12.5.72 — реальная компенсация позднего отказа импорта WireGuard (2026-10-09)
Backend e01454b720f92ae8adc1636f7a2092132232dc87 production build/deploy passed; frontend479f2ad оставлен, его container ID до/после совпал. Git archive SHA2566cffbd73c05cf28fded3c80d9c8965a3c22f8f698e33f499fb87f5d21fc2effc; backend src staging совпал с source. Новый image inspect IDsha256:b6d5d7f68a8529ead68d8a676a0def5edfdd6aa9ad485be4b0158c0241ecae46,OCI revision полныйe01454b,version1.0.0-test.e01454b. Module import/state assertion без сети passed, backend healthy,/health HTTP200. Private backup pre-e01454b.dump2364848bytes,0600,pg_restore --list passed; предыдущая.env и образы сохранены только на сервере для отката. SSH161.104.46.222 и RouterOS REST обоих CHR доступны с прежними доступами.
Создана собственная WG пара с уникальным name/comment,51879/1420 и198.18.255.241/30↔198.18.255.242/30; исходные native keys/association/handshake/Ping3/3 подтверждены. Private conf exports с явным Name использованы только в памяти, исходная пара обычным DELETE удалена. Для позднего отказа к каждому conf добавлен повтор того же Peer. Это настоящий native rejection, не fake HTTP response или transport injection.
Supplemental native service run на каждом CHR использовал новый applyWireguardImport и настоящий MikrotikClient. Adapter только записывал method/path/наличие receipt .id/завершение DELETE и делегировал реальные операции; GET retries наследуют harness, mutations не повторяются. Native trace: iface PUT receipt →IP PUT receipt →первый peer PUT receipt →второй peer HTTP400 →DELETE peer/IP/iface. State rolled-back и полный выбранный baseline restored на обоих CHR. Успешные native HTTP-коды не выдумывались: client возвращает body/void, отчёт отмечает completed и receiptIdPresent; status400 получен из реального MikrotikError. Наличие receipt/native identities на этой RouterOS версии подтверждено.
Отдельно реальный production UI/API наCHR1 при1280px иCHR2 при320px: неполный template400 сохраняет форму/server selection, duplicate-peer conf502,state rolled-back сохраняет введённый конфиг и показывает подтверждённую очистку; native observer не нашёл iface/peer/IP на выбранном устройстве. После исправления textarea повтор200 подтвердил applied name/peersCreated=1, Sheet закрылся, интерфейс появился в таблице. Применённая пара прошла native parameter/public identity/private scalar checks, handshake иPing3/3 в обе стороны. Expected UI errors:2×400 и2×502; unexpected API/page errors0,page overflow0. Comments/peer names не переносятся conf, явный Name — расширение parser приложения; byte-for-byte metadata restore не обещается.
[Native service/API evidence](ux-ui/acceptance/wg-import-compensation-native-2026-10-09.json), [production browser failure/retry](ux-ui/acceptance/browser-wg-import-compensation-e01454b-2026-10-09.json), [deploy/DB controls](ux-ui/acceptance/wg-import-compensation-deploy-controls-2026-10-09.json), [smoke6 страниц](ux-ui/acceptance/deploy-browser-e01454b-backend-2026-10-09.json). Финальный fixture exit0, собственные WG/peers/IP/connected routes удалены; выбранные WG/peers/IP/routes/IPv4 filter/nat/mangle совпали с baseline на обоих CHR. Остались3 основные службы, backend healthy. DB controls до/после servers2,speedHistory9,retentionDays14,migrations9; audit revisions намеренно сохранены. Smoke /dashboard,/servers,/uptime?tab=speed,/settings,/filters,/wireguard →200,320px fits,0 page/API errors. Ключи/конфигурации не включались в отчёты/скриншоты/traces/файлы; public JSON проверены. Product source после71 не менялся, общая локальная регрессия не повторялась; выполнены production build и реальные scoped сценарии.
Граница результата: подтверждённый native validation failure после трёх создающих операций, компенсация и ручной успешный retry в production HTTP/UI. Потерянный ответ/HTTP408/500 после commit,потеря процесса,unconfirmed cleanup,concurrent changes и audit DB failure остаются внешними ограничениями; unit71 их не заменяет. Следующий12.5.73 — изолированный audit failure после настоящего apply и truthful состояние applied с собственной WG парой/cleanup. RBAC/IPv6/throughput/multi-instance/PSK/multi-address/unknown-conf поля и остальные протоколы/интеграции остаются открытыми. Доступы и чужая RouterOS конфигурация не менялись. Локальный коммит без push.
## 12.5.73 — отсутствие audit receipt не означает полный успех импорта (2026-10-09)
При подготовке внешнего fault scenario найдено: captureAndAppendRevision перехватывает capture/persistence errors и возвращает null, а recordWireguard раньше игнорировал return value. Поэтому catch из71 не срабатывал при обычном сбое сохранения и route мог вернуть200. Внешний тест перенесён до исправления обнаруженной причины; реальный DB fault в73 не заявлен принятым.
recordWireguard теперь возвращает результат helper. Новый confirmWireguardImportRevision проверяет null/undefined и exception; созданная или уже существующая неизменённая ревизия считается подтверждением. Импорт после успешного native apply при отсутствующем receipt возвращает502,state applied: «Конфигурация применена, но сохранение ревизии не подтверждено. Обновите данные перед повтором». Формулировка не утверждает отсутствие строки БД: error может случиться после INSERT при prune/read. Подтверждённые изменения RouterOS не откатываются из-за audit error. Другие consumers recordWireguard продолжают игнорировать nullable receipt, их поведение не расширялось этим блоком.
Новый wireguard-import-revision.test.ts4/4: created/unchanged receipt, null/undefined, exception и настоящий captureAndAppendRevision с падающим capture callback. Последний воспроизводит именно контракт swallowing→null, DB запрос не выполняется; это не реальный отказ PostgreSQL. Новые tests включены в backend test:wireguard:42/42 (22 preflight+16 apply+4 revision), codec и Fastify4 invalid cases passed. Backend TypeScript/ESLint passed. Browser applied1/1 с подменённым502/точным новым message сохраняет textarea/server/error и не повторяет POST автоматически; это UI boundary, не native/DB интеграция. Diff check passed. Production UI/ReUI primitives не менялись.
Исправление локальное, runtime backend e01454b/frontend479f2ad не менялся; RouterOS объекты/пароли и DB schema в73 не менялись. Следующий12.5.74 — production build/deploy backend и изолированный реальный audit persistence failure после настоящего apply на собственных WG объектах: подтвердить applied/native/связность, предупреждение HTTP/UI, отсутствие повторной мутации и cleanup/baseline. Нельзя считать73 доказательством сбоев DB/процесса/transport/concurrency/RBAC/IPv6/интеграций; они и прочие внешние ограничения остаются открытыми. Локальный коммит без push.
## 12.5.74 — настоящий PostgreSQL audit отказ после успешного WireGuard apply (2026-10-09)
Backend source8eaf78b68631d774bf18ae049d0e11f90fe098d8 production build/deploy passed; frontend479f2ad иего container сохранены. Archive SHA256a685c56eff695beb8d30eaaf49c6ca03d97011e9a306679e2173d7485df7540a; backend src staging совпал с source. Image inspect IDsha256:2f94d4d52f8c2a23806ac7795af3d2346f9dd3114e2fcda4237b3be3c6513f69,OCI revision8eaf78b,version1.0.0-test.8eaf78b. Network-none revision helper: null false,unchanged receipt true. Backend healthy. Private backup pre-8eaf78b.dump2382377bytes,0600,pg_restore --list passed; previous.env/images сохранены на сервере. SSH и RouterOS REST обоих CHR доступны, пароли не менялись.
Подготовлена собственная WG пара с уникальным name/comment,51879/1420 и198.18.255.241/30↔198.18.255.242/30. Seed handshake/Ping/export private conf только в памяти/explicit Name и обычный DELETE выполнены. Изолированный контейнер из нового backend образа поднял настоящий Fastify HTTP endpoint с production wireguardRoutes на8082 (host127.0.0.1:8020). Scheduler/обычный main backend не запускались в worker. Endpoint ограничен POST import и точным content/serverId собственной fixture.
В PostgreSQL создана уникальная temporary NOLOGIN/NOSUPERUSER роль с USAGE schema иSELECT; write privileges не выдавались. Только worker pool запросы выполнялись через SET ROLE на выделенном соединении с обязательным RESET ROLE/release; queries делегировались настоящему pg driver, ответ SQL не подменялся. Production main pool/его права не менялись. Native RouterOS apply выполнился, snapshot успешно дошёл до БД, INSERT config_revisions получил настоящий SQLSTATE42501 на обоих устройствах. Counter реальных denied revision writes2; captureAndAppendRevision вернулnull, новый helper не объявил audit success.
Production frontend наCHR1 при1280px/CHR2 при320px направил POST на реальный изолированный HTTP endpoint через Playwright route.continue URL override; response fulfillment/HTTP fixtures/SQL/RouterOS mocks не использовались. Это отдельный backend process/HTTP port, не fault основного backend. Оба запроса вернули502,state applied; UI показал «Конфигурация применена, но сохранение ревизии не подтверждено», сохранил textarea/server selection, автоматического повторного POST нет. Native observer подтвердил interface/IP/peer после warning. Пара сохранила network parameters/public identity/private scalar и выполнила handshake/Ping3/3 в обе стороны; audit error не откатил рабочую конфигурацию. Keys/configs не сохранялись в отчёты/screenshots/traces/файлы.
[Native/PG evidence](ux-ui/acceptance/wg-import-audit-native-2026-10-09.json), [реальный HTTP/UI](ux-ui/acceptance/browser-wg-audit-8eaf78b-2026-10-09.json), [deploy/DB controls](ux-ui/acceptance/wg-import-audit-deploy-controls-2026-10-09.json), [smoke6 страниц](ux-ui/acceptance/deploy-browser-8eaf78b-backend-2026-10-09.json). Fixture exit0. Fault HTTP listener закрыт, pool восстановлен, DROP OWNED/DROP ROLE применены только к подтверждённо созданной NOLOGIN роли без owned business objects; temporaryAuditRoles0. Все собственные WG/peer/IP/connected routes удалены, selected WG/peers/IP/routes/IPv4 filter/nat/mangle baseline совпал на обоих CHR. Остались3 основные службы, backend healthy; frontend не перезапускался. Business DB controls servers2/speedHistory9/retentionDays14/migrations9 до/после совпали; штатные seed/cleanup audit revisions намеренно сохранены. Smoke /dashboard,/servers,/uptime?tab=speed,/settings,/filters,/wireguard200,320px fits,0 page/API errors. Публичные JSON проверены на отсутствие keys/config/password values.
Граница результата — изолированный реальный permission denial при INSERT после настоящего apply и truthful HTTP/UI. Не проверены физический DB disconnect,ошибка после COMMIT/prune/read,потеря процесса/transport/concurrency/multi-instance/RBAC/IPv6/throughput; warning73 остаётся осторожным и не утверждает отсутствие строки БД. Остаточные WireGuard ограничения открыты. Следующий12.5.75 — перейти к VXLAN: сверить route/model/context, создать только собственные реальные интерфейсы на двух CHR, проверить native/API/связность и cleanup с сохранением baseline. Product source после73 не менялся, общая локальная регрессия не повторялась; production build и scoped реальные сценарии выполнены. Локальный коммит без push.
## 12.5.75 — собственная VXLAN пара и реальный каталог/экспорт (2026-10-09)
Карта возможностей: backend GET /api/vxlan и /api/servers/:id/vxlan читают интерфейсы/статические VTEP; create/delete API отсутствует. UI — каталог, URL server/tunnel context и экспорт interface/VTEP fragment. Реальные fixture create/delete выполнены RouterOS REST напрямую, не объявляются операциями приложения. Схема статических VTEP сверена с [документацией MikroTik](https://help.mikrotik.com/docs/spaces/ROS/pages/100007937/VXLAN). Production source/runtime не менялся: backend8eaf78b/frontend479f2ad.
На194.226.121.150 и104.165.244.7 созданы собственные уникальные VXLAN interface/name/comment сVNI160075,UDP51880,MTU1400,local-address своего CHR,remote VTEP второго CHR иIP198.18.255.245/30↔198.18.255.246/30. Перед созданием проверены name/VNI/port/benchmark subnet collisions и selected native baseline. Existing bridge/ports/firewall/default routes не менялись. Native receipt IDs сохранялись только для собственной очистки. Short ICMP3/3 в обе стороны passed. GET /api/vxlan безfailures совпал по server/id/VNI/dstPort/local-address/remoteVTEP/l2mtu/enabled/up; это real API, не mocks. Interface running дополнен настоящим Ping, не используется как единственное доказательство связности.
[Native/API/Ping/cleanup](ux-ui/acceptance/vxlan-native-2026-10-09.json), [browser4/4](ux-ui/acceptance/browser-vxlan-2026-10-09.json). Browser выбрал точный tunnel id/server черезURL, увидел ровно свою строку, открыл экспорт и подтвердилVNI160075/port51880/статический remote VTEP на обоих CHR при1280/320px; page errors/overflow нет. Экспорт — fragment, его reapply не выполнялся; bridge/FDB/IP/MTU recreation не подтверждена. Первый browser run не завершился, native часть иcleanup exit0; повтор с диагностикой passed4/4. Причина первого сбоя не установлена и не объявлена исправленной product bug. Во всех попытках own объекты удалены.
Финальный fixture exit0, own IP→VTEP→interface удалены по receipt IDs с проверкой собственного comment. VXLAN/VTEP/IP/routes/IPv4 filter/nat/mangle/bridge/bridge-port selected projections совпали с baseline на обоих CHR. Динамические ARP/FDB не входили в baseline projection; полнота их очистки этим блоком не заявлена. Backend healthy,3 основные службы, business DB controls2servers/9speedHistory/14retentionDays/9migrations сохранены. [Контрольные данные](ux-ui/acceptance/vxlan-db-controls-2026-10-09.json). Ключей/паролей в JSON нет. Доступность обоих CHR подтверждена native операциями; тестовый серверSSH работает. Product changes/build не выполнялись, локальная общая регрессия не повторялась для read-only UI приёмки.
По code прямой /servers/:id/vxlan пока получает server без enabled guard; отключённый сервер здесь может опрашиваться, вопреки ранее принятому правилу пользователя. Следующий12.5.76 — исправить этот endpoint и проверить disabled/no native calls. Реальное отключение устройств в75 не выполнялось. VXLAN create/delete UX,bridge/FDB export/reapply,IPv6/throughput/RBAC/частичные сбои и остальные внешние ограничения открыты. Локальный коммит без push.
## 12.5.76 — VXLAN: достоверность, экспорт и полная профильная приёмка (2026-10-09)
По поручению пользователя работа укрупнена по разделам. В одном блоке выполнены code/API/UI, профильные проверки, production Docker build обеих частей, deploy, реальная приёмка и очистка; один локальный коммит в конце, без push.
Прямой GET /api/servers/:id/vxlan теперь возвращает409 для выключенного сервера до обращения к RouterOS. Защита есть также в native reader и агрегаторе, для home-router и exit-node. Неполные/некорректные параметры интерфейса, повторные ID/имена и неизвестные/некорректные статические VTEP считаются ошибкой устройства вместо выдуманных VNI/port/L2MTU/флагов. Сохранение последних успешных данных и частичная ошибка остаются прежними. VTEP сопоставляется с именем или RouterOS ID интерфейса.
Реальный MTU передаётся в модель, виден в таблице и экспортируется; для старого снимка без MTU показывается «—», параметр не придумывается, экспорт просит проверить его отдельно. CodeExportSheet прямо описывает fragment: interface/известный MTU/static VTEP, без IP/bridge/FDB. Стабильная actions cell получает callback через контекст, поэтому открытое меню сохраняется при refresh и экспорт использует последние данные. Frame/base-nova и установленные ReUI primitives сохранены; registry migration не выполнялась.
Проверки: backend mapping/HTTP route/export tests, backend и scoped frontend TypeScript, ESLint изменённых файлов и diff check passed. Профильный browser набор23/23 (VXLAN и два связанных layout cases), context-race4/4. В тесте1000 строк отображаются50 строк; измерено2245 DOM nodes, payload227787 bytes и829ms до ready в данном локальном запуске — это наблюдение, не универсальный performance SLA. Общая регрессия проекта не повторялась.
На161.104.46.222 развёрнуты backend/frontend mmapp-test/*:ux-vxlan76, version1.0.0-test.vxlan76. Сборочный source — git archive базового HEAD6b068ac с явными13 working-file overrides, а не отдельный уже закоммиченный revision. SHA256 архива b69f8eb8b5830e85930aca0974cd83a94940e2e162101b8798208720ccf3e1ae; [manifest](ux-ui/acceptance/vxlan-section-source-manifest-2026-10-09.json) позволяет сверить каждый изменённый файл. Production builds passed; Compose3 services running, backend/PostgreSQL healthy; frontend healthcheck отсутствует, HTTP/browser passed. Backup2441206 bytes/0600, pg_restore --list passed, .env сохранён приватно на сервере, прежние образы доступны для rollback.
Реальная собственная VXLAN пара на194.226.121.150 и104.165.244.7: VNI160075, UDP51880, MTU1400, публичные local/static remote VTEP, IP198.18.255.245/30↔198.18.255.246/30. Native параметры совпали с каталогом приложения; Ping3/3 в обе стороны. [Browser4/4](ux-ui/acceptance/browser-vxlan-section-2026-10-09.json) подтвердил URL выбранного устройства/туннеля, экспорт и отсутствие page overflow на1280/320px. Экспорт каждой стороны заново применён через строго ограниченный native REST adapter к собственным интерфейсам: только interface/VTEP команды, IP добавлены отдельно; MTU1400 и Ping3/3 повторно подтверждены. Это проверка параметров fragment, не запуск произвольного .rsc скрипта в терминале.
Две временные выключенные записи home-router/exit-node указывали на отдельный HTTP probe. Прямые GET вернули409, nativeProbeCalls0; временные записи удалены. [Native protocol](ux-ui/acceptance/vxlan-section-native-2026-10-09.json): cleanup сравнил исходные VXLAN/VTEP/IP/routes/IPv4 firewall/bridge/bridge-port на обоих устройствах, все проверки true. DB controls после: servers2/speedHistory9/retention14/migrations9. Пароли не менялись, SSH и оба CHR доступны. [Smoke шести страниц](ux-ui/acceptance/deploy-browser-vxlan-section-2026-10-09.json): HTTP200, mobile fits, JS errors0/API errors0.
| Референс | Схема применённого решения |
| --- | --- |
| [ReUI Data Grid](https://reui.io/docs/components/base/data-grid?ref=mcp) / [Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Контекст устройства → достоверная таблица/MTU → устойчивое меню |
| [Sheet8](https://reui.io/preview/base/sheet-8?ref=mcp) | Актуальный снимок → границы fragment → код → независимая native проверка |
```mermaid
flowchart LR
A[Устройство] --> B{Включено?}
B -->|Нет| C[409: без опроса]
B -->|Да| D{Снимок достоверен?}
D -->|Нет| E[Ошибка и последние данные]
D -->|Да| F[Таблица с MTU]
F --> G[Экспорт interface и VTEP]
G --> H[Повторное применение и Ping]
```
Границы: app VXLAN API read-only, create/delete выполнены native REST только на собственных объектах. IPv6/bridge/FDB/throughput/RBAC/concurrency и произвольный терминальный .rsc import не приняты; динамический ARP/FDB baseline не сравнивался. Первый запуск Edge в sandbox завершился до страницы; повторный разрешённый запуск прошёл. Этап12.5 целиком не закрыт. Следующий раздел12.5.77 — IPsec; остаточные VXLAN/WireGuard ограничения остаются в протоколе.
## 12.5.77 — основной блок IPsec (2026-10-09)
Подробный объём, протоколы, схема и ограничения: [12.5.77 в журнале](ux-ui-progress.md).
12.5.87 (2026-10-09): OSPF optimizer native/API и4 browser checks passed, собственные объекты очищены, baseline7 коллекций×2 сохранён. Подробности/runtime происхождение — в журнале.
12.5.88 (2026-10-09): recursion/GRE/Ping, apply/restore и4 browser checks passed; native baseline4 коллекций×2, cache/history сохранены. Backend recursive88, frontend optimizer87.
12.5.89 (2026-10-09): терминал/диагностика/RBAC и8 live UI checks passed, baseline7 коллекций×2 сохранён. Production auth не менялся.
12.5.91 (2026-10-09): frontend ospf91; целый CIDR подтверждён4 live cases, baseline7 коллекций×2 сохранён. Backend diagnostics89 неизменён.
## 12.5.95 — полнота Docker contexts и compiled backend (2026-10-10)
[Отчёт сверки](ux-ui/acceptance/deployment-source-audit-2026-10-10.json), local HEAD9d6cd00. Проверены902 unique tracked application/build inputs с учётом Docker COPY. Frontend515 совпавших файлов, backend405; common contracts/lockfile проверены в обоих contexts. Производственные TS/TSX/JS/CSS/public/config/migrations не отстают от текущих файлов. Исключения явно разобраны: frontend package workspaces безbackend; backend stripped root dependencies/scripts; отсутствующий .dockerignore в очищенном frontend context; recursive-routes.test.ts без позднего as const (тест исключён backend tsconfig). Эти исключения не требуют нового deployment.
Локальный contracts/backend production build passed. Дополнительно SHA980 emitted backend/contracts files сверены с реальным запущенным контейнером: missing0; после явной CRLF→LF нормализации different0. При raw byte сравнении10 JS файлов отличались переносами внутри multiline strings; байтовая идентичность не заявлена. Image IDs подтверждены docker inspect: backend97c1cff01efd…/frontendb4bade515234…, labels diagnostics89/ospf91 — названия блока, не Git SHA.
Для frontend подтверждён сохранённый build context/lockfile/config и текущий image ID; compiled frontend не пересобирался и не заявлен independently reproducible. Ранее принятые build/live proofs91 остаются основанием его поведения. Secrets/env не копировались, native writes/fixture/сообщений/deploy0. Повторный frontend build и широкая регрессия при отсутствии source drift не нужны. Следующий96 — remaining speed timezone/контракт времени, затем ограниченный transport disconnect при возможности безопасного окончания native test. Локальный коммит без push; этап12.5 открыт.
## 12.5.96 — speed history: одинаковый instant в трёх часовых поясах (2026-10-10)
[Native/SQL/API](ux-ui/acceptance/speed-timezone-2026-10-10.json), [live browser](ux-ui/acceptance/browser-speed-timezone-2026-10-10.json). Настоящий compiled production speed route/service/MikrotikClient и PG, один accepted TCP transmit3s1→2 с cap10Mbit/s на обоих native tx limits. Только cap добавлен тестовой оснасткой в команду, HTTP/native responses не подменялись. Production API cap не добавлялся; это функциональная проверка времени, неbenchmark. ProbeId отсутствует, существующие snapshots не изменялись.
POST result.createdAt, SQL created_at и production GET истории совпадают до миллисекунды. Instant фиксируется перед after-ping, после ответа bandwidth и3s ожидания; это не время начала bandwidth. Backend UTC; live browser UTC/AsiaNovosibirsk/AmericaLosAngeles×1280/320 =6/6: один instant, соответствующее местное время, корректная смена календарной даты, reload/document fits/pageerror0; UI native POST0. Миллисекунды не показываются в ячейке, но API не теряет их.
Две предварительные попытки завершили native тест, но остановились в fixture: лишнее требование Ping0% при фактических25% и Date.parse(Date) с потерей ms. Исправлены только тестовые условия/getTime; реальные timestamp продукта не менялись. Три коротких capped native команды всего, принятый итоговый Ping сохранён в отчёте; успешные browser/native checks повторно не выполнялись. Все три own history IDs удалены, исходный список истории сохранён; процессов/fixtures не осталось, аккаунты/RouterOS конфигурация не менялись.
ROS-10 принят для текущей версии POST/GET и перечисленных timezone; legacy receipt безcreatedAt сохраняет прежний отдельный fallback. Source/build/deploy0. Следующий97 — реальный обрыв HTTP receipt bandwidth-test через локальный relay, без изменения устройств и с независимым наблюдением короткого native завершения; не заявлять это physical WAN loss или auto cancellation. Квота15% использовано, этап12.5 открыт. Один локальный коммит без push.
## 12.5.97 — реальный обрыв HTTP receipt bandwidth-test (2026-10-10)
[Native/SQL/cleanup](ux-ui/acceptance/speed-disconnect-2026-10-10.json), [live browser](ux-ui/acceptance/browser-speed-disconnect-2026-10-10.json). Собственная disabled speed-проба с явно синтетическим прежним snapshot42/17Mbit/s/Ping15ms/0% для проверки сохранения. Actual compiled speed route/service/MikrotikClient/PG; source client направлен через локальный HTTP relay, destination/account/RouterOS не менялись. Relay передал настоящую TCP transmit3s команду с native cap10Mbit/s и через100ms после отправки закрыл receipt socket. Independent upstream продолжил читать ответ и подтвердил done testing; это реальный HTTP socket disconnect после отправки, не подмена ответа/throw вместо сети.
API502, history error/TXRX/Pingnull, probe error с прежними42/17/15/0; nativeCount1/noauto retry. App не получила доказательство завершения и не записала done, хотя relay независимо видел успешный native конец. UI2/2 на1280/320: error history/reload/document fits/pageerror0, API сохраняет старые snapshots; UI command POST0. Визуальное отображение card metrics отдельно не утверждается этим read-only сценарием.
Свои history/probe exact IDs удалены, исходные списки совпали, только3 compose containers/backend/PG healthy. Один короткий capped native запуск с первой попытки, без RouterOS configuration/account changes/build/deploy. Native команда не отменялась; physical WAN failure/abort/multi-instance locks не приняты. Lab AUTH_REQUIRED=false, rights не проверялись повторно. HTTP ошибка приложения не доказывает failure native команды.
Обнаружено оставшееся UX ограничение: timeout/socket message техническая и не объясняет неопределённость native результата. Следующий98 — единый понятный transport error для HTTP/history, профильные tests и один backend build/live повтор только изменённого message path; затем общая регрессия на согласованном runtime. Этап12.5 открыт. Один локальный коммит без push.
## 12.5.98 — понятный неизвестный результат теста скорости (2026-10-10)
После реального lost receipt97 техническое сообщение заменено единым speedRunErrorMessage для HTTP и сохраняемой истории: «Результат теста скорости неизвестен: ответ устройства не получен. Проверьте его состояние перед повторным запуском». Timeout/socket hang up/ECONNRESET не означают доказанный native failure. Известный отказ авторизации и остальные конкретные ошибки сохраняются; неизвестное сохранение PG остаётся отдельным outcome=unknown/runId. HTTP502/history error означают ошибку получения результата приложением; schema/status/автоматический retry не расширялись.
**Проверки.** Speed-test HTTP validation/persistence/RBAC и дополнительные3 transport cases/известная auth error passed; локальный contracts/backend production build и scoped ESLint passed. Service иroute используют один formatter. [Deployment](ux-ui/acceptance/deployed-speed-message-2026-10-10.json): одна Docker backend сборка из context diagnostics89 +3 working-tree files, package/lockfile неизменны, production tsc/entry/node --check/pg_restore18.6/compose --wait passed. Runtime backend ux-speed98/version1.0.0-test.speed98/image779b0fc010c9…; frontend ux-ospf91 прежний. Label speed98 — блок, не Git SHA. Приватный .env backup сохранён; обновлён только BACKEND_IMAGE_TAG.
[Native/API/PG](ux-ui/acceptance/speed-message-2026-10-10.json) и [browser](ux-ui/acceptance/browser-speed-message-2026-10-10.json): повторён только изменённый receipt path, одна capped10Mbit/s TCP3s команда, реальное закрытие socket после передачи, native independently done, API/history содержат новое сообщение; прежние синтетические42/17/15/0 сохранены, native1/noauto retry. Live1280/3202/2, сообщение видно в probe card, reload/document fits/pageerror0/UI command POST0. Свои disabled probe/history удалены, исходные IDs совпали, только3 compose containers/backend/PG healthy; RouterOS/credentials не менялись.
При согласовании указателей94–97 обнаружено, что массовая замена также затронула исторический абзац77 в плане/протоколе. Восстановлен точный абзац из40f730b, история/дата2026-10-09 сохранены; следующие обновления ограничены текущими указателями. Следующий99 — одна общая backend/main/context регрессия на текущем source, с восстановлением исходных доказательств, затем итоговая сводка. General backend/main runs уже запущены, их результат этим блоком не заявлен. Квота23% использовано; этап12.5 открыт. Один локальный commit без push.
## 12.5.100 — RouterOS: обрыв тела HTTP ответа больше не зависает (2026-10-10)
У ClientRequest и IncomingMessage разные error events. После получения headers частичный ответ не вызывал request error/end; запрос оставался pending даже после500ms timeout. Изолированная проверка воспроизвела6 failures по deadline1200ms для GET/POST/PUT/PATCH/DELETE/raw file reading; полныйsuccess/401 проходил. Добавлен общий watchRosResponseFailure на aborted/error во всех6 paths, очистка timer и существующий settle/AbortSignal cleanup дляPOST. Partial response отклоняется как ECONNRESET, без выдуманного ACK и повторных writes. Две прежние read-only file compatibility стратегии сохранены.
[Протокол](ux-ui/acceptance/routeros-response-transport-2026-10-10.json): после изменения7/7 включая complete success/401, probes.cancel/actual HTTP AbortSignal и byte file parser passed. Тест включён в test:ros-file. Локальный production build, новый test ESLint и Docker build прошли. Исходные2 prefer-const errors mikrotik.ts сохраняются, новые ошибки не добавлены; whole-file lint clean не заявлен. Общая backend регрессия повторена именно из-за изменения общей основы:24 npm groups/171 node:test cases/exit0. Console assertion scripts дополнительно входят в npm suite,171 не заявляется числом всех их assertions.
**Live.** [Native/API/PG](ux-ui/acceptance/speed-response-body-2026-10-10.json), [browser](ux-ui/acceptance/browser-speed-response-body-2026-10-10.json). Relay сначала получил actual RouterOS done testing, затем передал headers/первые16 bytes настоящего JSON и оборвал body. Теперь API502/понятный неизвестный результат вместо pending, история/прежний synthetic snapshot42/17/15/0 согласованы. Один capped10Mbit/s TCP3s test, native1/noauto retry, PC/3202/2/new message/reload/document fits/pageerror0. Свои disabled probe/history удалены, original IDs совпали, credentials/configuration RouterOS не менялись. Это controlled HTTP socket loss после headers, не independent WAN failure/cancelled native command.
**Runtime.** Backend ux-response100/version1.0.0-test.response100/image797979da82d6…; одна сборка изspeed98 +client/test/package-script files, source archive SHA в отчёте. Entry/node --check/pg_restore18.6/compose --wait passed, приватный .env backup; обновлён только BACKEND_IMAGE_TAG, frontend ux-ospf91/dependencies/migrations прежние. Label response100 — имя блока, не Git SHA. Backend/PG healthy,3 compose containers. Одна локальная фиксация без push; main UI99 всё ещё выполняется на неизменённом frontend source, его итог не заявлен. Квота37% использовано. Следующий101 — подтверждённые нарушения контраста/keyboard code после main99, затем context/финальная сводка.
## 12.5.101 — доступность общей оболочки, текста и OSPF-колонки (2026-10-10)
| Поверхность / референс | До | Доработка |
| --- | --- | --- |
| Sidebar / [App Shell12](https://reui.io/preview/base/app-shell-12?ref=mcp) | Light muted token на тёмной rail:3,55:1 | Subtitle AppSwitcher/NavUser использует sidebar foreground/70, popup style сохранён |
| Информация / [Settings16](https://reui.io/preview/base/settings-16?ref=mcp) | Alerts empty text opacity40; enabled badge3,62:1; containers/uptime hints<4,5 | Семантические foreground tokens без лишней прозрачности; локальный override badge, общий theme/vendor не менялись |
| Справка CLI / Settings16 | Horizontal pre нельзя достичь клавиатурой |3 named regions/tabIndex0/visible focus; Tab/Shift+Tab/ArrowRight проверены |
| Filters | HR light badge3,28:1; initial API error4,4:1 | Existing status-online/offline foreground для этих конкретных элементов |
| OSPF / [Data Grid Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Last area/backbone за pinned180px CIDR на320px | Last-column alignment вправо иtitle полной области; цельный CIDR/пиннинг/сортировка сохранены |
Схема: общий context → читаемый status/empty text → таблица с pinned CIDR и доступной последней областью → named code region с keyboard scroll. Структура Frame/base-nova/ReUI Data Grid/Badge сохранена; не установлены новые компоненты, не изменены vendor internals/shared theme. ReUI adapting/quality и MCP Data Grid audit checklist проверены, props/types взяты из установленного API.
[Протокол](ux-ui/acceptance/operational-a11y-2026-10-10.json).24 unique accessibility cases:5 sections +Filters503×dark/light×1280/320; violations0/document fit/no writes. Первые4 alerts failures были неверным fixture endpoint(/api/alerts/overview вместо/api/alerts),2 light Filters выявили реальный contrast initial error. Исправлены fixture/локальный error foreground; повторены только alerts/filters12 cases, остальные12 accepted cases не повторялись. Geometry5/5: исправленный failed main OSPF scenario +4 CIDR sizes. Context221/221 из99 работает на101 source, без регрессии source/permissions/checkpoints.
Scoped TypeScript/новые components+test lint passed; старый NavUser set-state-in-effect error подтверждён наHEAD, whole-file clean не заявлен. Одна remote frontend Docker production build/full TypeScript/entry/node --check/compose passed, backend/lockfile/миграции прежние. Frontend ux-a11y101/version1.0.0-test.a11y101/image52b50784b914…; clean context ospf91 +9 source overrides, archive SHA в отчёте, label неGitSHA. Приватный .env backup, изменён толькоMMAPP_IMAGE_TAG.
[Live20/20](ux-ui/acceptance/live-a11y-2026-10-10.json) настоящего frontend/backend безHTTP mocks:5 routes×2 themes×2 widths, axe0/pageerror0/overflow0/API writes0. Сертификатные3 blocks во всех4 combinations доступны Shift+Tab/Tab иArrowRight. [Светлая CLI/фокус320](ux-ui/screens/certificates-a11y-light-320-2026-10-10.png), [тёмные Filters320](ux-ui/screens/filters-a11y-dark-320-2026-10-10.png) просмотрены; остальные dark certificate/light filters snapshots сохранены. Code screenshot показывает горизонтально прокрученный focused block, его содержимое не обрезано в данных.
Это scoped accessibility delta, не полная WCAG/все состояния/повтор всегоmain. Два CHR/credentials/configuration не менялись, только3 compose containers/backend/PG healthy. Следующий102 — клиент PATCH сейчас принимает nonempty malformed JSON как{}, что может выглядеть ACK; проверить/исправить его без изменения правила empty successful response, затем ограниченная профильная фиксация. Один локальный коммит без push; этап12.5 остаётся открытым.
## 12.5.102 — malformed PATCH JSON не подтверждает изменение (2026-10-10)
Раньше rosPatch превращал непустой невалидный JSON в{} и мог выглядеть успешным ACK. Теперь возвращает error «Некорректное JSON-подтверждение RouterOS: результат изменения неизвестен» без эха тела ответа. Empty2xx compatibility, нормальный JSON, explicit401, команды/права/метаданные/автоматические retries не менялись. [MikroTik REST PATCH](https://help.mikrotik.com/docs/spaces/ROS/pages/47579162/REST%2BAPI) описывает updated object как результат успешного изменения; ошибки не следует заменять пустым объектом.
[Отчёт](ux-ui/acceptance/patch-acknowledgement-2026-10-10.json): before8 tests/7pass/1fail (PATCH falsely resolved); after8/8. GET/POST/PUT rejection иexplicit empty PATCH сохранены, partial-response6/complete success/401 прежние. IPsec иOSPF optimizer profile suites/локальный backend production build/new test lint passed. Консольные assertion scripts этих suites не переобозначаются произвольным числом node:test cases. Whole backend/main/context не повторялись после одного parser branch; общая100/99 и профили сохраняют свои границы.
**Native.** Своя GRE pair/private198.18.102.0/30 на двух CHR. Normal PATCH comment вернул actual updated.id/comment. Relay следующего PATCH сначала получил настоящий native200/updated comment, затем отдал downstream malformed JSON200. SDK rejected unknown; независимый GET подтвердил фактически изменённыйcomment. PatchCalls1/noauto retry дляfault path. Это HTTP response fault injection после real write, не реальное повреждение WAN; не заявлена приёмка каждого API mutation handler. До любых writes проверены оба устройства/subnet/отсутствие GRE с такими же outer endpoints. Exact own IDs/name/comment/address/interface cleanup, original3 collections×2 совпали, public/default/metadata/195.195.195.195/32 иcredentials сохранены.
**Связность/оснастка.** Первый fixture остановился доPATCH на требовании Ping3/3, фактически2/3; cleanup accepted. ACK scenario не требует нулевых потерь: повтор использовал по одному paced Ping3/1s, сохранил фактические1/3/66% наCHR1→2 и3/3/0% обратно; zero-loss GRE не принят. Сетевые потери не скрыты успешным ACK. Следующий103 — read-only native packet rows/public versus own GRE diagnostics, чтобы отличить actual packet loss от неверной интерпретации статистики; BGP hold-timer безBFD отложен до понимания пути.
**Deployment.** Одна backend Docker production build изresponse100 +client/test, без dependency/миграций; entry/node --check/pg_restore18.6/compose --wait passed. Backend ux-patch102/version1.0.0-test.patch102/image34fca84b8721…; frontend ux-a11y101 прежний. Приватный .env backup, изменён только BACKEND_IMAGE_TAG, labelpatch102 неGitSHA. Только3 compose containers/backend/PG healthy. Один локальный commit без push; этап12.5 открыт.
## 12.5.103 — native Ping: public и собственный GRE (2026-10-10)
[Сырые packet rows/cleanup](ux-ui/acceptance/gre-ping-diagnostics-2026-10-10.json). Своя GRE pair198.18.103.0/30, доwrites обаenabled CHR доступны/нетконфликтов prefix/outer endpoints.8 bounded native Ping команды по10 пакетов/interval0,5s: initial/settled×оба направления×public/GRE;80 packets всего. После первой серии2s пауза. Сохранены seq/time/status/sent/received/loss/avg-rtt без credential fields, resource version/CPU. Source/runtime не менялся: backend patch102/frontend a11y101.
| Путь | Initial | Settled |
| --- | --- | --- |
| Public CHR1→CHR2 |10/10 |10/10 |
| Public CHR2→CHR1 |10/10 |10/10 |
| GRE CHR1→CHR2 |9/10,1 timeout |10/10 |
| GRE CHR2→CHR1 |10/10 |10/10 |
Во всех8 ответах final sent/received соответствуют числу raw reply/timeout rows. В этой серии статистика согласована; счётчики нельзя «исправить», скрыв timeout. Наблюдения102 с1/3 и2/3 не переписаны. Здесь steady sample не выявил устойчивых потерь, но причиной начальных потерь и долгосрочной zero-loss/SLA это не является; startup/transient explanation остаётся гипотезой. Нет packet capture/физическогоWAN теста/максимальной нагрузки.
Exact own GRE/IP IDs/name/comment/address/interface удалены, baseline3 коллекций×2 совпал; public/default/metadata/195.195.195.195/32 иcredentials сохранены. ОбаCHR доступны, native fixtures/extra containers0, build/DB writes/messages0. Следующий104 — собственная BGP пара безBFD, negotiated hold3s/keepalive1s, scoped TCP loss при работающем GRE/ICMP, withdrawal/recovery. Проверка отличает hold expiry от административного connection/interface disable; не обещает точный timing/physical WAN redundancy. Один локальный commit без push; этап12.5 открыт.
## 12.5.104 — BGP hold expiry без BFD (2026-10-10)
[Native/API/cleanup](ux-ui/acceptance/bgp-hold-timer-2026-10-10.json). Собственная GRE198.18.104.0/30/loopbacks198.18.204.1/32↔2/32, AS65104/65105; input/output chains принимают только соответствующий exact own /32, output.network single own loopback/default-originate never. Обаnative connection use-bfd=false, hold3s/keepalive1s; session local/remote hold-time3s иkeepalive1s подтверждены, BFD configurations не создавались.
Две собственные firewall rules только наCHR1: input/output TCP между own GRE link IPs с exact in/out-interface; baseline firewall empty проверен. НиGRE, ниBGPconnection не отключались. Полный underlay остаётся активным, после protocol loss direct GRE ICMP3/3×2/running=true. BGP initially Established/own route/Ping3/3×2; после scoped TCP loss обе сессии перестали быть Established/active own route отсутствует. Снятие двух own rules восстановило Established/own /32/catalog Rx1×2.
ACK добавления двухdrops41,3ms; первое notEstablished наблюдение2667,3ms, обе active routes отсутствуют3690,5ms от начала fault. last-keepalive instant не зафиксирован, samples включаютREST/планирование: это upper observation bounds, не точное hold duration/SLA. Различие с92 административнымdisable/93BFD-path loss сохранено. В этой конфигурации отказ TCP проявился при работающем GRE/ICMP; physical WAN redundancy/разные peers/IPv6/scale не приняты.
Определение hold/keepalive подтверждено [официальным BGP connection reference](https://manual.mikrotik.com/docs/cli-reference/routing/bgp/connection/); текущая online docs7.26, наличие свойств/поведение непосредственно проверено на lab7.24.5. Source/UI/build/DB writes/messages0, первая попытка passed. Ownership preflight exact IDs/name/comment/chain/list/address/interface/protocol/src/dst, drops сначала удалены дляrecovery, потом own BGP/filter/address-list/IP/bridge/GRE. Baseline10 коллекций×2 совпал, public/default/metadata/195.195.195.195/32/credentials сохранены, обаCHR доступны. Runtime backend patch102/frontend a11y101, extra fixtures/containers0. Один локальный commit без push.
Следующий105 — заключительный source/context/runtime/evidence контроль окна и точная матрица оставшихся внешних условий. Принятые network tests не повторять без изменения/ошибки. Этап12.5 остаётся открытым.
## 12.5.105 — source/runtime/evidence: заключительный контроль окна (2026-10-10)
[Финальная source сверка](ux-ui/acceptance/deployment-final-audit-2026-10-10.json), HEADbeb72ce.904 unique tracked application/config inputs: frontend515/backend406 matched; production source drift0. Root package preprocessing/workspaces/clean-context dockerignore идве исключённые backend tests(recursive as const/speed98 assertions) разобраны. Backend984 compiled files actual container совпадают с local build после явнойLF normalisation; byte identity не заявлена. Frontend identified by source context/lockfile/image/build101/live20, independent binary reproducibility не заявлена.
[Read-only stand](ux-ui/acceptance/stand-final-control-2026-10-10.json): обаenabled CHR отвечают/RouterOS7.24.5,14 native collections×2 не содержат prefixes объектов этого окна. Own speed history/probes0, servers2/migrations9. Это выборочная GET/SELECT сверка по своим namespace, не full export/universal ownership scanner. Нативные session caches не удалялись.3 compose services running/backend/PG healthy/compose config passed; дополнительных fixture containers нет. Credentials/RouterOS defaults/public/195.195.195.195/32 сохранены в профильных baseline проверках.
Runtime backend ux-patch102/version1.0.0-test.patch102/image34fca84b8721…; frontend ux-a11y101/version1.0.0-test.a11y101/image52b50784b914….13 контрольных блоков93–105; каждый фактический результат сохранён локально безpush. Whole main1207/1208 с исходным failure иdelta5/5, context221/221, backend100 groups24/node171 +parser1028/8/IPsec/OSPF profiles, accessibility24local/20live; это точные границы, не суммарная выдуманная «полная production приёмка». Принятые unchanged tests повторно не запускались.
Все numbered records датированы, no duplicate12.5.21 после exact dedup, progress/stage12 согласованы.120 перегенерированных canonical/mock evidence files восстановлены из493 protected originals, прежние чужие skills/AGENTS/8GRE-VXLANscreens/tsbuildinfo/.codex/.codegraph изменения сохранены.20 новых JSON reports разобраны и проверены по заданным sensitive keys(password/secret/private-key/privateKey/token/authorization/tcp-md5-key): непустых strings0. Это конкретный recursive key scan, не универсальная гарантия secret-free всех артефактов.
Внешняя12.5 открыта: настоящие PortalSSO/Telegram/clientOS/IPv6/WAN policy/scale/multi-instance/durable retry/physical loss идругие условия [матрицы](ux-ui-remaining-acceptance.md) не заменяются лабораторными two-CHR proofs. По Telegram отправки0; для real delivery нужны отдельный тестовый бот/чат иявное разрешение на конкретное сообщение. Запрошено наличие Portal/Telegram, зависимые действия не выполнялись. Следующий106 — подготовка внешних интеграций при наличии доступов, иначе отдельные согласованные network/scale bounds. Квота89% использовано при заключительной сверке; новые крупные блоки не начинать без возможностей закончить checks/cleanup/commit. Один локальный commit без push.
## 12.5.106 — готовность Portal/Telegram без внешних сообщений (2026-10-10)
[Read-only отчёт](ux-ui/acceptance/integration-readiness-2026-10-10.json): actual lab authRequired=false, issuerConfigured=true/jwtConfigured=true (только booleans), portalHostname=localhost. Это не настоящий Portal login/проверка ролей/отзыва; JWT value/issuer string не сохранены. Telegram DB tokenConfigured=false/chatConfigured=false, activeRules0. Секреты/chat ID не выводились, API доставки/getMe/login не вызывались, конфигурация/таблицы не менялись, messagesSent0. Helper/pool/container закрыты, основной runtime/3 compose services прежние.
Вопрос о наличии тестовых Portal/Telegram задан пользователю; ответа/разрешения на сообщение пока нет. Реальная приёмка этих веток не заменяется локальными fake sender/JWT checks35–49/89. Следующий107 требует тестовую Portal-конфигурацию/аккаунт и отдельный bot/chat; перед отправкой подготовить конкретное сообщение и получить прямое разрешение. Доступы кCHR/SSH этого разрешения не дают. Остальные clientOS/IPv6/WAN policy/scale/multi-instance/physical failure/durable retry bounds остаются в [матрице](ux-ui-remaining-acceptance.md).
За окно сохранены14 local commits93–106, push0. Backend patch102/frontend a11y101, source904/compiled984 matches, main1207/1208+geometry delta5/5/context221/221/backend171+parser8 profiles/accessibility24local20live вточных границах99–105. ОбаCHR доступны, свои конфиги/DB fixtures очищены, credentials не менялись. Квота94% использовано перед записью; этап12.5 целиком открыт. Один локальный commit без push.
## 12.5.113 — IPsec: несколько сессий одного клиента без ложного офлайн (2026-10-10)
Исправлен mapper: ранее повторяющиеся established active-peers.id удалялись из индекса целиком, и даже единственный соответствующий клиент выглядел офлайн. Теперь индекс сохраняет группу сессий. Единственный клиент с совпадающим ID получает online=true; activeAddress/activeSince выдаются только при одной established сессии. При нескольких сессиях reader не выбирает произвольный lease/uptime. Claims считаются на группу: если её разделяют разные catalog clients, у них sessionAmbiguous и нет подтверждённого online/адреса, как в112. Начальные/завершающиеся сессии не подтверждают online.
Изменены backend/src/services/ipsec-live.ts, ipsec-state.test.ts и tests/e2e/ipsec-data.spec.ts. Контракт и существующие компоненты ReUI не менялись: таблица уже показывает «онлайн» без адреса. Проверены certificate/PSK, перестановка native rows, конфликт aliases, переход несколько→одна→нет established сессий. State108/108; все8 профильных скриптов, backend build, ESLint прошли. E2E16 unique passed33.6s: два новых сценария1280/320 и прежняя профильная регрессия IPsec.
На стенд собран/развёрнут только backend ux-sessions113/version1.0.0-test.sessions113. Source base cb6ec09/context build-alias112 плюс один явный override; source и compiled ipsec-live.js SHA256 совпали с локальными байтами. Label sessions113 не является Git SHA. Frontend ux-alias112-version/version1.0.0-test.alias112 сохранён, backend/PG healthy; у frontend нет healthcheck, подтверждены HTTP/browser. Rollback .env сохранён privately как pre-sessions113.env, прежний образ оставлен.
Оба CHR прошли реальный fetchIpsecState, aggregate GET /api/ipsec вернул200 без failures. В собранном reader проверены контролируемые snapshots с повторяющимися ID и aliases на базе прочитанных состояний; это НЕ создание нескольких реальных IKE подключений. Каталог live пустой: browser smoke1280/320 проверил API, пустое состояние, отсутствие ошибки и overflow; pageerrors0/APIwrites0. Первый browser запуск получил ECONNREFUSED: прежний localhost туннель отсутствовал; восстановлен согласованный SSH forward3000/8000, повтор passed. RouterOS writes0, acceptance DBwrites0, тестовых сетевых объектов не создавалось; пароли прежние.
Протокол: [ipsec-multiple-sessions](ux-ui/acceptance/ipsec-multiple-sessions-2026-10-10.json). Следующий114 — один сертификат с несколькими identity refs: текущий last-reference-wins ещё не исправлен, нужно проверить представление строк и выбор target для мутаций. Одновременные реальные подключения с одним ID, внешние интеграции, client OS, полнаяPKI и итоговая общая регрессия остаются отдельной приёмкой.
| Референс | Схема |
| --- | --- |
| [ReUI Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | ID → группа established → один клиент «онлайн» / разные клиенты «Не определено» |
| [ReUI Stats12](https://reui.io/preview/base/stats-12?ref=mcp) | Несколько сессий → один подтверждённый клиент → сводка без двойного счёта |
## 12.5.114 — IPsec: общий сертификат, разные identity и безопасный target (2026-10-10)
Устранён last-reference-wins: mapper хранит все ссылки на remote-certificate и выдаёт отдельную строку для каждой identity. У каждой строки свой identity:<native-id>, имя, peer, Remote ID, mode-config/static IP. Сертификат без ссылок сохраняет cert:<native-id>. Общая observed сессия не присваивается двум строкам: sessionAmbiguous и «Не определено»; независимые explicit ID проверены отдельно. Перестановка native identity rows не меняет состав/поля каталога.
Resolver помечает запрос по certificate target как неоднозначный при нескольких refs, поэтому PATCH/DELETE не выбирают первую identity. DELETE identity с removeCertificate=true проверяет другие identity/peer refs до первого удаления и возвращает409. Явный removeCertificate=false допускает удаление выбранной identity с сохранением сертификата; локальный HTTP тест подтверждает один delete/историю и отсутствие других writes. Интерфейс пока не предлагает этот отдельный вариант — следующий115 должен сделать его понятным. Прямой endpoint принудительного удаления сертификатов не менялся.
Изменены backend services/ipsec-live.ts, routes/ipsec.ts, state/mutation tests и UI HTTP fixture. Контракт и компоненты ReUI/base-nova не менялись; существующая таблица принимает отдельные DTO rows. State114/114, все8 профильных скриптов, backend build и scoped ESLint passed. E2E18 unique/35.9s: две новые проверки общего сертификата1280/320 плюс профильная регрессия.
Before на backend113: native established с адресом198.18.114.250, две certificate identities, но каталог сохранил только вторую и присвоил ей адрес; первая отсутствовала. After на ux-refs114 обе строки присутствуют и unknown без активного адреса, конфигурационные250/251 сохраняются. Certificate PATCH/DELETE и identity DELETE с общим сертификатом вернули409. PATCH выбранной identity при одинаковых match-by=certificate условиях вернул502 с native400 «a matching identity already exists»; обе identity остались неизменными. Это ограничение RouterOS, успешное редактирование одновременно существующих идентичных match rules НЕ принято. После удаления собственного дубля исходная identity восстановила online/250; её API PATCH имени и возврат исходного имени дали200, native readback совпал. Два успешных PATCH вызывают запись истории с dedupe; число вставленных revisions отдельно не заявляется.
Live browser4/4 без HTTP mocks: dark/light1280/320, обе реальные строки, unknown alert/сводка, decoy offline, reload, overflow0, pageerrors0/APIwrites0. Desktop light и mobile dark снимки просмотрены. Первичные helper ошибки сохранены: syntax до вызовов; DELETE с Content-Type без тела дал400 до guard; затем native matching conflict потребовал правильного критерия приёмки. Каждый запуск с сетевыми объектами завершил cleanup13 коллекций×2; предварительные отказы не выданы за passed.
Backend только: ux-refs114/version1.0.0-test.refs114, base60b2e09/context build-sessions113 плюс два overrides; source и compiled bytehashes совпали. Frontend ux-alias112-version/version1.0.0-test.alias112 сохранён. Backend/PG healthy; frontend подтверждён браузером, собственного healthcheck нет. Rollback .env pre-refs114.env сохранён privately, старый образ оставлен. Собственные certificates/keys/imports/peers/identities/mode-config/profile/proposal/groups/templates/files удалены; исходные13 коллекций×2 совпали, default/public/metadata/195.195.195.195/32/logging сохранены. Оба CHR доступны; пароли прежние.
Протокол: [shared certificate](ux-ui/acceptance/ipsec-shared-certificate-2026-10-10.json), [live UI](ux-ui/acceptance/browser-ipsec-refs-2026-10-10.json). Следующий115 — UI для удаления только выбранной identity с сохранением общего сертификата; затем согласовать оставшиеся native/внешние ограничения и итоговую регрессию. Множественные реальные сессии одного ID, клиентские ОС, полнаяPKI, интеграции и multi-WAN не закрыты этим блоком.
| Референс | Схема |
| --- | --- |
| [ReUI Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Сертификат → все identity → отдельные строки/настройки → выбор по identity ID |
| [ReUI Sheet8](https://reui.io/preview/base/sheet-8?ref=mcp) | Выбранная identity → проверка ссылок → API409 без записи либо подтверждённая операция |
## 12.5.115 — IPsec: удалить identity и сохранить общий сертификат через UI (2026-10-10)
В существующий AlertDialog добавлен Checkbox «Удалить также клиентский сертификат» только для certificate identity с явным identity:<id>. По умолчанию выбран для единственной привязки; при других rows того же certName на том же serverId выключен/disabled. Сертификаты с одинаковым именем на другом сервере не считаются общими. Подтверждение объясняет сохранение сертификата и остальных identity; запрос передаёт removeCertificate=false. При API ошибке диалог/выбор/данные сохраняются, блокировки повторного нажатия прежние. Для cert-only row без identity нет ложной возможности «удалить клиента, сохранив единственный объект».
Изменены app/(main)/ipsec/page.tsx и tests/e2e/ipsec-delete.spec.ts. ReUI/base-nova, установленный AlertDialog и Checkbox переиспользованы; vendor/theme не менялись. Scoped ESLint и source TypeScript passed; production frontend build passed. Приняты26 unique E2E: первая профильная серия22 passed/4 failed из-за проверки getByRole фона при открытом модальном диалоге; corrected includeHidden проверка сохранности DOM rows дала4/4 rerun9.8s. Это26 уникальных, не30 сценариев.
Frontend ux-keepcert115/version1.0.0-test.keepcert115 развёрнут; backend ux-refs114/version1.0.0-test.refs114 сохранён. Source base58f5c48/context build-alias112-front плюс один page override, bytehash совпал. Label keepcert115 — метка этапа, неGitSHA; compiled frontend reproducibility не заявлена. Backend/PG healthy, frontend HTTP/browser passed, healthcheck у frontend отсутствует. Private rollback pre-keepcert115.env и прежний образ сохранены.
На собственном signed-certificate IKE fixture проверены4 live диалога (dark/light1280/320) без mocks; первые3 отменены, в light320 выполнен ровно один DELETE identity с removeCertificate=false. Native readback подтвердил отсутствие выбранной identity и сохранение точного certificate ID и другой identity. Исходный клиент восстановил online/198.18.115.250, unknown alert исчез. Последующие PATCH имени/возврат200 подтвердили восстановление. Чужой для приложения mode-config API не удалял: helper очистил только собственный fixture объект. История вызывается API с dedupe; точное число вставленных revisions не заявляется.
Собственные native объекты и private exports/imports очищены, исходные13 коллекций×2 совпали; маршруты/default/logging сохранены. Оба CHR/SSH доступны, пароли прежние. Screens4, просмотрен light320. Протоколы: [native/deployment](ux-ui/acceptance/ipsec-preserve-certificate-2026-10-10.json), [live UI](ux-ui/acceptance/browser-ipsec-keepcert-2026-10-10.json).
Следующий116: default user DELETE ещё угадывает имя сертификата для identity без remote-certificate; проверить/исключить случай PSK + отдельный cert с совпавшим именем. После последнего исправления — единая общая регрессия. Внешние Portal/Telegram/client OS/multi-WAN/scale и множественные native IKE sessions остаются в матрице.
| Референс | Схема |
| --- | --- |
| [ReUI Sheet8](https://reui.io/preview/base/sheet-8?ref=mcp) | Выбранная identity → прямой объём удаления → сохранить общий сертификат → подтверждённый API результат |
## 12.5.116 — IPsec: не удалять сертификат, угаданный по имени PSK (2026-10-10)
Устранена подтверждённая ошибка default DELETE: при пустом remote-certificate managed display name преобразовывалось в ipsec-user-<slug>, и несвязанный сертификат мог удаляться вместе с PSK identity. Теперь имя клиента не является доказательством связи: certificate deletion/preflight используют только явный remote-certificate либо выбранный cert target. Прямая одиночная certificate привязка по-прежнему допускает удаление; shared refs блокируются до записи как114. PSK диалог объясняет сохранение сертификатов; описания mode-config уточняют, что удаляются только неиспользуемые объекты приложения.
Изменены routes/ipsec.ts, mutation test, IPsec page и delete E2E. Все8 backend scripts, state114, backend build/source TypeScript/scoped ESLint passed. HTTP тест подтвердил PSK name collision: один identity DELETE, removeCertificate0; positive explicit binding: identity+certificate writes2. E2E28 unique passed39.6s, включая PSK описание/сохранение отдельной строки1280/320 и профильную регрессию. Vendor/ReUI/base-nova не менялись.
Before на backend114: создана собственная PSK identity с managed name, совпадающим со slug собственного unused signed decoy certificate. DELETE200 удалил оба объекта, хотя remote-certificate пуст. After на bound116: четыре live PSK диалога (dark/light1280/320), один DELETE через light320 UI, PSK удалён, тот же native ID/имя несвязанного сертификата сохранены. Browser не использовал mocks; APIwrites1, pageerrors0. Исходная certificate IKE сессия/online/198.18.116.250 сохранялись. Это не тест новой PSK сессии/throughput. Просмотрен light320 screenshot.
Обе части собраны последовательно и развёрнуты как ux-bound116/version1.0.0-test.bound116. Base d52c48e/context backend build-refs114, frontend build-keepcert115-front; по одному override для route/page, два source bytehash и compiled backend route bytehash совпали. Frontend compiled reproducibility не заявлена, label bound116 неGitSHA. Private rollback pre-bound116.env и прежние образы оставлены. Backend/PG healthy; frontend browser/HTTP подтверждён, healthcheck отсутствует. На VM25GB после сборок3.6GB свободно/86% занято; ресурсов достаточно для текущих проверок, production performance не оценивалась.
Оба native запуска очистили собственные fixtures, baseline13 коллекций×2 совпал; сохранены logging/default/public/metadata/195.195.195.195/32. Пароли прежние, оба CHR/SSH доступны. API DELETE вызывает history recording с dedupe; число новых revisions отдельно не заявляется. Протоколы: [binding](ux-ui/acceptance/ipsec-certificate-binding-2026-10-10.json), [live UI](ux-ui/acceptance/browser-ipsec-bound-2026-10-10.json).
Следующий117 уже запущен: единая основная UI-регрессия1244 сценария на текущем frontend source, затем контекстный набор и сверка source/build/runtime. Внешние аккаунты/Portal/Telegram/client OS/scale/multi-WAN и одновременные native IKE sessions остаются в матрице.
| Референс | Схема |
| --- | --- |
| [ReUI Sheet8](https://reui.io/preview/base/sheet-8?ref=mcp) | Выбранная identity → явная certificate связь → preflight → удаление выбранных объектов / сохранение несвязанных |
## 12.5.117 — общая UI-регрессия и сверка действующего source/runtime (2026-10-10)
Основной набор1244:1243 passed/1 failed за28.8m; контекстный221/221 за7.2m. Failed large-backups.spec.ts измерял кнопки сразу после изменения1440→320 viewport: размер43.796875px во время CSS-transition, после двух animation frames ровно44×44, границы viewport/pinned соблюдены. Исправлен только тест: expect.poll ждёт прежние44px/координаты без снижения порога. Scoped rerun1/1 за10.2s, полноценный поиск/refresh/error/page/file/focus/grid axe сценарий завершился. Итог1465 unique accepted (1243+1+221); основной первоначальный exit1/failure сохранён,1244 fresh whole-main pass НЕ заявляется. Production UI менять/пересобирать не требовалось, scoped ESLint passed.
Source audit базируется на057b530:905 tracked application/config inputs, frontend515 raw matched + preprocessing package + отсутствующий clean-context .dockerignore; backend405 raw matched + подготовленный root package + четыре test-source differences. Содержимое frontend package проверено: только исключён backend workspace; backend package: scripts omitted, dependencies/devDependencies empty, остальные поля совпадают. Production source drift0; различия ipsec-state/ipsec-mutation/recursive-routes/speed-test tests явно исключены из этого утверждения. Контексты не содержат non-example .env inputs. Git label bound116 — метка, неSHA.
Все984 emitted production backend/contracts outputs, построенные по текущим tracked non-test TS paths, совпали с actual backend container после CRLF→LF. Старые вложенные local dist/backend/src outputs не включались: они не текущие outputs и отсутствуют в контейнере. Это normalized equivalence, не обещание byte identity; отдельная frontend binary reproducibility не доказана. Runtime source contexts build-bound116/build-bound116-front, обе версии1.0.0-test.bound116; backend/PG healthy, frontend HTTP/browser принят116, собственного healthcheck нет.
Read-only stand: оба enabled CHR reachable/RouterOS7.24.5 stable;27 коллекций×2 не содержат собственных prefixes (критерии/пути сохранены в JSON), own speed runs/probes0, servers2/migrations9. Это scoped namespace scanner, не full export и не универсальное определение ownership; native session caches не удалялись. Проверка не меняла RouterOS/пароли. Отдельный118-before fixture после этого подтвердил legacy export bug и очистился по13 коллекциям×2; archive/passphrase остались в памяти и не попали в Git.
Автоматически переснятые120 ранее чистых PNG сохранены в ignored tmp/regression117-generated-screens и убраны из diff; восемь исходных dirty GRE/VXLAN снимков восстановлены из сохранённой копии с проверенными исходными размерами. В этот блок включён только relevant large-backups-320 screenshot; unrelated skills/AGENTS не коммитились. Протокол: [regression/source/runtime](ux-ui/acceptance/regression-current-source-2026-10-10.json).
Следующий118 — удалить name inference из legacy POST /ipsec/users/:serverId/:rosId/cert, отказать PSK до export и проверить прямую certificate binding. Before200 с архивом отдельного своего сертификата уже воспроизведён, не принят как верное поведение. UI fixtures не заменяют native/Portal/Telegram/client OS/multi-WAN/scale приёмку.12.5 остаётся открыт.
| Референс | Схема |
| --- | --- |
| [ReUI Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Viewport → окончание анимации → прежний touch target44px → keyboard/file/axe |
## 12.5.118 — IPsec: legacy экспорт только по явной certificate привязке (2026-10-10)
Исправлен POST /ipsec/users/:serverId/:rosId/cert: managed display name больше не преобразуется в clientCertName как fallback. PSK либо отсутствие remote-certificate возвращают409 до вызова exporter, без contentB64/passphrase. Для отдельного сертификата остаётся явный export-by-name endpoint. Direct certificate binding поддерживается после смены display label: имя сертификата/ключ не меняются, bundle.user соответствует актуальной подписи.
Изменены routes/ipsec.ts и mutation test. Все8 backend scripts/state114, backend build и scoped ESLint passed. HTTP test подтвердил PSK409/exportCalls0, positive200/exportedName ровно explicit ref при другом display label. Первый positive mock упал502 из-за отсутствующего getCertificates у заглушки; fixture дополнен и повтор принят. Последняя перестановка независимых HTTP кейсов проверена focused script повторно. UI/source не менялись, full1244/context221 не повторялись после локального изменения одного backend endpoint; границы117 сохранены.
Native before на backend116: создана своя PSK identity без remote-certificate с именем, совпадающим со slug собственного unused signed decoy cert. Legacy POST200 вернул его P12 archive. After на118: этот запрос409 без archive/passphrase. Для primary certificate identity временно установлен другой managed display label; POST200 вернул archive её прямого remote-certificate, исходный comment восстановлен. Архив/passphrase/instructions использовались только в памяти, не записывались в report/Git. Existing certificate IKE session/CN/FQDN/catalog оставались корректны; это не новая PSK session или клиентская OS приёмка.
Backend ux-export118/version1.0.0-test.export118 собран из build-bound116/base9da5e55 с одним route override; source/compiled route bytehash совпал. Frontend ux-bound116/version1.0.0-test.bound116 сохранён. Backend/PG healthy; rollback .env pre-export118.env и прежний образ оставлены, label export118 неGitSHA. Оба native запуска очистили собственные certificates/imports/peers/identity/groups/templates/mode-config/profile/proposal/files, baseline13×2 совпал. Native certificate IDs сохранялись до собственного cleanup; logging/default/public/metadata/195.195.195.195/32 сохранены, оба CHR/SSH доступны, пароли прежние. Протокол: [export binding](ux-ui/acceptance/ipsec-export-binding-2026-10-10.json).
Следующий119 — закрыть controlled-only границу113: несколько реальных established IKE sessions с одним ID и одним certificate principal. Подготовка отдельного official Debian/strongSwan image начата; клиенты будут в собственных Docker namespaces, private credentials временные/свои, host network и приложение не перенастраиваются. До native подтверждения этот пункт остаётся открытым. Конфигурация сверена с [strongSwan](https://docs.strongswan.org/docs/latest/swanctl/swanctlConf.html), [каталогом credentials](https://docs.strongswan.org/docs/latest/swanctl/swanctlDir.html) и [RouterOS](https://manual.mikrotik.com/docs/virtual-private-networks/ipsec/). Внешние Portal/Telegram/Windows/macOS/mobile/multi-WAN/scale остаются отдельно.
| Референс | Схема |
| --- | --- |
| [ReUI Sheet8](https://reui.io/preview/base/sheet-8?ref=mcp) | Выбранный клиент → явная certificate binding → PKI export либо409 без архива |
## 12.5.119 — две реальные IKE-сессии одного certificate principal (2026-10-10)
Контролируемая граница113 дополнена реальными сессиями: два Docker Linux клиента, official Debian trixie/strongSwan6.0.1-6+deb13u7, собственные namespace/bridge, NET_ADMIN только внутри clients. Один свой RSA2048 клиентский сертификат/ключ, свой CA и явно закреплённый server certificate. IKE/ESP AES256/SHA256/MODP2048, unique=never; чужие сетевые объекты/host networking приложения не перенастраивались. Docker создал и затем удалил собственную временную bridge/NAT сеть.
В принятой конфигурации local ID получен непосредственно из сертификата. RouterOS подтвердил две established с одинаковым ID CN=<имя>-client и разными198.18.119.249/248. Каждый клиент выполнил Ping3/3 до собственного encrypted endpoint198.18.119.1. Это short data-plane proof, не throughput/rekey/SLA. API: clientsTotal1/clientsOnline1, activeAddress/activeSince/sessionAmbiguous отсутствуют. Два live UI1280/320 без mocks: один зелёный «онлайн», VIP не присвоен произвольно, unknown alert отсутствует; writes0/pageerrors0. Mobile screenshot просмотрен. Application source не менялся, backend118/frontend116 сохранены.
Первый cleanup остановился: helper ошибочно ожидал comment у cert, который SDK/RouterOS не сохранил. До повторения scoped recovery проверил имя/CN/CA references/native IDs, удалил только свои объекты/credential files; Docker cleanup уже был завершён. Последующие retries сохранили baseline16×2. Первые FQDN/ADDR4, ручной DN и pinned server+ручной DN получили AUTH_FAILED; RouterOS сообщил identity not found/peer ID does not match certificate. Certificate-derived ID с тем же ключом/CA/server pin прошёл. Точная причина различий encoding не доказана; эти варианты не переименованы в success и остаются следующей120 приёмкой.
Final cleanup: labelled clients/network удалены после owner проверки, свои native logging/peer/identity/policy/group/profile/proposal/mode-config/pool/bridge/address/certificates удалены по ID;16 исходных коллекций×2 совпали, default/public/metadata/195.195.195.195/32 сохранены. Private P12/pass/PEM/config files удалены, пустые свои directories закрыты без recursive delete. Архивы/ключи не попали в Git. Оба CHR доступны, пароли прежние. Инструментальный image сохранён для повторения; приложение не пересобиралось. Протоколы: [native/отказы/cleanup](ux-ui/acceptance/ipsec-real-multiple-sessions-2026-10-10.json), [live UI](ux-ui/acceptance/browser-ipsec-multiple-2026-10-10.json).
References: [strongSwan configuration](https://docs.strongswan.org/docs/latest/swanctl/swanctlConf.html), [credentials](https://docs.strongswan.org/docs/latest/swanctl/swanctlDir.html), [RouterOS](https://manual.mikrotik.com/docs/virtual-private-networks/ipsec/). Два контейнера используют один public WAN/NAT, не являются независимыми площадками и не закрывают Windows/macOS/iOS/Android. Следующий120 — ID interop/encoding; остальные внешние зависимости сохранены в матрице.12.5 открыт.
| Референс | Схема |
| --- | --- |
| [ReUI Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Две подтверждённые сессии → один клиент онлайн → без произвольно выбранного VIP |
## 12.5.120 — кодирование DN и FQDN SAN в реальном IKE (2026-10-11)
На том же strongSwan6.0.1-6+deb13u7 последовательно проверены шесть вариантов с собственными CA/server/client certs, server certificate pin, RSA/AES256/SHA256/MODP2048. Certificate-derived DN, явный asn1dn с точными DER-байтами, FQDN из DNS SAN и FQDN с явным RouterOS remote-id установили tunnel и дали Ping3/3 каждый. Ручной текстовый DN и точный DER с единственным изменением тега CN 0x0c→0x13 отклонены AUTH_FAILED. Сертификат содержит UTF8String; парсер strongSwan6.0.1 выбирает PrintableString для этого ASCII CN. Это доказанная граница данной пары версий, не утверждение обо всех DN/PKI.
Обнаружено: FQDN SAN без явно заданного remote-id успешно аутентифицируется, но catalog API показывает offline. С remote-id=fqdn:… online=true. Первый helper остановился на ошибочном ожидании online; finally полностью очистил стенд. Уточнённый сценарий сохранил этот дефект отдельным результатом и завершил шесть вариантов. Он требует исправления в121, а не считается успешной приёмкой отображения. Ранее119 отказ FQDN включал requested IDr; новая конфигурация закрепляет точный server cert и не запрашивает IDr. Проверка сертификатов не отключалась.
Все свои containers/network/credentials и native objects удалены после проверки ownership. Baseline16 коллекций×2 совпал; оба CHR доступны, пароли и исходная конфигурация сохранены. Application source/runtime не менялись, UI заново не тестировался. [Протокол](ux-ui/acceptance/ipsec-id-interop-2026-10-11.json). Следующий121 — SAN matching с защитой неоднозначности и нескольких ID одного principal. Windows/macOS/mobile, независимые WAN, scale/rekey и интеграции остаются открыты.
References: [Identity parsing6.0](https://docs.strongswan.org/docs/6.0/config/identityParsing.html), [парсер6.0.1](https://github.com/strongswan/strongswan/blob/6.0.1/src/libstrongswan/utils/identification.c).
| Референс | Схема |
| --- | --- |
| [ReUI Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Native established → точный ID/сертификат → подтверждённый online; неоднозначность → неизвестно |
## 12.5.121 — подтверждённый онлайн по DNS SAN и нескольким IKE ID (2026-10-11)
Исправлен обнаруженный120 дефект: RouterOS принимает FQDN SAN, но API сопоставлял только DN/CN/явный remote-id. Теперь точный DNS SAN учитывается при прямой привязке сертификата к identity и отсутствующем/auto remote-id. SAN должен быть уникален среди всех native certificates; DNS wildcard/IP/email/чужие namespaces и конфликты DN/CN не угадываются. Явный иной remote-id не подменяется SAN. Общие claims проверяются по каждой native session, поэтому пересечение с PSK или другой identity остаётся sessionAmbiguous, без присвоения её адреса.
Все наблюдаемые DN/CN/explicit ID/SAN сессии одного principal объединяются: online подтверждён, но при нескольких сессиях не выбираются произвольные VIP/uptime. Добавлены13 state scenarios: unique/duplicate SAN, explicit/auto, DN+SAN с перестановкой, PSK collision, неподдерживаемые SAN, CN shadow и отсутствие привязки. Прошли127 state checks и8 профильных scripts, backend production build и scoped ESLint. Общая регрессия117 не повторялась; DTO/frontend/vendor не менялись.
Backend ux-san121/version1.0.0-test.san121 собран из контекста118 с одним source override. Локальный и серверный SHA256 source/compiled ipsec-live совпали. Frontend116 сохранён; backup pre-san121.env/предыдущий image оставлены. Backend healthy. Первый native helper остановился на regex старого диапазона VIP; finally восстановил baseline, затем regex исправлен. Повторение: один certificate-derived DN и один FQDN SAN одного cert одновременно established, Ping3/3 каждый. Catalog online1, activeAddress/activeSince отсутствуют. Два live UI1280/320 без mocks/write/pageerrors, mobile screenshot просмотрен.
Все свои Docker clients/network/credentials/native configs удалены после ownership preflight; baseline16 коллекций×2 совпал, default/public/metadata/195.195.195.195/32 сохранены. Оба CHR доступны, пароли прежние. [Native/build/проверки](ux-ui/acceptance/ipsec-san-matching-2026-10-11.json), [live UI](ux-ui/acceptance/browser-ipsec-san-2026-10-11.json). Следующий122 — IKE/CHILD rekey/reconnect; клиентские ОС/длительные нагрузки/физические WAN/integrations остаются открыты.
| Референс | Схема |
| --- | --- |
| [ReUI Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Native DN+SAN → один клиент online → несколько сессий без случайного VIP |
## 12.5.122 — реальный rekey CHILD/IKE и повторное подключение (2026-10-11)
На собственном Linux strongSwan→CHR certificate tunnel приняты пять состояний: initial, CHILD rekey, IKE rekey, terminated, reconnected. CHILD rekey подтверждён новой парой native ESP SPI после ухода старых SA; IKE rekey — новым strongSwan IKE unique ID после ухода прежнего. В четырёх connected фазах native established1/API online и Ping3/3 с первой попытки; после terminate established0/API offline без activeAddress/uptime. Повторное подключение вернуло online/Ping. RSA/private CA/exact server certificate pin/AES256/SHA256/MODP2048 сохранены.
Первый прогон принял обе смены ключей/офлайн, но reconnect Ping failed. Сценарий не сохранил достаточно данных для доказательства причины. Повторение использовало именно выданный native VIP, записало все client addresses и ограниченные Ping attempts; каждая рабочая фаза прошла с первого Ping3/3. Это не превращает первый отказ в успех и не доказывает мгновенное/бесшовное восстановление. Оба протокола сохранены. Длительное обновление, packet loss в переходе, reauth и физический WAN/SLA ещё не приняты.
Application source/image не менялись, общая регрессия и UI повторно не запускались. Все собственные Docker clients/network, private P12/PEM/pass/config и native configs/certs/logging удалены с ownership preflight. Baseline16×2 совпал, оба CHR доступны/пароли прежние. Native installed-sa сохранялись только по whitelist public SPI/state/адресов, ключи не записывались. [Протокол с первоначальным отказом](ux-ui/acceptance/ipsec-rekey-reconnect-2026-10-11.json). Следующий123 — неправильный server pin и непривязанный клиентский certificate.
Reference: [strongSwan rekey6.0](https://docs.strongswan.org/docs/6.0/swanctl/swanctlRekey.html).
| Референс | Схема |
| --- | --- |
| [ReUI Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Новые SA → подтверждённый online → terminate/offline → reconnect/online |
## 12.5.123 — server pin и привязка клиентского сертификата (2026-10-11)
Три реальные Linux strongSwan→CHR попытки без ослабления проверки сертификатов. Контрольный клиент с private CA/точным server pin/привязанным remote-certificate установил туннель и дал Ping3/3. Замена server pin на другой собственный certificate привела к отказу на клиенте. Второй RSA client certificate, подписанный тем же CA, но не указанный в remote-certificate identity, отвергнут RouterOS. Общий доверенный CA не подменяет точную native привязку. Отказы проверялись как ожидаемые, а не success tunnel.
После каждой попытки native established0 и catalog online0; неподключённые клиенты не получили active session. Все собственные Docker clients/network/private credentials и native objects удалены;16 исходных коллекций×2 совпали, пароли/default/public/metadata/195.195.195.195/32 сохранены. Оба CHR доступны. Source/runtime не менялись, профильная общая регрессия и UI не повторялись. [Протокол](ux-ui/acceptance/ipsec-certificate-auth-boundaries-2026-10-11.json).
Это ограниченная certificate authentication приёмка, не полная PKI: revocation/expiry, прочие client OS/custom OIDs/ID namespaces остаются открыты. Следующий124 — полноценный reauth и наблюдаемая граница IKE online при отсутствии CHILD SA.
| Референс | Схема |
| --- | --- |
| [ReUI Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Сертификат и привязка подтверждены → online; ошибка pin/привязки → отказ без ложного online |
## 12.5.124 — reauth и честная граница IKE онлайн (2026-10-11)
Реальный strongSwan certificate reauth завершился новой IKE SA и уходом старой; после initial/reauth/CHILD restore Ping3/3 каждый с первой попытки. При terminate только CHILD SA RouterOS сохранил established IKE1, installed-sa0; API продолжал online=true, Ping2/2 потерян. После нового CHILD SA Ping восстановился. Это подтверждает семантику текущего online: установленная IKE-сессия, не измерение передачи данных.
На странице добавлено краткое пояснение «Онлайн означает установленную IKE-сессию. Передачу данных проверяйте Ping». ReUI/Frame/base-nova и существующие компоненты сохранены. Production frontend build/typecheck и scoped ESLint прошли; source hash страницы совпал с Docker context. Frontend ux-ike124/version1.0.0-test.ike124 развёрнут, backend ux-san121 сохранён. Backup pre-ike124.env/прежний image оставлены. Два live UI1280/320 без writes/pageerrors/overflow: дождались API receipt и стабильного положения текста, screenshot mobile просмотрен. Empty catalog UI проверяет пояснение; активные DN/SAN строки уже приняты121.
Native objects/private credentials/Docker clients/network очищены с ownership preflight, baseline16×2 совпал. Оба CHR доступны, пароли/default/public/metadata/195.195.195.195/32 сохранены. Полная регрессия117 не повторялась для этой текстовой правки. [Native/build](ux-ui/acceptance/ipsec-reauth-child-status-2026-10-11.json), [браузер](ux-ui/acceptance/browser-ipsec-ike-status-2026-10-11.json). Длительный reauth/rekey, transition loss, физические WAN и клиентские ОС остаются открыты; следующий125 — отзыв/CRL.
| Референс | Схема |
| --- | --- |
| [ReUI Stats12](https://reui.io/preview/base/stats-12?ref=mcp) | IKE online → пояснение значения → отдельная проверка Ping |
## 12.5.125 — фактическая граница локального отзыва сертификата (2026-10-11)
Контрольный собственный certificate tunnel установился/Ping3/3. Первая попытка использовала неверный /certificate/revoke и получила400 no such command; finally очистил fixtures. По официальному CLI reference уточнена /certificate/issued-revoke. Повторение подтвердило native revoked=true у собственного leaf certificate. Уже установленная IKE-сессия осталась established. После terminate повторное подключение тем же отозванным certificate также установилось. Ожидание отказа не прошло; это сохранённое наблюдение, не успешная приёмка revocation blocking.
После cleanup чтение certificate/settings подтвердило на обоих CHR crl-use=false/crl-download=false; certificates0/crls0. Глобальные settings в этом блоке не изменялись. Документация описывает CRL проверку отдельной настройкой, поэтому native revoked flag не считается доказательством блокировки при нынешней конфигурации. Application source/API не менялись; вывод об API online после reconnect не делается — helper остановился раньше его чтения.
Все свои configs/certificates/logging/private credentials/Docker clients/network удалены. Baseline17 коллекций×2, включая certificate/crl, совпал; default/public/metadata/195.195.195.195/32 и пароли сохранены. [Протокол наблюдения и непройденное ожидание](ux-ui/acceptance/ipsec-local-revocation-observation-2026-10-11.json). Следующий126 — контроль валидного клиента и отказ отозванного при собственной CRL цепочке/временном crl-use, с обязательным возвратом исходных settings. Полная CRL/expiry/PKI приёмка остаётся открытой.
References: [issued-revoke](https://manual.mikrotik.com/docs/cli-reference/certificate/issued-revoke/), [CRL settings](https://manual.mikrotik.com/docs/authentication-authorization-accounting/certificates/).
| Референс | Схема |
| --- | --- |
| [ReUI List9](https://reui.io/preview/base/list-9?ref=mcp) | Метка revoked → отдельная CRL policy → реальная попытка соединения → подтверждённый результат |
## 12.5.126 — CRL-enabled отзыв и проверенная очистка цепочки (2026-10-11)
Создана собственная CA/серверная/клиентская цепочка с CRL URL. До control IKE временно включены crl-use/crl-download на CHR1, после проверки certificates0/CRLs0 baseline. Валидный клиент установился/Ping3/3. После issued-revoke подтверждён revoked=true; действующая IKE могла остаться established. После явного terminate новый IKE тем же cert отвергнут AUTH_FAILED, native established0/API offline. Это закрывает отличие от125 для данной local CA конфигурации, не полную PKI и не мгновенный разрыв существующих SA.
Все certificate/settings возвращены к точной исходной записи. Initial sign потребовал точный .id — добавлен по ответу REST. Первый cleanup остановился на удалении issued server leaf: RouterOS требует revoke для сертификата CA с CRL. Settings/Docker/network/configs к этому моменту уже восстановлены/удалены. Recovery проверил ровно три собственных имени/CN/issuer, отсутствие своих configs, исходные settings и удалил точный собственный CA ID с каскадом только этих проверенных детей. CRL/private files очищены. Повторение использовало preflight всех дочерних cert IDs/ссылок перед own CA cascade и прошло целиком; baseline17 коллекций×2, private credentials/Docker/settings restored.
Наблюдение показывает риск API удаления: identity может быть удалена до native отказа удаления CRL-issued certificate. Следующий127 —409 до любых writes для защищённого leaf и CA с issued children; сохранение cert при identity-only остаётся доступным. Production source/runtime в126 не менялись. Оба CHR доступны, пароли/default/public/metadata/195.195.195.195/32 сохранены. [Все результаты/отказ cleanup/recovery](ux-ui/acceptance/ipsec-crl-revocation-2026-10-11.json).
Reference: [Certificates/CRL](https://manual.mikrotik.com/docs/authentication-authorization-accounting/certificates/). Expiry, внешняя CRL загрузка/timeout, intermediate/custom PKI, клиентские ОС и долговременные нагрузки остаются открыты.
| Референс | Схема |
| --- | --- |
| [ReUI List9](https://reui.io/preview/base/list-9?ref=mcp) | CA/CRL policy → валидный клиент → отзыв → reconnect отказ → возврат исходных settings |
## 12.5.127 — удаление CRL-issued сертификатов без частичных изменений (2026-10-11)
Исправлена выявленная126 последовательность: перед удалением identity API проверяет явно привязанный cert/issuer. Локально issued либо revoked certificate CA с crl=true получает409 до любых writes. Пользователь может удалить только identity с removeCertificate=false. В /ipsec/certs дополнительно запрещено отдельное удаление CA с дочерними certs: RouterOS каскадно удаляет цепочку, поэтому force=true это ограничение не обходит. Автоматический отзыв/удаление чужой цепочки не добавлялся. Imported non-issued/non-revoked leaf сохраняет прежний сценарий удаления.
Добавлены13 профильных HTTP cases с нулевыми writes/history при отказе, сохранением cert при identity-only, обеими issued/revoked формами native metadata, CA force guard и положительным imported случаем. Прошли8 IPsec scripts (state127), backend production build/scoped ESLint. Backend ux-crl127/version1.0.0-test.crl127 собран из121 с одним route override; локальные и серверные source/compiled SHA256 совпали. Frontend ux-ike124 сохранён, backup pre-crl127.env/прежний image оставлены. DTO/vendor не менялись.
Native собственная CRL chain: семь409 (user/cert targets, direct leaf/CA с/безforce и revoked leaf) сохранили certs; до identity-only identity также оставалась. Identity-only200 удалил выбранную identity, сохранил все3 certs. Первый control остановился на Ping3/3 без достаточной диагностики; cleanup прошёл, отказ сохранён. Повторение проверяло выданный native VIP и записывало bounded Ping attempts, затем завершило API-сценарии. Мгновенная связность/SLA не заявляется.
Settings восстановлены точно, own CA cascade после проверки всех детей/ссылок очистил только собственную цепочку; baseline17×2/Docker/private credentials restored. Оба CHR доступны, пароли/default/public/metadata/195.195.195.195/32 сохранены. UI и общая регрессия117 повторно не запускались: guards/backend-only, сохранение modal при API error уже принято предыдущими UI блоками. [Протокол](ux-ui/acceptance/ipsec-crl-delete-preflight-2026-10-11.json). Следующий128 — expired/not-yet-valid certs без изменения часов.
| Референс | Схема |
| --- | --- |
| [ReUI Sheet8](https://reui.io/preview/base/sheet-8?ref=mcp) | Проверка cert/CA →409 без изменений → выбор сохранить cert → подтверждённое identity-only удаление |
## 12.5.128 — сроки сертификатов и неподтверждённая причина отказа (2026-10-11)
На OpenSSL3.5.7 созданы собственные same-key/same-CA сертификаты с явно заданными датами. Часы VM/CHR не менялись. Действующий original cert и перевыпущенный valid cert установили IKE/Ping3/3 каждый. Для renewed/invalid сертификатов временная собственная identity проверяла доверенный CA (remote-certificate=none/match-by=remote-id/auto), сохраняя pubkey auth/crypto и точный server certificate pin. Положительный renewed control доказывает работоспособность этой конфигурации с новым certificate DER.
Expired и not-yet-valid certificate не установили сессию за30s: IKE_INIT отвечал, затем IKE_AUTH retransmits, без явного AUTH_FAILED. Native established0/API online0. Это наблюдение тайм-аута, а не доказанный RouterOS expiry отказ. Журнал прочитан после cleanup, audit boundary уже не сохранился; точная причина остаётся открытой. Следующий129 должен захватить scoped auth logs сразу в каждой фазе.
Первый подход пытался импортировать expired cert: новых native rows оказалось0, точная причина импорта не записана. Cleanup остановился на принадлежности файла/ID. Scoped recovery проверил собственный namespace/CN/issuer/возраст, удалил только свои configs/certificate chain и точное имя созданного CRT (flash directory не удалялся), private files/CA key. Повторение не импортировало invalid certificates, держало их только в собственном client filesystem; cleanup baseline17×2/Docker/credentials passed. Оба CHR доступны/пароли/default/public/metadata/195.195.195.195/32 сохранены.
[Протокол и все ограничения](ux-ui/acceptance/ipsec-certificate-time-observation-2026-10-11.json). Полный первоначальный Ping failure127 дополнительно перенесён в репозиторий. Source/runtime не менялись, UI/общая регрессия не повторялись. Expiry reason и внешняя CRL/PKI приёмка не закрыты.
Reference: [OpenSSL x509 dates](https://docs.openssl.org/3.5/man1/openssl-x509/).
| Референс | Схема |
| --- | --- |
| [ReUI List9](https://reui.io/preview/base/list-9?ref=mcp) | Valid control → encoded dates → native establishment/API → тайм-аут без выдуманной причины |
## 12.5.129 — непройденный положительный контроль и изоляция диагностики (2026-10-11)
Повторение с чтением журнала во время фаз остановилось на valid-renewal control: original cert/Ping3/3 прошли, действующий новый cert получил IKE_AUTH timeout. Expired/future случаи не запускались. Поэтому предыдущие128 тайм-ауты не считаются доказанной expiry причиной. Phase authLogs оказались пусты; точная транспортная/сертификатная причина пока не определена.
Readonly clock проверка: VM20:13:44Z, CHR1 23:13:44/+03:00 (Moscow), CHR2 22:13:44/+02:00 (Warsaw), в пределах точности секунд совпали. Часы и timezone не менялись. Default memory:1000 entries/stop-on-full=false; CHR1 журнал содержит273 сообщения namespace129. Гипотеза о повторном использовании container IP/UDP tuple не выдаётся за установленную причину. Следующий130 использует отдельный netns/IP на вариант и собственный memory logging action с чтением только своего буфера; default logs не очищаются.
Final cleanup baseline17 коллекций×2/Docker/private files (включая собственный CA key) passed. Оба CHR доступны, passwords/default/public/metadata/195.195.195.195/32 сохранены. Source/runtime не менялись, UI/регрессия не повторялись. [Failure/control/clocks/log metadata](ux-ui/acceptance/ipsec-time-control-failure-2026-10-11.json).12.5 и time-validity diagnosis открыты.
| Референс | Схема |
| --- | --- |
| [ReUI List9](https://reui.io/preview/base/list-9?ref=mcp) | Положительный контроль не прошёл → не принимать отрицательные случаи → изолировать транспорт/журнал |
## 12.5.130 — изолированная проверка сроков и исправление остатка cleanup (2026-10-11)
Каждый renewed/expired/future вариант получил отдельный Docker client namespace/IP (.3/.4/.5); прежние контейнеры удерживали адреса до общего cleanup. Original и renewed valid client установили IKE/Ping3/3. Expired и not-yet-valid client получили явный AUTHENTICATION_FAILED от CHR, native established0/API online0. Own key/CA/server pin/pubkey auth/crypto сохранены, часы не менялись. Это принимает local same-key/CA time-boundary после положительного renewed control; точная причина прежних128/129 тайм-аутов не доказана.
Созданы и затем удалены собственные memory action/rule без очистки штатного memory. Collector GET buffer query сохранил также исторические сообщения, поэтому строгая атрибуция этих логов не считается принятой; proof отрицательных случаев — прямой IKE AUTH_FAILED и состояние API/native. Полный диагностический buffer selector требует отдельной проверки через print query.
Обнаружено дополнительно: recovery128 удалял объекты по name/comment и пропустил logging rule, имеющее только prefix. Оно входило в последующие baseline128/129/130; их равенство не доказывало отсутствие этого остатка. Проверено точное имя namespace из recovery128, единственная rule с этим prefix, topics и action=memory; удалён только её native ID. Все остальные logging rows остались точно прежними, default журнал не очищался. Артефакты128/129 дополнены исправлением, исторические ограничения сохранены.
Итоговое повторение18 коллекций×2 прошло; после него отдельно удалён доказанный остаток128. Own custom logging action/clients/network/private files/CA key очищены, certificates/CRLs0, оба CHR доступны/пароли/default/public/metadata/195.195.195.195/32 сохранены. Source/runtime/UI не менялись. [Протокол и correction](ux-ui/acceptance/ipsec-isolated-certificate-time-2026-10-11.json). Следующий131 — ECDSA P-256 chain/Ping/экспорт. Full intermediate/custom PKI/external CRL/OS/scale остаются открыты.
| Референс | Схема |
| --- | --- |
| [ReUI List9](https://reui.io/preview/base/list-9?ref=mcp) | Раздельные клиенты → valid control → explicit AUTH_FAILED → API offline → полная ownership очистка |
## 12.5.131 — ECDSA P-256 и итоговая очистка блока IPsec (2026-10-11)
Создана собственная ECDSA P-256 CA/server/client chain (prime256v1), без изменения existing certificates/passwords. strongSwan6.0.1 установил certificate-authenticated IKE/ESP tunnel с точным server certificate pin/private CA и AES256/SHA256/MODP2048; Ping3/3. Public client key проверен Node X509: ec/prime256v1. API online1 и конкретный VIP этой единственной сессии. Экспорт client cert через /api/ipsec/certs/1/export вернул200/archive; архив и passphrase не сохранены в evidence/Git.
Own logging/peer/identity/policy/group/profile/proposal/mode-config/pool/bridge/address/certificates/private files/Docker client/network удалены по ownership preflight; baseline16×2 совпал. Дополнительная итоговая readonly inventory18 коллекций на каждом CHR проверила все namespaces120–131: residue0, established0, crl-use/download=false, private directories0. Labelled Docker acceptance containers/networks0; backend ux-crl127 и PostgreSQL healthy, frontend ux-ike124 running/HTTP+UI уже подтверждены124. Source/runtime/UI в131 не менялись, тесты и регрессия не повторялись. Оба CHR доступны, пароли/default/public/metadata/195.195.195.195/32/flash directory сохранены.
За эту серию исправлены implicit DNS SAN online121, смысл подписи IKE online124 и no-write CRL certificate/CA deletion guards127. Native interop/rekey/reauth/authentication/CRL/time validity/ECDSA приняты только в описанных границах. Все initial failures/recovery сохранены; тайм-ауты128/129 не переименованы в success и не используются как proof expiry. [ECDSA/экспорт/final inventory](ux-ui/acceptance/ipsec-ecdsa-p256-2026-10-11.json).
Следующий132 — проверить scoped logger через POST print query (GET buffer collector130 содержит исторические сообщения), затем external CRL download/failure и оставшуюся матрицу. Windows/macOS/mobile, intermediate/custom PKI, независимые WAN/scale/долговременные нагрузки/реальные интеграции ещё не приняты. Этап12.5 открыт; новые native проверки начинать только с доступным бюджетом для cleanup и сохранения.
| Референс | Схема |
| --- | --- |
| [ReUI Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | EC cert/CA → native IKE/Ping → API online/VIP → подтверждённый экспорт → ownership cleanup |
## 12.5.132 — изоляция диагностических буферов RouterOS (2026-10-11)
На обоих CHR RouterOS7.24.5 созданы по два собственных RAM action/rule с разными prefix. Один script/info marker попал в оба буфера. POST /log/print с .query=[buffer=ownAction] и .proplist вернул только нужный prefix: один маркер, foreignRows0. Контроль другого буфера вернул другой prefix; несуществующий буфер —0 строк. Обычный POST параметр buffer отклонён400; это ожидаемый отрицательный контроль. В проекции поле buffer отсутствует, поэтому изоляция подтверждена независимыми маркерами/контролями, а не выдуманным значением поля.
GET /log?buffer=ownAction тоже изолирует корректно. Повторное чтение helper130 показало, что после initial scoped read его collector обращался к общему GET /log. Поэтому предыдущая формулировка о ненадёжности GET buffer уточнена: дефект был в диагностическом сборщике. Исторические записи130 остаются смешанными и не становятся доказательством конкретной причины отказа сертификата.
Все четыре собственных logger/action на каждом CHR удалены по exact-ID/name/prefix/action/topics preflight. Полные существующие logging/action rows до/после совпали на обоих устройствах; default buffer не очищался. Пароли и VPN-конфигурация не менялись. [Протокол и точный selector](ux-ui/acceptance/routeros-scoped-log-2026-10-11.json). Документация: [REST query](https://manual.mikrotik.com/docs/developer-guides/rest-api/), [раздельные memory buffers](https://manual.mikrotik.com/docs/diagnostics-monitoring-and-troubleshooting/log/).
Source/runtime/UI не менялись; build и регрессия не повторялись. Следующий133 — оставшиеся реальные сценарии и проверка расхождений API; external CRL distribution failures, другие ОС и независимые WAN остаются открыты.12.5 не завершён.
## 12.5.133 — реальные журналы в REST-терминале (2026-10-11)
Диагностика132 выявила продуктовый баг getLogs: GET /log?limit=N использовал limit как REST property filter. На обоих CHR default memory содержал1000 строк, но SDK возвращал0, а API log print limit=3 —200/(no log entries). Исправлен SDK: чтение default memory с проекцией полей, последние N строк в native chronological order, максимум200. Невалидный limit отклоняется до опроса. Это лимит вывода: native buffer читается целиком перед slice; лимит сетевой передачи не обещается.
Проверены реальные API limits3/50/500→3/50/200 на каждом CHR, own marker виден, latest native IDs совпадают; limit0→400. Live терминал1280/320 получил по3 реальные строки, очистил поле команды после успеха и не имеет document overflow. Уточнена исходная подпись: «REST: каждая команда — отдельный запрос. Результат появится после ответа API.»; постоянная фраза о непроверенном соединении больше не противоречит успешному результату. ReUI Frame/Button/Input и base-nova сохраняются, vendor/layout не менялись.
Профильный HTTP SDK test (tail/default50/cap200/short/empty/invalid limits/401) passed, включён в npm test:exec. HTTP route/empty-versus-error и signed JWT/RBAC passed; backend build passed; source-only TypeScript и frontend production build passed. Scoped ESLint страницы/тестов passed; SDK lint имеет две исходные prefer-const ошибки125/899, проверка с отключением только этой rule passed. Обычный root tsc захватил ignored historical tmp и failed; существующий source-only config passed. Initial SDK test sandbox EACCES исправлен разрешённым loopback запуском. Первый UI assertion сравнивал newline string с отдельными div и failed; исправлен только способ проверки, final2/2 passed. Эти initial failures не скрыты и не прибавлены к уникальным сценариям.
Развёрнуты production backend/frontend ux-log133; backend/PostgreSQL healthy, frontend running/live UI. SDK source и compiled output SHA256 совпали с Docker; source страницы совпал с build context. Сохранены private rollback env и предыдущие образы. Только script/info markers добавлены в default logs; журнал не очищался, новых конфигурационных/VPN fixtures нет, оба CHR доступны, пароли не менялись. [До/после и проверки](ux-ui/acceptance/terminal-log-limit-2026-10-11.json), [live UI](ux-ui/acceptance/browser-terminal-logs-2026-10-11.json).
Следующий134 — external CRL distribution/failure и оставшаяся матрица. Полная итоговая регрессия после последнего product изменения ещё требуется;12.5 открыт.
| Референс | Схема |
| --- | --- |
| [ReUI App Shell12](https://reui.io/preview/base/app-shell-12?ref=mcp) | Устройство → log print limit=N → default memory tail → ответ API → реальные строки |
## 12.5.134 — внешняя загрузка CRL и отказ HTTP endpoint (2026-10-11)
Первый CHR выпустил собственные CA/client certificates с CDP; второй импортировал только public PEM, private-keys-imported0. Публичный DER CRL успешно разобран OpenSSL. Временный HTTP endpoint на Debian161.104.46.222:18084 отдавал только точный CRL path с Content-Length/Connection close. Фактические downloader GET от104.165.244.7 зафиксированы; dynamic CRL для CA и client в итоговом snapshot оба invalid=false/expired=false/revoked0.
Для независимого static CRL URL с отсутствующим path сервер вернул404 фактическому downloader. Строка осталась invalid=true/cert=none; ранее загруженные валидные CA/client CRL сохранились. Это принятие HTTP download/404/cache preservation, а не доказательство IKE refusal для сертификата с недоступным собственным CDP. Новый VPN tunnel здесь не создавался: проверяется инфраструктура распространения CRL. Отказ IKE, истёкший/повреждённый CRL, часовой refresh и немедленное завершение existing IKE остаются открыты.
Initial attempts сохранены полностью.1: manual download400/in progress и cleanup preflight failed, поскольку RouterOS потребил публичные файлы после импорта; exact scoped recovery убрал own chain/files/cache, остальные файлы сохранены.2: direct CHR-to-CHR CRL не загрузился за20s, cleanup10×2 passed.3: receiver /tool/fetch к direct CHR URL получил remote disconnected while in HTTP exchange, хотя Debian GET200; точная причина неизвестна, настройки HTTP/Firewall не менялись.4: временный endpoint дал valid CRL control, но повторный manual download во время automatic job вернул400/in progress; cleanup passed.5: busy receipt учтён отдельно, ожидается actual downloader request/status; valid+404/cache control и cleanup passed. Эти отказы не переименованы в success; direct distribution между CHR не принята.
CRL-use/download второго CHR восстановлены точным сравнением исходного settings object. Own logger/action, issuer chain, imported certificates, exports/uploads и CRL cache удалены после exact ownership preflight. Набор IDs10 коллекций на каждом CHR совпал с baseline итогового запуска; endpoint closed, порт18084 больше не слушается, Compose one-off завершён. Default buffer не очищался; flash directory/default/public/metadata/195.195.195.195/32 сохранены; пароли не менялись. Backend/PG healthy, frontend ux-log133 running; source/runtime/UI не менялись, build и регрессия не повторялись. [Все попытки и итоговый протокол](ux-ui/acceptance/ipsec-external-crl-download-2026-10-11.json).
Следующий135 — certificate-bound missing/expired/malformed CRL и IKE enforcement с новым успешным контролем.12.5 открыт.
| Референс | Схема |
| --- | --- |
| [ReUI List9](https://reui.io/preview/base/list-9?ref=mcp) | Own CA → public certificate/CDP → HTTP200 CRL → valid cache → own404 → invalid row → scoped cleanup |
## 12.5.135 — недоступный CRL привязанного сертификата и реальный IKE (2026-10-11)
Создан собственный certificate-authenticated tunnel на CHR2; client CA/certificate выпущены CHR1 и импортированы в responder только публично. Собственный responder CA/server key создан native на CHR2. Linux strongSwan использовал собственный client key/private CA и точный public server certificate pin. CRL-use/download=yes; distinct Linux containers/addresses сохранены для трёх фаз.
1. Валидный external CRL для CA/client загружен: IKE/ESP established, Ping3/3, API online=true.
2. Тот же certificate CDP endpoint отвечает404; own CRL cache сброшен только после проверки ownership всех сертификатов/URL, invalid caches подтверждены. Native RouterOS ответил AUTHENTICATION_FAILED в обоих запусках; scoped log первого запуска — «failed to validate path: CRL not found» для собственного client certificate. Established0/API online=false. Это явный PKI отказ, не inference по timeout.
3. Endpoint снова отдаёт signed valid CRL, оба cache valid; новый Linux container: IKE/Ping3/3/API online=true.
Первый запуск прошёл1–2, но recovered control получил IKE_INIT timeout без ответа и не был принят как восстановление. Его полный протокол сохранён, exact transport cause неизвестен. Повторный полный запуск прошёл три фазы; возможный bounded transport retry записывается отдельно, не увеличивает число уникальных сценариев. [Оба запуска и итог](ux-ui/acceptance/ipsec-external-crl-ike-2026-10-11.json).
CRL settings восстановлены точным сравнением. Own endpoint/logger/CA/certificates/private exports/credentials/Linux clients/network/IPsec identity/peer/policy/group/profile/proposal/mode-config/pool/bridge/address удалены по ownership checks.18 наборов IDs на каждом CHR совпали с baseline; private files removed, Docker cleanup, порт18084 закрыт. Existing/default/public/metadata/195.195.195.195/32/flash directory и пароли сохранены. Crypto dumps в evidence не включены, сохранены только выбранные auth/CRL сообщения.
Source/runtime/UI не менялись; действующий backend/frontend ux-log133. Следующий136 — повреждённый и подписанный истёкший CRL. Общая UI-регрессия после133 запущена отдельным процессом, её результат пока не заявляется. Немедленное завершение существующего IKE при отзыве, другие ОС и SLA ещё не приняты;12.5 открыт.
## 12.5.136 — повреждённый и подписанный истёкший CRL в IKE (2026-10-11)
В собственном external-CA tunnel проверены четыре payload на одном certificate-bound CDP: valid DER → HTTP200 malformed text → signed expired DER → original valid DER. Между фазами own cache сбрасывался после certificate/URL ownership preflight, CRL-use/download=yes. Private CA key использован только в0700/0600 временных файлах для подписания CRL, затем удалён. OpenSSL проверил подпись expired DER точным собственным CA; lastUpdate=now−2h, nextUpdate=now−1h. Часы CHR/Debian не менялись.
Оба positive controls установили IKE/ESP, Ping3/3 и API online=true. Malformed payload дал invalid=true caches, AUTHENTICATION_FAILED/established0/API offline. Signed expired payload был распознан RouterOS как invalid=false/expired=true, но новое IKE тоже получило явный AUTHENTICATION_FAILED/established0/API offline. Это четыре уникальные фазы без retry в итоговом запуске; отказ не выводится из сетевого timeout. Per-phase log сохраняет выбранную auth metadata; список expired может содержать earlier malformed reason и не выдаётся за отдельный точный текст причины expiry.
Own certificates/CA/exports/imports/private credentials/Linux containers/network/endpoint/loggers/tunnel config/pool/bridge/address удалены.18 наборов IDs×2 совпали с baseline, CRL settings restored exact, endpoint closed/порт18084 не слушается. Default/public/metadata/195.195.195.195/32/flash directory и пароли сохранены. [Четыре фазы, подпись и cleanup](ux-ui/acceptance/ipsec-malformed-expired-crl-2026-10-11.json); [OpenSSL CRL date options](https://docs.openssl.org/3.0/man1/openssl-ca/).
Source/runtime/UI не менялись, действуют backend/frontend ux-log133. Следующий137 — external revocation при existing IKE и новый handshake. Уже запущенная общая UI-регрессия после133 продолжается; её итог будет отдельным последующим блоком, без объявления успеха заранее. Другие ОС/SLA/часовой refresh/immediate active-session revocation остаются открыты;12.5 открыт.
## 12.5.137 — внешний отзыв сертификата и существующая IKE-сессия (2026-10-11)
Собственный external-CA tunnel подтвердил IKE/Ping3/3. Затем CHR1 отозвал собственный client certificate. Свежий CRL содержит его точный serial, подпись проверена собственным public CA; CHR2 загрузил CA/client cache valid с revoked count1. Новый Linux client получил AUTHENTICATION_FAILED; scoped RouterOS log — «revoked by CRL cert is revoked by crl».
Уже установленная IKE-сессия в коротком наблюдении сохранилась и продолжила Ping3/3. API online=true корректно отражал именно эту старую сессию, а не успех нового handshake. После явного terminate только собственного старого IKE API стал offline; ещё один новый revoked client также получил AUTHENTICATION_FAILED/established0/API offline. Поэтому отзыв/обновление CRL не выдаётся за гарантированное немедленное завершение уже установленного туннеля. [Подпись/serial, старый IKE, два отказа и cleanup](ux-ui/acceptance/ipsec-external-crl-revocation-2026-10-11.json).
Own logger/certificate chains/exports/imports/private credentials/Linux containers/network/tunnel config/pool/bridge/address/HTTP endpoint удалены.18 наборов IDs×2 restored, CRL settings object восстановлен точно, port18084 closed. Default/public/metadata/195.195.195.195/32/flash и пароли сохранены. Source/runtime/UI не менялись; действуют backend/frontend ux-log133. Ключи и crypto dumps в evidence не сохранялись.
Следующий138 — intermediate CA certificate chain. Общая UI-регрессия после133 продолжается и будет принята только по итоговому протоколу. Другие ОС, долгие нагрузки, periodic refresh и немедленное завершение existing sessions ещё не приняты как гарантии;12.5 открыт.
## 12.5.138 — промежуточный CA и повторная аутентификация (2026-10-11)
CHR1 выпустил собственную RSA2048 chain Root CA → Intermediate CA → client. Root/intermediate имеют CA BasicConstraints, leaf — CA=false; обе подписи проверены Node X509, полная цепочка/сроки/constraints прошли OpenSSL verify. CHR2 импортировал три public certificates и загрузил три valid/nonexpired CRL cache через два собственных CDP path. Отдельные native responder CA/server key созданы на CHR2.
Linux strongSwan с собственной client private key, explicit public Root/intermediate trust и точным server certificate pin установил IKE/ESP: Ping3/3/API online=true/конкретный VIP. Reauth завершился успешно, IKE id изменился1→2; новый IKE/ESP снова Ping3/3/API online/VIP. Профиль не менял auth algorithms/правила существующих сетевых операций. [Полная цепочка, CRL, IKE/reauth и cleanup](ux-ui/acceptance/ipsec-intermediate-ca-chain-2026-10-11.json).
Own issuer chain удалена только после доказательства ownership всех descendants/отсутствия references. Own responder/imports/exports/private credentials/Docker client/network/endpoint/loggers/cache/tunnel objects/pool/bridge/address удалены;18 наборов IDs×2 restored, CRL settings restored exact, порт18084 закрыт. Default/public/metadata/195.195.195.195/32/flash directory и пароли сохранены. Source/runtime/UI не менялись; backend/frontend ux-log133.
Принята именно описанная native RSA chain и один Linux client. Arbitrary custom OIDs/policies/path length/missing chain/intermediate revocation/прочие ОС и полная production PKI не приняты. Следующий139 — дождаться итогов текущей общей UI-регрессии, выполнить context/source series и сохранить точный итог с сохранением исходных evidence/screens.12.5 открыт.
## 12.5.139 — общая регрессия, сверка Docker и реальный RIPE (2026-10-11)
После последнего продуктового изменения133 выполнена полная main UI-серия:1244/1244 passed, затем последовательно context/source/backend switch:221/221 passed. Итого1465 уникальных сценариев, оба exit0, без retries/delta rerun. Это production UI code с HTTP mocks/изолированными источниками, а не1465 живых RouterOS операций. Source не менялся во время обеих серий; production build/live UI133 и native135–138 остаются отдельными доказательствами.
С текущих tracked non-test backend/contracts source inputs построен manifest984 emitted outputs. Все984 совпали с actual Docker backend ux-log133 после CRLF→LF; missing0/different0. Старые вложенные local dist/backend/src outputs исключены. Создан input manifest906 файлов, но equality всех raw inputs/воспроизводимость frontend binary этим не заявляются. Нового build не требовалось: runtime source не менялся.
Реальный production RIPE service в отдельном процессе, без чтения/записи рабочего кеша, обогатил194.226.121.150 и104.165.244.7: network-info/maxmind-geo-lite/as-overview200, prefix/ASN/holder/country/coordinates получены. Это provider metadata, не гарантия физического положения хоста и не complete NetFlow pipeline. Дополнительный no-fetch контроль с198.18.139.1 failed: benchmark IPv4 ошибочно отправлен upstream. Private192.168/loopback контроль не вызвал запросов; public cache hits проверяются отдельно в следующем блоке. Этот отказ сохранён, весь RIPE test не объявлен success. [Регрессия, compiled hashes и partial RIPE](ux-ui/acceptance/regression-runtime-ripe-2026-10-11.json).
Перед регрессией сохранены586 existing evidence files.125 автоматически изменённых файлов восстановлены; все исходные SHA256 совпали, включая восемь pre-existing dirty GRE/VXLAN PNG. Новые135–138 evidence не затёрты. Подробные временные logs/snapshots в ignored tmp; побочные generated screenshots не включены в коммит. Source/runtime не менялись; backend/frontend ux-log133. Следующий140 — исправление фильтра специальных IPv4 согласно IANA, профильные backend/flow проверки, build/deploy и повторный live RIPE.12.5 открыт.
## 12.5.140 — специальные IPv4, RIPE и изолированная SQL-приёмка (2026-10-11)
Исправлен isNonPublicIp: benchmark198.18/15, TEST-NET ranges, reserved240/4 и non-global IETF assignments исключены из внешнего RIPE lookup. Глобальные PCP/TURN anycast192.0.0.9/10 сохранены eligible. Фиксированные CIDR masks вычисляются один раз; hot flow predicate больше не разбирает строки CIDR/адреса для каждого range. IPFIX tuples, NAT, network config и DB schema не менялись.31 boundary/exception checks и stale public-cache bypass/no-fetch тесты passed; [IANA](https://www.iana.org/assignments/iana-ipv4-special-registry/).
Local test:traffic-flow (20 scripts) exit0, но шесть SQL modules включали PG skips — не объявлены pass. Все шесть затем проверены against production candidate в четырёх собственных temporary PostgreSQL DBs. Parent создаёт exact own DB, child проверяет current_database до test import, DATABASE_PATH/GEOIP_DIR вынесены в ephemeral container; original DB/legacy SQLite не использовались fixtures. Все четыре DB удалены с owner/prefix check, включая failed runs.
Initial failures сохранены и исправлены в tests: analytics зависел от чужого hardcoded server7 (FK); теперь создаётся own server, все SQL scoped, finally cleanup. Map-hops использовал TEST-NET как вымышленные публичные сервисы; fixtures получили eligible synthetic IPv4, assertions не ослаблены. Statistics не создавал historical server_snapshots partition; теперь создаёт exact fixed-date partition. Ingest/analytics/map-hops/purge/facts-rebuild/statistics SQL modules passed across bounded runs; прошедшие modules без необходимости не повторялись. Mock upstream failure fixture перенесён с TEST-NET на eligible address и явно подтверждает реальный вызов stub.
Changed-file ESLint, backend production build, RIPE/IP profile tests passed. Реальный production RIPE service снова обогатил два публичных IP; повторный public cache hit и special/private controls дают0 дополнительных requests. Действует backend ux-ripe140/frontend ux-log133; backend/PG healthy. Все984 emitted outputs совпали с candidate Docker, actual deployed IP service SHA256 совпал; private rollback env/old image сохранены. [Полные попытки/проверки/границы](ux-ui/acceptance/flow-special-ipv4-2026-10-11.json).
Readonly live traffic/statistics smoke320: rendering200/no overflow/pageerror0. При этом traffic отправил initial requests /api/traffic/servers/srv1 и /interfaces, оба400/id is required; это existing mock-id hydration/catalog gate defect, не часть IPv4 fix и не скрытый success. [Smoke](ux-ui/acceptance/browser-flow-special-ip-2026-10-11.json). Следующий141 — gate live fetch до подтверждённого numeric server id/catalog. IPv6 special ranges — отдельно. Full UI1465 accepted139 до backend-only140; backend/SQL/live delta проверены отдельно, frontend не менялся.12.5 открыт.
## 12.5.141 — подтверждённый каталог перед запросами трафика (2026-10-11)
Исправлен обнаруженный140 initial live defect: details/interfaces requests отправлялись с demo ID srv1 до загрузки реального каталога и получали400. Теперь details, interfaces и SSE ждут positive safe numeric ID, присутствующий в подтверждённом каталоге текущего backend. Смена источника данных лишает старый каталог права запускать запросы; смена периода не сбрасывает выбранный интерфейс. Demo-режим и backend API не менялись.
17 профильных E2E passed: два новых сценария удерживают запрос каталога и проверяют отсутствие любых individual requests до подтверждения, затем успех numeric ID или503 без запросов к серверу; остальные проверяют историю/ошибки/гонки периода/интерфейсов и SSE. Changed-file ESLint и source-only TypeScript passed; production Docker frontend build passed. Runtime frontend ux-traffic141, backend ux-ripe140 сохранён. Private rollback env и предыдущий образ оставлены.
Readonly live /traffic1440 и320: каталог и numeric interfaces200, initial srv1/400 отсутствуют, pageerror0, horizontal overflow нет. [Протокол](ux-ui/acceptance/traffic-confirmed-catalog-2026-10-11.json). Это приёмка начальной загрузки с реальным текущим каталогом, а не полной цепочки NetFlow ingestion/throughput. Сетевые объекты и пароли не менялись. Следующий отдельный блок — IPv6 special registry guard; оставшаяся внешняя приёмка перечислена в матрице.12.5 открыт.
## 12.5.142 — специальные IPv6 и рабочий кеш RIPE (2026-10-11)
Исправлены две причины недостоверного обогащения IPv6: неполная проверка служебных адресов и отсутствие IPv6-поиска в RIPE-кеше. Теперь документальные/benchmark/discard/dummy/SRv6/local/multicast адреса и некорректные записи не запрашивают RIPE, даже при старом seeded metadata. Более конкретные глобальные назначения внутри2001::/23 сохранены; Teredo/6to4 со статусом N/A не объявлены non-global. Правила сверены с [IANA](https://www.iana.org/assignments/iana-ipv6-special-registry/), eligibility не гарантирует маршрутизацию.
Добавлены validated128-bit parser, /48 buckets и отдельные широкие IPv6-префиксы. Lookup выбирает самый точный свежий CIDR, учитывает замену/просрочку/инвалидацию. Отрицательный кеш использует /128 и не затрагивает соседний адрес. Expanded и compressed записи дают одинаковый результат; IPv4-mapped hex/dotted/expanded формы нормализуются к одной IPv4 host identity. Host /128 удаляется перед RIPE resource request. Тест с3000 unrelated /48 подтверждает, что lookup не сканирует их все. Фиксированные special CIDR вычисляются один раз.
Changed-file ESLint, backend production build и IP/RIPE profile tests прошли локально и в candidate. Потребители classification/destination/GeoIP passed. Первый local aggregate остановился на GeoIP из-за ограниченного доступа к temporary files; разрешённый отдельный rerun passed, причина и неуспешный запуск не скрыты. Шесть PG skips локального запуска не считаются успешными: все шесть SQL-модулей затем прошли одним запуском в собственной temporary DB, удалённой с owner check. Working DB и legacy SQLite не использовались fixtures.
Первый Docker запуск указал отсутствующий Dockerfile.backend; исправлен путь backend/Dockerfile, build passed. Все984 emitted production outputs candidate совпали с local build. Реальный RIPE API дал6 HTTP200 для Google и Cloudflare IPv6; cached sibling/expanded address и special/invalid controls дали0 новых requests. Service process отдельный, persistence выключена. Backend ux-ipv6142 развёрнут, /health и Docker health healthy; frontend ux-traffic141 сохранён. Live /traffic1440/320 passed без srv1/400/pageerror/overflow. Rollback env/image сохранены, сетевые настройки и пароли не менялись.
[SQL/live RIPE и границы](ux-ui/acceptance/flow-ipv6-ripe-2026-10-11.json), [browser smoke](ux-ui/acceptance/traffic-ipv6-smoke-2026-10-11.json). Это не доказывает IPv6 WAN connectivity или полный exporter→ingest→SQL→UI pipeline. При live RIPE выявлены координаты0/0 для Cloudflare; следующий143 — проверить, не подменяются ли отсутствующие значения нулями. Далее — IPv6 flow pipeline.12.5 открыт.
## 12.5.143 — неизвестные координаты RIPE без ложной точки на карте (2026-10-11)
При real RIPE IPv6 acceptance142 Cloudflare получил координаты0/0 после ответа upstream с country=? и latitude/longitude=0. Эти данные не подтверждают положение узла. Исправлен pickGeo: принимается только полная пара finite numeric coordinates в диапазонах±90/±180; empty strings, boolean, numeric strings, missing/partial/out-of-range coordinates дают null pair. Unknown-country0/0 также даёт null. Действительный ноль на экваторе/меридиане и явно заданный known-country0/0 сохраняются. ASN country fallback не превращает неизвестную точку в подтверждённые координаты.
16 новых end-to-end service cases в RIPE profile прошли локально и в production candidate. ESLint, backend build,984 compiled outputs comparison passed. Три затронутых SQL-потребителя (analytics, map-hops, facts-rebuild) прошли в собственной temporary PostgreSQL DB; она удалена с owner check, working DB не использовалась fixtures. Real RIPE снова дал6 HTTP200 для Google/Cloudflare IPv6. Upstream unknown-country0/0 сохранён в протоколе вместе с service lat/lng=null, ASN/country retained. Cache controls не сделали новых queries.
Backend ux-geo143 развёрнут, health healthy, frontend ux-traffic141 сохранён; read-only traffic PC/mobile smoke выполнен отдельно. Rollback env/image сохранены. [Полный протокол](ux-ui/acceptance/ripe-unknown-coordinates-2026-10-11.json), [browser smoke](ux-ui/acceptance/traffic-geolocation-smoke-2026-10-11.json), [RIPE API](https://stat.ripe.net/docs/data-api/api-endpoints/maxmind-geo-lite).
Unknown0/0 policy основана на наблюдённом live ответе, а не на заявлении о поведении всех providers. Старые persisted entries с уже потерянной raw provenance не переписываются: исправлены новые fetches, прошлый cache живёт по прежнему TTL. Изменений schema/UI/theme или настроек CHR нет, пароли не менялись. Полная физическая точность геолокации и licensed GeoLite2 file acceptance не заявляются. Следующий144 — реальный IPv6 IPFIX UDP→collector worker→SQL в изолированной БД.12.5 открыт.
## 12.5.144 — IPv6 IPFIX через UDP, production worker и PostgreSQL (2026-10-11)
Новый controlled dual-stack IPFIX fixture воспроизвёл реальный parser defect: zero IPv4 placeholders заменяли уже прочитанный IPv6 или блокировали последующее IPv6 field. Исправлены source/destination поля в обоих порядках: usable IPv4 сохраняет прежний приоритет, zero IPv4 не подменяет usable IPv6. Expanded unspecified IPv6 теперь распознаётся так же, как ::, включая NAT fallback. Новая проверка добавлена в test:traffic-flow; parser assertions исполняются всегда, UDP/SQL часть требует exact own MMAPP_OWN_TEST_DB/current_database before migrations, иначе явно skip.
21 local traffic-flow scripts exit0; existing6 PG modules и UDP own-DB часть имели явные skips и не объявляются pass. Changed-file ESLint и backend production build passed. Candidate984 emitted outputs matched. Затем в own temporary PostgreSQL DB запущен настоящий production collector worker с UDP loopback socket: отправлены template и data datagrams, приняты6 IPv6 flows с forward/reverse public peers и documentation/benchmark/multicast controls. Проверены каждый src/dst, bytes/packets; raw/minute сохраняют все25200B/42 packets. Hour/day Internet facts по существующим правилам включают только три public flows:7200B/12 packets. Worker dropped0/error0, graceful shutdown acknowledged; SQL totals проверены после flush.
Две initial fixture failures сохранены: в первом запросе использовались неверные SQL column names src_ip/dst_ip (actual src/dst); во втором ожидалось равенство all traffic и Internet facts, что противоречит существующим правилам. Исправлены только ожидания/запрос теста, assertions каждого адреса/объёма не ослаблены, production aggregation/filter/schema не менялись. Third attempt passed. Все3 own temporary DBs удалены с owner check; working DB и legacy SQLite fixtures не использовались.
Backend ux-ipfix144 развёрнут, health healthy; frontend ux-traffic141 сохранён. Live traffic1440/320 passed без initial srv1/400, page errors/overflow. Rollback env/image оставлены. [Все попытки и границы](ux-ui/acceptance/ipv6-ipfix-worker-sql-2026-10-11.json), [browser smoke](ux-ui/acceptance/traffic-ipfix-smoke-2026-10-11.json).
Это real UDP/worker/SQL path с синтетическим exporter через IPv4 loopback transport, не native RouterOS IPv6 export/outer transport и не maximum throughput. CHR configuration/passwords не менялись. Следующий145 — проверить возможность native RouterOS IPv6 exporter и populated API/UI на собственных objects/DB.12.5 открыт.
## 12.5.145 — настоящий RouterOS IPv6 IPFIX и заполненный интерфейс (2026-10-11)
Оба CHR доступны с прежними credentials, RouterOS7.24.5. Исходно Traffic Flow disabled/targets empty. Созданы собственные GRE-пара с allow-fast-path=false и fd00:145:1::1/2/64, advertise=no. CHR1 временно экспортирует IPFIX только своего GRE, с short timeouts/one owned target. Native Ping прошёл5/5 в обе стороны; CPU/input-output path и IPv6 support сверены с [официальным Traffic Flow manual](https://manual.mikrotik.com/docs/diagnostics-monitoring-and-troubleshooting/traffic-flow/), версия manual7.26, фактическая проверка7.24.5.
На Debian запущен отдельный application/production collector worker в own temporary PostgreSQL DB. Скопирована конфигурация только CHR1 без публикации credentials; worker слушает UDP48145, HTTP API доступен только через localhost18145/SSH. Native RouterOS sender, не synthetic fixture, передал IPv6 IPFIX records: production API содержит реальные ULA source/destination и positive bytes/packets. Deployed frontend ux-traffic141 проверен через явный relay реальных ответов отдельного backend: Sessions DOM содержит IPv6, PC1440/mobile320 API200/pageerror0/no document overflow. Screenshots сохраняют frame/current scroll position, не все строки одновременно. Initial UI attempts искали адрес на Applications summary и ошибочно выбирали button вместо actual tab; исправлено только обращение к существующей вкладке.
Тест не использовал main DB для seeded fixtures; обычный background polling главного приложения оставался активным, поэтому абсолютное отсутствие background writes не заявляется. IPsec/WireGuard keys, пароли, исходные public/default/metadata routes не менялись. Native objects/GRE/IPv6 inputs принадлежат одному unique tag.
Автоматическая очистка восстановила Traffic Flow и удалила objects CHR1, но GET собственного GRE по ID на CHR2 вернул401. Child drain прошёл, own DB удалена. Read-only resource и полный каталог обоих CHR снова доступны с теми же credentials; причина одиночного GET401 не установлена, пароль не менялся. Recovery по свежему полному каталогу проверил exact comment/name/local-remote/address и отсутствие IDs в baseline; удалены только два оставшихся objects CHR2 обычным DELETE. Все12 collection projections×2 и Traffic Flow/IPFIX fields/IPv6 settings совпали с исходными. Initial failure и recovery сохранены, не заменены гладким success.
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 открыт.
## 12.5.147 — подтверждённые HTTP данные аналитики и месяца (2026-10-11)
HTTP analytics/monthly раньше принимались как typed JSON без runtime schema check: malformed200 с отсутствующей conversationsList мог упасть при render. Теперь reused existing contract schemas и flowConfirmed error state, как в SSE/settings. Неверные required fields и negative RX/TX series отклоняются; monthly.month обязан совпадать с requested month. Existing Alert/Повторить аналитику показывает понятную ошибку, retry сохраняет server/range/month. Никаких false zero defaults для отсутствующих обязательных данных.
Необязательные overlay/wire measurements могут быть неизвестны отдельно от основных счётчиков. Invalid optional numbers (missing/null/string/negative/nonfinite) нормализуются в undefined, UI сохраняет Нет данных; legitimate numeric0 и valid core остаются. Это сохраняет partial-data UX и прежнюю проверку, вместо объявления всего DTO недоступным. Contract schemas/backend response shapes не менялись.
34 профильных E2E приняты across attempts:31 passed в первом запуске; strict optional metric rejection и два monthly fixtures без server catalog дали3 failures. Исправлены partial metric handling и fixtures, повторены только эти3, все passed. Covered incomplete analytics/monthly, negative series, different month, no pageerror/no false speed, retry with identical scope, existing flow races/SSE/metrics/month/table and IPv6 labels. ESLint/source-only TypeScript/frontend Docker build passed. [Receipt](ux-ui/acceptance/traffic-http-contracts-2026-10-11.json).
Frontend ux-http147 развёрнут, backend ux-labels146 сохранён. Настоящие analytics/monthly HTTP200 текущего backend прошли схемы; month2026-10 совпал с запросом. [Live PC/mobile smoke](ux-ui/acceptance/traffic-http-validation-smoke-2026-10-11.json). Это contract compatibility/read-only smoke с текущими lab data, не новый populated WAN test. Rollback image/env сохранены, device/password changes нет.
Следующий148 — не запускать scoped flow HTTP/SSE до подтверждённого выбранного элемента каталога и не превращать malformed serverId в aggregate request.12.5 открыт.
## 12.5.148 — подтверждённый срез потоков без агрегатной подмены (2026-10-11)
Исправлено продолжение initial srv1 defect для flow mode. Scoped analytics/SSE теперь ждут выбранный элемент current provider/range/scope catalog. Server ID обязан быть positive safe numeric и присутствовать в exporters/monthly catalog, user ID — в confirmed clients. Catalog pending/error не запускает запрос для guessed/old selection; analytics loading не висит после catalog failure. Monthly history сохраняет supported non-exporting/disabled catalog entries, device polling не добавлено.
Backend больше не извлекает numeric prefix из1suffix и не превращает srv1/invalid/unsafe IDs в omitted filter/all-servers aggregate. Возвращается400 Некорректный идентификатор сервера. Missing/empty optional filter сохраняет aggregate semantics. Query validation выполняется до acquisition MAX4 SSE slots, поэтому malformed requests не съедают live quota.
21 invalid query cases (7 IDs×analytics/monthly/live) прошли source/candidate; full4 slots остались доступны. Новый тест сначала импортировал несуществующий non-scoped package; исправлен на existing @fastify/type-provider-zod без установки dependencies, проверки затем passed. Backend test включён в обычную traffic-flow series.36 E2E одним запуском passed: delayed/error catalog без any scoped request, затем only confirmed id1; existing flow/SSE/races/month/DTO/IPv6 labels. ESLint/source-only types/both production builds и984 emitted backend outputs comparison passed.
Backend/frontend ux-scope148 развёрнуты, health healthy. Real API9 malformed cases400 и2 valid scoped cases200; [receipt](ux-ui/acceptance/flow-scoped-query-2026-10-11.json), [PC/mobile readonly smoke](ux-ui/acceptance/traffic-flow-scope-smoke-2026-10-11.json). No native changes/password changes/schema/theme changes; rollback env/images сохранены. Populated native145 не повторялся без необходимости.
Следующий149 — строгий month input и calendar bounds: invalid month не должен подменяться текущим или выдаваться за подтверждённый zero report.12.5 открыт.
## 12.5.149 — календарный месяц без тихой подмены и ложных нулей (2026-10-11)
Supplied malformed month раньше подменялся current UTC month на route; impossible month мог вернуться из service как zero report. Теперь непустой параметр передаётся для strict YYYY-MM/month1..12/year!=0000 validation, invalid получает400 Некорректный месяц отчёта до SQL. Missing/empty optional month сохраняет прежний current UTC default. Runtime non-string тоже отклоняется.
Calendar bounds больше не используют Date.UTC дляyear1..99 (он превращает их в1901..1999) и не режут extended ISO date at year10000. Integer year/month arithmetic даёт exact next-month day1, average bps используют Gregorian month length/leap rule. Source tests проверяют нормальный month/year rollover,1/99/9999, invalid input rejection before SQL. Normalized labels/DB schema не менялись.
В candidate Docker5 SQL intervals прошли в own temporary PostgreSQL DB:0001 January,0099 December,1900 February28days,2000 February29days,9999 December/end10000. In-month1200B retained, next-month12000B excluded, average country bps matches exact month length. Fixture DDL выполняется только после exact own DB/current_database check, DB удалена с owner check; working DB/legacy SQLite не использовались fixtures. Both month and scoped-query tests добавлены в normal traffic-flow series. ESLint/backend build/984 output comparison и6 frontend scoped/context tests passed; frontend не пересобирался.
Backend ux-month149 развёрнут, frontend ux-scope148 сохранён, health healthy. Real API6 invalid months400 иcorrect2026-10→200/same month; initial smoke helper Fetch.status method typo исправлен только в harness, сохранён как setup error. [Full SQL/live receipt](ux-ui/acceptance/flow-month-calendar-2026-10-11.json), [PC/mobile smoke](ux-ui/acceptance/traffic-month-calendar-smoke-2026-10-11.json). Device/password changes нет, rollback retained. Это не расширяет UI на future month selection.
Следующий небольшой150 — понятные подписи Sessions columns вместо App/Proto/Iface/JH/EN, сохраняя ReUI grid/Frame/base-nova/data semantics.12.5 открыт.
## 12.5.150 — понятные названия колонок сессий (2026-10-11)
Существующая ReUI Sessions grid получила ясные подписи вместо внутренних сокращений:
| Было | Стало |
| --- | --- |
| JH | Экспортёр |
| EN | Выходной узел |
| App | Приложение |
| Proto | Протокол |
| Iface | Интерфейс |
| Напр. | Направление |
| Download / Upload (tooltip) | Получение / Отправка |
Column IDs, accessors, sorting/filtering, row values, direction meanings, grid layout/Frame/base-nova/vendor не менялись. Экспортёр описывает serverName корректнее, чем JH: данные могут поступать с разных типов устройств. IPv6 bracket/ICMPv6 labels146 сохранены.
Existing viewport1440/320 cases passed: endpoint/tooltip/IPv4/ICMPv6 behaviour иno document overflow. ESLint passed. Первый types check совпал с Next dev записью generated routes.d.ts и прочитал незавершённый файл; после окончания E2E/webserver TypeScript повторён последовательно и passed без изменения source. Production frontend build passed. Frontend ux-sessions150 развёрнут, backend ux-month149/PG healthy; [receipt](ux-ui/acceptance/flow-sessions-column-labels-2026-10-11.json), [readonly PC/mobile smoke](ux-ui/acceptance/traffic-sessions-labels-smoke-2026-10-11.json). Rollback image/env сохранены. Network/password/device/schema changes нет; populated native145 не повторялся для copy-only delta.
Окно завершает coherent группу IPv6/NetFlow142–150. Следующий151 — application GRE IPv6 address lifecycle. Native inner proof109/145 уже есть, но gre-live читает только /ip/address, а entity-snapshots create/restore/delete всегда используют IPv4 resource. Нельзя просто объединить IPv6 catalog без family-safe write/delete paths: одинаковые ROS IDs в разных namespaces и dynamic link-local требуют отдельной обработки. План151: static IPv6 catalog, family-aware paths, create/update/restore/delete+legacy snapshot compatibility, запрет неоднозначной смены primary при multiple addresses, profile/native own tunnel cleanup иUI metadata. Сначала проверить лимит; не выпускать partial family migration.12.5 открыт, public IPv6 WAN/outer и внешние integrations остаются в матрице.
## 12.5.151 — управление статическими IPv6-адресами GRE (2026-10-11)
GRE читает IPv4 и IPv6 адреса; динамические адреса исключены из управления. Ошибка любого address catalog или неверный формат ответа останавливает чтение/запись, неполный ответ не становится пустым снимком. Выбранный выключенный сервер также исключён из опроса.
Create/PATCH/restore/delete выбирают /ip/address или /ipv6/address по проверенному CIDR; одинаковый RouterOS ID в разных семействах безопасен. Новые снимки содержат все статические адреса, disabled/advertise/comment/no-dad. PATCH меняет только целевой GRE, сохраняет дополнительные адреса; очистка поля передаёт явную пустую строку. Восстановление старой ревизии при нескольких текущих адресах возвращает409 до записи. Неоднозначные ID/name и переименование также409. Expanded/compressed IPv6 сравниваются по одному ключу. Применение from-pool/EUI-64 остановлено с объяснением: их выделение не принимается за обычный literal static address.
Существующие ReUI/Frame/base-nova сохранены, добавлена подсказка IPv4/IPv6 с префиксом. Проверки: config-sync4 scripts (включая14 invalid POST/PATCH до DB/REST), gre-comment и selected-context tests; backend/source-only types/ESLint;15 GRE E2E; backend/frontend production builds;984 emitted outputs совпали. Первый E2E запуск не стартовал из-за sandbox Windows/SWC canonicalize access; разрешённый повтор прошёл.
Настоящие production Fastify handlers + выделенная PG база + оба CHR:18 API requests включая создание IPv6 пары, PATCH IPv6, сохранение дополнительных IPv4/disabled IPv6, history restore многoадресного снимка, legacy409 и ID/name409, смену IPv6→IPv4, очистку, восстановление и DELETE. Ping3/3 в обе стороны после running=true и address invalid=false. Первоначальный короткий Ping получил0 вместо ожидаемых3 и остановил первый сценарий; причина не доказана. Его результат и очистка сохранены отдельно, повтор не скрывает начальный отказ. Это короткий dataplane, не доказательство бесшовности/throughput.
Оба запуска: собственные объекты удалены,8 static collections×2 совпали с baseline, отдельные базы удалены. Пароли не менялись, public/default routes не трогались. Native parent читает исходные enabled server credentials; background polling главного приложения продолжался, отсутствие всех background SQL writes не заявляется. Runtime backend/frontend ux-gre151 healthy, live read-only PC/mobile catalog/form smoke прошёл после cleanup; native mutation принята через изолированную базу, deployed browser mutation не выполнялась.
Протоколы: [native/cleanup](ux-ui/acceptance/gre-ipv6-native-2026-10-11.json), [API/history](ux-ui/acceptance/gre-ipv6-api-history-2026-10-11.json), [первый запуск](ux-ui/acceptance/gre-ipv6-initial-cleanup-2026-10-11.json), [compiled parity](ux-ui/acceptance/gre-ipv6-compiled-2026-10-11.json), [live UI](ux-ui/acceptance/gre-ipv6-smoke-2026-10-11.json).
Границы: IPv6 ULA inner по IPv4 GRE outer; IPv6 outer/public WAN, scale, длительное восстановление и from-pool/EUI-64 не приняты. Полная регрессия после139 не повторялась: выполнен профиль изменённых областей. Следующий152 — WireGuard IPv6 lifecycle;12.5 остаётся открытым.
## 12.5.152 — IPv6 lifecycle WireGuard и общий допуск выключенных серверов (2026-10-11)
WireGuard читает оба address catalogs; ошибки/не-массивы не превращаются в пустые данные. Catalog показывает активный статический адрес, новые snapshots сохраняют все статические адреса с disabled/advertise/comment/no-dad. Dynamic link-local исключён из управления. Create и PATCH address, history restore и delete выбирают семейство по CIDR; дополнительные адреса сохранены, legacy snapshot с несколькими текущими адресами409. Общий адресный planner переиспользован GRE/WireGuard; constructor alias GreRestoreConflict совместим. PATCH не переименовывает одновременно интерфейс и адрес.
Import подтверждает receipts в /ip/address и /ipv6/address раздельно, normalized IPv6 identities принимаются, automatic link-local не считается чужим static child. Lost/unconfirmed receipt не разрешает удаление по одному имени; rollback не удаляет IPv4 с совпавшим IPv6 ID. IPv6 RSC export использует /ipv6 address add +advertise=no, parser распознаёт IPv6 address line. Multiple/special address import и export явно отклоняются вместо тихой потери данных. Это single-address literal import/export, не произвольный RouterOS configuration codec. Существующий ReUI create sheet получил подсказку IPv4/IPv6; структура/Frame/base-nova сохранены.
При native приёмке обнаружено: getEnabledServerById ранее проверял только ID. Теперь общий getter допускает только enabled=true и полный корректный DB ID; WireGuard selected catalog также исключает disabled. Это влияет на использующих getter GRE/WireGuard/firewall/containers/traffic/overlay. Постоянный opt-in test network-disabled-server.test.ts делает33 API/SQL cases: три типа Home Router/Jump Host/Exit Node ×11 calls, factory любого ROS client запрещена, contacts=0, enabled positive control проходит.8 malformed IDs проверяются до SQL, включая unsafe/выход за integer DB range. Без MMAPP_OWN_TEST_DB SQL часть честно skipped; в собственном PG стенде выполнена и база удалена.
Проверки:56 node:test cases import/rollback/revision/delete, service/config/HTTP scripts, GRE config-sync и14 invalid GRE requests, containers/live-maps profiles;10 E2E (WireGuard IPv6/error-retained input PC/mobile, tables/menus и GRE smoke после общего planner), source types/ESLint; обе production сборки,984 emitted outputs совпали с окончательным backend.
Native изолированная PG + production handlers + оба CHR:29 API cases, native handshake0s и Ping3/3 в обе стороны после IPv6 invalid=false; create/PATCH/IPv6→IPv4/clear, multiple-address history restore, legacy409, export multiple409, RSC/conf single IPv6 export и реальный import/delete, disabled GET empty/PATCH404 с forbidden factory. После каждого запуска9 static collections×2 совпали, собственные интерфейсы/peers/адреса и PG базы удалены. Native source/cleanup не меняли пароли/public/default routes. Background polling главного приложения продолжался; отсутствие всех background SQL writes не заявляется.
Первый сценарий остановился из-за ошибки теста: ожидал200 от POST peer, фактический корректный201. После исправления сценарий прошёл весь native lifecycle, но завершающий disabled PATCH вернул500 из-за реального дефекта общего getter. Оба отрицательных протокола сохранены; getter исправлен,33 isolated API/SQL cases и полный native сценарий на финальном образе прошли. Frontend повторно не собирался из-за backend-only gate delta.
Runtime backend/frontend ux-wg152 healthy; deployed live read-only catalog/create-sheet на1440/320 passed после cleanup. Browser mutations покрыты controlled E2E, реальные RouterOS mutations — production handlers в выделенной базе. IPv6 ULA inner по IPv4 WireGuard outer, не IPv6 public WAN/client OS/throughput/scale/lost ACK physical acceptance. From-pool/EUI-64/multiple-address import/export остаются явными ограничениями; full regression после139 не повторялась.
Протоколы: [native/cleanup](ux-ui/acceptance/wireguard-ipv6-native-2026-10-11.json), [API/history/import/export](ux-ui/acceptance/wireguard-ipv6-api-history-2026-10-11.json), [33 SQL/API gates](ux-ui/acceptance/network-disabled-sql-2026-10-11.json), [до исправления getter](ux-ui/acceptance/wireguard-ipv6-before-gate-api-2026-10-11.json), [compiled](ux-ui/acceptance/wireguard-ipv6-compiled-2026-10-11.json), [live UI](ux-ui/acceptance/wireguard-ipv6-smoke-2026-10-11.json).
Следующий153 — sustained OSPF/BFD-only gate и recovery на собственных GRE;12.5 остаётся открытым.
## 12.5.153 — граница OSPF/BFD и предупреждение конфликта состояний (2026-10-11)
В существующей OSPF странице ReUI/Frame/base-nova добавлено предупреждение последнего опроса: OSPF Full при наблюдаемом BFD Down/AdminDown. Correlation требует точный server/interface/neighbor IP, explicit active/useBfd=true, одну direct multihop=false BFD session и свежие данные; чужое устройство/интерфейс/peer, duplicate sessions, unknown/multihop/inactive/non-BFD template не создают вывод. Native Full/route states и правила RouterOS не меняются. Переход Проверить BFD сохраняет server/node context и атомарно снимает search, чтобы найденная сессия была видна. Референс остаётся существующий ReUI Data Grid/Frame, новые vendor components не устанавливались.
На обоих CHR собственные GRE198.18.153.0/30 и OSPFv2 loopbacks198.18.253.1/32↔2/32, hello1s/dead20s, BFD200ms×3. Два own firewall правила на CHR2 блокировали только UDP3784 input/output на own GRE с exact private src/dst. Protocol89/ICMP не блокировались; OSPF Hello отдельным packet capture не измерялся.51 native rounds около30s: BFD Down наблюдался, в поздних samples после20s оба OSPF neighbors Full и own route active. Это подтверждает отсутствие гарантированного постоянного route gate при BFD-only ACL loss; непрерывность каждого пакета/мгновенного состояния не заявляется. Data plane initial/fault/recovery Ping3/3×2. После удаления fault — BFD Up/Full/active, затем собственные firewall/OSPF/BFD/IP/bridge/GRE objects удалены.10 static collections×2 совпали с baseline; filter/BFD config order также сравнивался. Default/public routes и пароли сохранены.
UI native positive проверена в source Next dev3133 с настоящим backend8000, без JSON mocks и browser mutations:1440/320 показывают alert+native Full; переход ведёт к реальному Down, сохраняет server и очищает q. Скриншоты [1440](ux-ui/screens/ospf-bfd-conflict153-1440-2026-10-11.png), [320](ux-ui/screens/ospf-bfd-conflict153-320-2026-10-11.png); мобильный экран визуально проверен.3 unit cases,9 controlled E2E с recovery/foreign/non-BFD/unknown и previous data-cache scenarios, source types/ESLint passed. Read-only deployed PC/mobile smoke после cleanup подтвердил отсутствие ложного alert.
Frontend production build прошёл с окончательным source context; frontend ux-ospf153 развёрнут, backend ux-wg152/PG healthy. Первоначальная SCP сессия истекла в ожидании пароля; первый frontend candidate был собран без delta и не развёртывался. Context пересинхронизирован/хеш проверен, финальная сборка повторена и принята. Backend code/build не менялись, broad regression не повторялась. Только собственный завершённый container6a521d… удалён после exact-ID/state check; background main polling продолжался, собственная SQL база не создавалась.
Правила конфигурации сверены с [MikroTik BFD](https://manual.mikrotik.com/docs/user-guides/routing-and-networking-protocols/unicast/bfd/). Протоколы: [native51 samples/recovery/cleanup](ux-ui/acceptance/ospf-bfd-sustained-2026-10-11.json), [real source UI](ux-ui/acceptance/ospf-bfd-live-source-2026-10-11.json), [deployed smoke](ux-ui/acceptance/ospf-bfd-deployed-smoke-2026-10-11.json).
Границы: sustained BFD-only gate не гарантирован на RouterOS7.24.5; программа показывает реально наблюдаемый конфликт и не навязывает новые network rules. IPv6/scale/independent WAN/continuous packet loss/SLA не приняты этим блоком. Следующий154 — OSPFv3 IPv6 routes; существующий catalog читает только /ip/route, требуется family-safe /ipv6/route.12.5 открыт.
## 12.5.154 — IPv6 маршруты OSPFv3 в API и интерфейсе (2026-10-11)
Каталог и selected/all OSPF reads получают /ip/route и /ipv6/route. Обе коллекции обязательны: ошибка/не-массив не становятся успешным пустым ответом. IPv6 rows имеют namespace ipv6: для native ID: одинаковые IPv4/IPv6 IDs не конфликтуют. IPv4 IDs сохранены, операция только чтения. Gateway parser предпочитает фактический nonblank immediate-gw, затем configured gateway; это сохраняет наблюдаемый интерфейс после %. Существующие ReUI tables/Frame/base-nova не менялись.
Backend build, config-sync, live-maps profiles (dual family ID collision, IPv6 read failure/malformed payload, link-local gateway/via, existing disabled/partial/unknown),9 OSPF data/cache/BFD E2E и984 compiled parity passed. Backend ux-ospf154 развёрнут с rollback copy; frontend ux-ospf153 сохранён, PG/backend healthy. Native проверка выполнена после profile/parity deployment на disposable lab; frontend/backend неподтверждённый candidate не публиковался.
На обоих CHR собственный GRE IPv4 outer, IPv6 link fd00:154:1::1/64↔2/64, loopbacks fd00:154:ff::1/128↔2/128, OSPFv3 router IDs198.18.254.1↔2. Interface templates принадлежат только own GRE/loopback, originate-default=never, use-bfd=no; public/default paths не менялись. Native neighbors Full и own learned IPv6 route active, Ping3/3×2. Catalog/selected API содержат ровно соответствующие remote loopbacks с ipv6: ID и actual link-local nextHop +own GRE via.4 production UI cases: оба устройства на1440/320, IPv6 prefix/family row ID/gateway/interface присутствуют в DOM, document overflow/page errors0. На mobile отдельные columns могут находиться в горизонтальном table scroll; все columns одновременно viewport-visible не заявляются.
Координационный harness ожидал ui.done180s и завершился exit1 до позднего сигнала. Исходный passed=false/timeout сохранён: не переписан на успех и не скрыт повтором. Это не API/OSPF/Ping отказ: соответствующие assertions и4 независимых реальные UI cases прошли. finally удалил own OSPF/GRE/bridge/IPv6 objects,13 static collections×2 совпали с baseline, включая IPv4/IPv6 routes/filter/ND. Background main polling продолжался; собственная SQL fixture база не создавалась. Пароли сохранены, оба CHR доступны. Остановленный own container удаляется только по точному ID/state, не по широкому filter.
Протоколы: [native и timeout/cleanup](ux-ui/acceptance/ospfv3-native-2026-10-11.json), [4 real UI](ux-ui/acceptance/ospfv3-live-ui-2026-10-11.json), [compiled984](ux-ui/acceptance/ospfv3-compiled-2026-10-11.json). Конфигурация сверена с [официальным OSPF](https://help.mikrotik.com/docs/spaces/ROS/pages/9863229/OSPF).
Границы: IPv6 ULA inner по IPv4 GRE outer, single area/single path, BFDv6 выключен, IPv6 public WAN/outer, scale/interop/throughput/physical redundancy не приняты. Full orchestration script success не заявляется; production behavior/profile и независимые native/UI/cleanup proofs отделены от timeout. Следующий155 — BGP IPv6 session/NLRI;12.5 открыт.
## 12.5.155 — IPv6 BGP session и обмен NLRI (2026-10-11)
Без изменения production source/dependencies/build: на двух CHR созданы собственные GRE с IPv6 link fd00:155:1::1/64↔2/64, loopbacks fd00:155:ff::1/128↔2/128, private AS64555↔64556, afi=ipv6. Output.network использует own /ipv6/firewall/address-list. Input/output filters принимают только точный own/remote /128, default-originate=never и network-blackhole=no. Native sessions Established, каждый узел получил ровно1 собственный remote IPv6 prefix; initial/recovery Ping3/3 в обе стороны.
Catalog и selected API подтвердили Established и IPv6 peerIp. Administrative disable одной own connection снял own active IPv6 route на другом узле, первое наблюдение144ms после PATCH — не hold-timer/SLA. Enable вернул sessions/routes/Ping. Read-only production UI1440/320 показал обе IPv6 сессии/Established в DOM, document overflow/page errors0; горизонтально скрытые mobile columns не выдаются за одновременно видимые. [Live UI](ux-ui/acceptance/bgp-ipv6-live-ui-2026-10-11.json), [native/withdrawal/recovery](ux-ui/acceptance/bgp-ipv6-native-2026-10-11.json).
Первый harness проверял отсутствующее поле remoteAddress, тогда как public API контракт использует peerIp. Он остановился после успешных native route/Ping assertions;11 baseline collections×2 восстановлены. Failure сохранён [отдельно](ux-ui/acceptance/bgp-ipv6-initial-2026-10-11.json). Исправлен только ignored test helper; полный второй сценарий exit0. Own BGP/filter/address-list/IPv6/bridge/GRE objects удалены,11 static collections×2 совпали, filter order также сохранён. Обе завершённые собственные container identities проверены и удалены; пароли/public/default routes не менялись. Background main polling продолжался, SQL fixture база не создавалась.
Конфигурация сверена с [официальным BGP connection/AFI](https://manual.mikrotik.com/docs/cli-reference/routing/bgp/connection/) и [IPv6 address lists](https://manual.mikrotik.com/docs/firewall-and-quality-of-service/firewall/address-lists/). Границы: IPv6 BGP transport/NLRI внутри GRE по IPv4 public outer, два собственных peers/single path. Это не IPv6 public WAN/outer, independent WAN, external peer interoperability, BFDv6, continuous packet loss/maximum throughput/scale acceptance. ReUI/Frame/base-nova и runtime backend ux-ospf154/frontend ux-ospf153 сохранены.
Следующий156 — общая UI/context regression после151–154, один проход с сохранением исходных изображений;12.5 открыт.
## 12.5.156 — bigint идентификаторы серверов и начало общей регрессии (2026-10-11)
Audit actual schema обнаружил, что servers.id и references — PG bigint с Drizzle mode:number. В152 ошибочно введён верхний предел2147483647; это не диапазон данной DB схемы. Ограничение удалено, общая parseDbServerId требует positive safe integer и полную decimal строку. IDs2147483648 и Number.MAX_SAFE_INTEGER сохраняются точно;9007199254740992/3 и прочие unsafe/malformed не округляются в другой сервер. Историческая запись152 отражает прежнюю ошибочную границу; этот блок её исправляет.
Permanent server-id.test.ts проверяет25 valid/invalid forms без SQL. Dedicated PG test сохранил33 API checks disabled Home/Jump/Exit с forbidden ROS factory/contacts0, enabled control и2 реальные positive bigint rows. Guards MMAPP_OWN_TEST_DB152/156/current_database выполнены до bootstrap; собственная база удалена. Локальные config-sync/live-maps profiles и production backend build passed;984 emitted files совпали. Backend ux-id156 развёрнут, frontend ux-ospf153 сохранён. Native devices не изменялись этим блоком.
Протоколы: [SQL/33 guards/2 bigint controls](ux-ui/acceptance/network-bigint-sql-2026-10-11.json), [compiled984](ux-ui/acceptance/network-bigint-compiled-2026-10-11.json). ReUI/Frame/base-nova/контракты UI сохранены, frontend build без source delta не повторялся.
Однократная общая UI regression запущена:1260 main cases.348 текущих tracked screen files, включая8 preexisting user-dirty GRE/VXLAN изображений, сохранены с SHA256 в ignored tmp/regression156-originals. На checkpoint774 cases ошибок не наблюдалось; это не завершённая приёмка всего прогона. Source screenshots могут временно меняться тестами и должны быть восстановлены исходными bytes после main/context. В157 дождаться основного процесса, выполнить221 context cases одним sequential server session, восстановить348 файлов, выполнить types/checks и записать точные exits/failures. Не выдавать running/skipped за pass.12.5 открыт.
## 12.5.157 — общая регрессия после IPv6 и bigint исправлений (2026-10-12)
Однократный основной прогон завершён: **1260 UI-сценариев прошли**, exit0. Затем в отдельной последовательной frontend-сессии прошли **221 проверка контекста**, exit0; всего 1481 сценарий, без сложения повторных профильных прогонов. Полная команда backend test завершилась exit0: все **24 профиля**, входящие в эту команду, прошли. Это не число отдельных assertions. Первоначальный sandbox-запуск остановился в probes.cancel из-за EACCES на локальном HTTP listener; исходный лог сохранён, полный повтор с разрешённым доступом прошёл. Проверки собственной PostgreSQL базы и bigint rows относятся к156, этим общим прогоном повторно не заявляются.
Source TypeScript прошёл после остановки тестового Next dev. Все348 tracked изображения восстановлены из сохранённых перед прогоном текущих bytes, каждое сверено по SHA256; сохранены в том числе8 пользовательских GRE/VXLAN изменений. Сгенерированные тестами изображения не заменяют согласованные референсы. Production source не менялся, образы ux-id156/ux-ospf153 повторно не собирались и не развёртывались. RouterOS конфигурация и пароли этим блоком не изменялись.
Протокол: [регрессия157](ux-ui/acceptance/regression-157-2026-10-12.json). Это локальная контролируемая регрессия интерфейса/контекста/backend, а не повтор native сценариев или приёмка внешних сервисов, клиентских ОС, масштаба и физических WAN. Исторический timeout orchestration154 остаётся в исходном протоколе. Этап12.5 открыт; следующий158 — проверка эквивалентных IPv6 адресов в сопоставлении OSPF/BFD.
## 12.5.158 — корректное сопоставление IPv6 OSPF и BFD (2026-10-12)
Строковое сравнение не связывало эквивалентные IPv6 адреса: например FE80:0000:0000:0000:0000:0000:0000:0002 и fe80::2. Теперь IPv6 приводится к канонической записи, optional zone должна совпадать с наблюдаемым интерфейсом. Hostnames, malformed IPv4/IPv6, пустая/чужая/повторная zone не создают совпадение. Stale duplicate с тем же точным device/interface/peer не исключается до проверки уникальности: наличие такой неоднозначности подавляет предупреждение. Single stale session также не доказывает конфликт. Это только корреляция наблюдений; состояния RouterOS и правила сети не менялись.
5 unit tests,11 E2E, source TypeScript и ESLint прошли. E2E включает IPv4/IPv6 на1440/320, предупреждение/переход к BFD с сохранением устройства и очисткой поиска, recovery/foreign/not-used/unknown; остальные7 проверяют состояния данных OSPF. Полную1481 UI/context регрессию157 повторно не запускали: она принята на предыдущем source, эта delta проверена отдельно.
Переданный production source SHA256 совпал локально/на сервере. Frontend production build exit0; ux-bfd158 развёрнут с сохранённой private rollback env, backend ux-id156/PG сохранены. Немедленный curl после старта получил000 до готовности frontend; последующие две browser проверки1440/320 получили200, реальные catalog/server API200, page errors/overflow0 и отсутствие ложного предупреждения после очистки native fixtures. Позитивная native BFDv6 сессия этим блоком не заявляется. Пароли и RouterOS конфигурация не менялись; прежний закрытый SSH-туннель localhost3000/8000 восстановлен.
Протоколы: [профильные проверки и сборка](ux-ui/acceptance/ospf-bfd-correlation-2026-10-12.json), [реальный развёрнутый интерфейс](ux-ui/acceptance/ospf-bfd-ipv6-smoke-2026-10-12.json). Установленные ReUI/Frame/base-nova переиспользованы без изменения primitives.
| Референс | Схема доработки |
| --- | --- |
| [ReUI Data Grid Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Устройство → точный IPv6 peer/интерфейс → достоверное предупреждение → соответствующая BFD сессия |
Следующий159 — native OSPFv3/BFDv6 на собственной GRE паре, short loss/recovery и независимая сверка cleanup. Официальный [BFD manual](https://manual.mikrotik.com/docs/user-guides/routing-and-networking-protocols/unicast/bfd/) описывает IPv4/IPv6 и use-bfd, но текущая страница версии7.26 не заменяет эксперимент на стенде7.24.5. Sustained route gate, scale/IPv6 public WAN/outer и физическая резервность остаются непроверенными;12.5 открыт.
## 12.5.159 — native OSPFv3 и BFDv6 с потерей и восстановлением (2026-10-12)
Два CHR7.24.5, собственные GRE с IPv4 outer, ULA fd00:159:1::1/64↔2 и loopbacks fd00:159:ff::1/128↔2/128. OSPFv3 single area/private router IDs, originate-default=never; BFD разрешён только на собственном GRE для fe80::/10,200ms×3, use-bfd=yes только own template. Начальные состояния: BFD Up, OSPF Full, собственный удалённый IPv6 маршрут active; Ping3/3 в обе стороны. Catalog и selected API подтвердили own маршруты/ipv6:IDs/link-local nextHop/via.
Два собственных /ipv6/firewall/filter правила блокировали только UDP3784 input/output на CHR2, exact own GRE и соответствующие link-local src/dst /128. OSPF89/ICMPv6 не блокировались; отдельный packet capture Hello не выполнялся.44 samples за25s показали BFD Down и поздние OSPF Full/own route active после20s. Это наблюдаемая граница, не доказательство постоянного route gate/непрерывной доставки/SLA. На production frontend ux-bfd158 с реальным backend ux-id156 два readonly UI случая1440/320 показали предупреждение, IPv6 BFD Down и переход с сохранением server context; page errors/overflow0. [ПК](ux-ui/screens/ospfv3-bfd159-1440-2026-10-12.png), [телефон](ux-ui/screens/ospfv3-bfd159-320-2026-10-12.png); mobile просмотрен, скрытые горизонтально table columns не считаются одновременно видимыми.
После снятия own UDP fault: BFD Up/Full/route active и recovery Ping3/3×2. Затем own rules/templates/area/instance/BFD config/IPv6/bridge/GRE удалены;13 static collections×2 сравнивались по выбранным конфигурационным полям, dynamic rows/volatile counters исключены. Порядок IPv4/IPv6 filters и BFD configuration сохранён. Это не побайтное сравнение полного runtime export. Helper exit0; container удалён после сравнения exact full ID с own cidfile и состояния exited0. Собственная SQL fixture база не создавалась, helper только читал server config из main DB, background polling продолжался. Пароли/public/default routes не менялись; оба CHR доступны при cleanup.
Протоколы: [native44/recovery/cleanup](ux-ui/acceptance/ospfv3-bfd-native-2026-10-12.json), [2 реальные UI](ux-ui/acceptance/ospfv3-bfd-live-ui-2026-10-12.json). Source/dependencies/build не менялись после158, повторная общая регрессия не требовалась. [Официальный BFD](https://manual.mikrotik.com/docs/user-guides/routing-and-networking-protocols/unicast/bfd/) использован как справка; фактический результат относится к установленной7.24.5, не текущей версии страницы7.26.
Принят basic native IPv6 BFD в OSPFv3, scoped loss/recovery/API/UI; IPv6 public outer/WAN, scale, физическая резервность/interop/continuous loss остаются открыты. Следующий160 — BGP IPv6+BFD own pair;12.5 открыт.
## 12.5.160 — IPv6 BGP с BFD: снятие маршрута и восстановление (2026-10-12)
На двух CHR7.24.5 собственная GRE пара по IPv4 outer, ULA fd00:160:1::1↔2/64 и loopbacks fd00:160:ff::1↔2/128, private AS64555/64556. BGP afi=ipv6/use-bfd=yes; BFD разрешён только own GRE/ULA subnet200ms×3. Input/output routing filters принимают только точные own/remote /128, default-originate=never, network-blackhole=no. Initial BFD Up/Established/ровно1 own remote NLRI и Ping3/3×2, catalog/selected sessions API подтверждены.2 real UI1440/320 показали IPv6 peers/Established, no overflow/page errors; собственные native мутации выполнялись helper, browser только читал.
На CHR2 два own IPv6 filter rules блокировали только UDP3784 input/output, exact own GRE/ULA src/dst /128. TCP179/ICMPv6/публичные пути не блокировались.44 samples за25s подтвердили BFD Down и отсутствие обоих own active IPv6 routes; первое такое REST наблюдение636ms после установки fault, это не SLA/packet capture/continuous packet loss. Во время перехода native established flag некоторое время ещё присутствовал на одном узле; промежуточные состояния сохранены полностью. Fault catalog показал Unknown для обеих session rows с отсутствующим установленным FSM state, не догадку Idle/Down. UI во время самого fault отдельным сценарием не проверялся.
Удаление own fault вернуло BFD Up/Established/NLRI и Ping3/3×2. Все созданные connection/instance/filter/address-list/BFD/IPv6/bridge/GRE удалены;12 static collections×2 совпали по выбранным конфигурационным полям (dynamic/volatile исключены), routing/IPv6 filter/BFD configuration order сохранён. Helper exit0, container удалён по exact full ID из cidfile только после exited0. Основная DB только читалась helper; background polling продолжался, отдельная SQL база не создавалась. Пароли и default/public routes не менялись; оба CHR доступны при cleanup.
Протоколы: [native44/withdrawal/recovery/cleanup](ux-ui/acceptance/bgp-ipv6-bfd-native-2026-10-12.json), [2 live UI](ux-ui/acceptance/bgp-ipv6-live-ui-2026-10-12.json), [ПК](ux-ui/screens/bgp-ipv6-160-1440-2026-10-12.png), [телефон](ux-ui/screens/bgp-ipv6-160-320-2026-10-12.png). Source/dependencies/build не менялись; runtime ux-id156/ux-bfd158 сохранён, без повторной общей регрессии.
Basic single-path BGP IPv6/BFD withdrawal/recovery принят, не IPv6 public WAN/outer/scale/interop/physical redundancy/бесшовность. [BFD с BGP](https://manual.mikrotik.com/docs/user-guides/routing-and-networking-protocols/unicast/bfd/) — справочный документ; результат фактически проверен на7.24.5. Следующий161 — audit legacy selected BGP/alert parser: общий catalog сохраняет Unknown, но старый detectState угадывает Active из uptime и Idle при отсутствующем native FSM.12.5 открыт.
## 12.5.161 — неизвестные состояния BGP без ложных оповещений (2026-10-12)
Общий legacy/selected parser больше не угадывает Active из uptime и Idle при отсутствии native FSM. Established=true сохраняет подтверждённое Established; остальные известные FSM распознаются точным match, malformed/future-prefix/blank/missing сохраняют Unknown. Catalog и selected state согласованы; legacy числовые counters/timers этим блоком не мигрировались. BGP alert evaluation рассматривает только известные FSM: Unknown/blank/future state не подтверждают проблему и не становятся подтверждённым previous down при recovery.
Из collector выделена чистая корреляция BGP signals: newest current Unknown остаётся Unknown, previous baseline ищет ближайшее известное состояние среди сохранённых runs. Так Idle→Unknown→Established подтверждает recovery на основе последнего известного Idle; Established→Unknown→Established не создаёт ложный recovery; Unknown current не создаёт event. История ограничена существующими8 прочитанными collector runs, неизвестный период не становится новым фактом. Legacy peer keys serverName:peerName сохранены; миграция неоднозначных одинаковых имён этим блоком не заявляется.
Live-maps parser/profile прошёл; alert-engine groups/evaluate прошли, SQL confirm-stability тест **пропущен** из-за отсутствующего локального PG подключения/EACCES, не записан как pass. Outbox/alerts HTTP/JWT profile прошёл на controlled sender interfaces, реальные сообщения не отправлялись. На скомпилированном коде replay92 сохранённых настоящих RouterOS rows из160:19 Established/73 Unknown, selected/catalog states совпали;73 unknown problem и73 unknown previous recovery проверки не создали event. Это воспроизведение native payloads, не новый live mutation/SQL/outbox-delivery тест.
Backend build прошёл, окончательный Docker кандидат ux-bgp161b совпал с локальными988 emitted non-test файлами (новый module добавил4 outputs). Первоначальный ux-bgp161/984 был развёрнут до обнаружения last-known gap; финальный161b пересобран и развёрнут после исправления baseline, обе версии/rollback env сохранены. Backend/PG healthy, frontend ux-bfd158 сохранён;3 readonly real GET catalog/selected и2 browser1440/320 passed/no errors/overflow после cleanup. Positive missing-FSM rows доказаны replay, пустой live catalog не выдан за native inactive proof. Общая регрессия157 относится к прежнему source; эта delta проверена профильными сценариями.
Протоколы: [compiled988](ux-ui/acceptance/bgp-unknown-compiled-2026-10-12.json), [native payload replay](ux-ui/acceptance/bgp-unknown-replay-2026-10-12.json), [deployed API/UI](ux-ui/acceptance/bgp-unknown-deployed-2026-10-12.json). RouterOS конфигурация/пароли этим блоком не менялись, новые native fixtures не создавались, ReUI/Frame/base-nova UI primitives сохранены.
Следующий162 — native private4-byte ASN в IPv6 BGP и отображение длинных AS на1440/320; прежний BFD fault повторять без новой delta не требуется.12.5 открыт.
## 12.5.162 — четырёхбайтовые ASN в IPv6 BGP и интерфейсе (2026-10-12)
Два CHR7.24.5, own IPv4 outer GRE/IPv6 ULA fd00:162:1::1↔2/64 и loopbacks fd00:162:ff::1↔2/128. Private AS4200000162↔4200000163 взяты из [диапазона IANA4200000000–4294967294](https://www.iana.org/assignments/as-numbers), reserved4294967295 не использован. Input/output filters принимают только exact own/remote /128, afi=ipv6, default-originate=never и network-blackhole=no. Native Established и negotiated as4, local/remote AS сохранили исходные10-значные числа вместо AS_TRANS; catalog совпал, capabilities содержит4-byte-AS. Каждый узел получил ровно один own remote IPv6 NLRI, initial Ping3/3×2.
Readonly production UI1440/320 показал обе IPv6 сессии/Established и точные remote ASN в DOM, no errors/document overflow. Mobile проверен визуально; AS columns могут требовать горизонтального table scroll, одновременная viewport visibility всех columns не заявляется. Administrative disable одной own BGP connection снял own remote IPv6 route на другом узле, первое наблюдение135ms после PATCH, не hold timer/BFD/SLA/continuous loss. Enable вернул Established/NLRI и Ping3/3×2. BFD fault160 без source delta не повторялся.
Own connections/instances/routing filters/address-list/IPv6/bridge/GRE удалены,11 static collections×2 совпали по выбранным конфигурационным полям, filter order сохранён. Helper exit0; container удалён после exact-ID/state check. Main DB только читалась helper, background polling продолжался; пароли/public/default paths не менялись, оба CHR доступны при cleanup. Source/dependencies/build после161 не менялись, runtime ux-bgp161b/ux-bfd158 сохранён.
Протоколы: [native/as4/withdrawal/recovery/cleanup](ux-ui/acceptance/bgp-four-byte-asn-native-2026-10-12.json), [2 live UI](ux-ui/acceptance/bgp-ipv6-162-live-ui-2026-10-12.json), [ПК](ux-ui/screens/bgp-ipv6-162-1440-2026-10-12.png), [телефон](ux-ui/screens/bgp-ipv6-162-320-2026-10-12.png). Live UI162 использует отдельный файл bgp-ipv6-162-live-ui, протокол160 сохранён отдельно.
Границы: private four-byte ASN между двумя RouterOS, single-path IPv6 внутри IPv4 GRE, не interop со сторонними peers, IPv6 public outer/WAN, scale/physical redundancy. Следующий163 — проверка duplicate legacy alert keys serverName:peerName: два разных устройства с одинаковыми именами не должны создавать ложные state transitions внутри одного snapshot.12.5 открыт.
## 12.5.163 — неоднозначные ключи BGP-оповещений (2026-10-12)
Два CHR в native162 имели одинаковые legacy alert keys CHR:peerName. Раньше второй peer внутри того же snapshot мог стать previous state первого. Collector теперь сначала группирует строки одного run: повторный key становится current Unknown, а ambiguous history не используется для поиска previous known state через разные identities. Даже одинаковые states не доказывают уникальное соответствие configured target конкретному peer. Distinct keys и last-known переходы161 сохранены; stable server/peer ID target migration не выполнена. Для legacy ambiguous targets события подавляются консервативно.
Unit assertions проверили duplicate same/different/unknown states и исторический barrier. Compiled replay46 real native160 snapshot pairs подтвердил одинаковые ключи,46 Unknown/46 suppressed problem/46 suppressed recovery. Это сохранённые RouterOS payloads, не новая native mutation. Alert groups/evaluate и controlled outbox/HTTP/JWT profiles прошли; SQL stability снова skipped из-за отсутствующего PG подключения и не считается pass. Backend build/988 emitted parity passed, ux-bgp163 развёрнут с rollback env; backend/PG healthy, frontend ux-bfd158 сохранён.3 readonly catalog/selected GET и2 live UI1440/320 passed/no errors/overflow после fixture cleanup. Образы/сборка отражают эту delta, полная1481 UI/context regression157 повторно не запускалась.
Протоколы: [replay46](ux-ui/acceptance/bgp-ambiguous-replay-2026-10-12.json), [compiled988](ux-ui/acceptance/bgp-ambiguous-compiled-2026-10-12.json), [deployed API/UI](ux-ui/acceptance/bgp-ambiguous-deployed-2026-10-12.json). ReUI/Frame/base-nova UI primitives сохранены; RouterOS/пароли/объекты не менялись, сообщения не отправлялись.
Следующий164 — strict nullable selected BGP counters/AS/timers: legacy selected API ещё подменяет отсутствующие значения default numbers и UPDATE messages количеством prefixes.12.5 открыт.
## 12.5.164 — достоверные числа BGP во всех маршрутах чтения (2026-10-12)
Selected/all BGP parser и тип BgpSessionRead теперь используют nullable remote/local AS, timers, RX/TX prefixes и message counters. Отсутствующее/invalid/unsafe значение не становится0/90/30 или типом eBGP. Prefix RX читается только из prefix-count; UPDATE messages не являются количеством префиксов, TX prefixes остаётся null без доказательства. Наблюдаемый0 сохраняется0, известные ASN до32-bit сохраняются точно. Catalog переиспользует общий parser, добавляя AFI; миллисекунды в timers переведены в дробные секунды, overflow duration остаётся unknown.
Это намеренное изменение старого selected/all API numeric contract: clients должны обрабатывать null, историческое legacy-preserved утверждение ранних блоков больше не описывает эту версию. Все repository type consumers прошли backend build; основной BGP UI уже использовал nullable catalog. Collector keys/state и правила163 сохранены, новые numeric defaults не добавлялись.
Live-maps profile и controlled alert/outbox HTTP/JWT прошли,15 BGP data/freshness/link E2E passed. Compiled replay96 реальных rows из160/162:146 missing counters сохранены null,104 observed zero сохранены0,4 four-byte ASN rows точны; selected/catalog fields совпали с native values. Это replay, не новый live native lifecycle. Backend production build/988 emitted parity passed; ux-bgp164 развёрнут с rollback env, backend/PG healthy, frontend ux-bfd158 сохранён.3 readonly GET и2 real UI1440/320 passed/no errors/overflow после cleanup. Positive nullable rows доказаны replay и unit/HTTP profiles, empty live catalog не считается positive missing-field доказательством. Broad regression157 не повторялась без необходимости.
Протоколы: [native replay96](ux-ui/acceptance/bgp-nullable-replay-2026-10-12.json), [compiled988](ux-ui/acceptance/bgp-nullable-compiled-2026-10-12.json), [deployed API/UI](ux-ui/acceptance/bgp-nullable-deployed-2026-10-12.json). ReUI/Frame/base-nova primitives/RouterOS конфигурация/пароли сохранены, новые fixtures/сообщения не создавались.
Следующий165 — общий GRE/BGP collector: await внутри Promise.allSettled сериализует независимые reads и не сохраняет успешный BGP при раннем GRE throw; текущие BGP signals также не должны восстанавливать отсутствующий в newest snapshot peer из старого run.12.5 открыт.
## 12.5.165 — независимый сбор GRE/BGP и актуальные сигналы оповещений (2026-10-12)
Убраны await внутри Promise.allSettled: независимые GRE/BGP reads действительно запускаются параллельно. Promise boundary сохраняет sync и async ошибки отдельно; успешная группа не теряется при отказе другой. Dependency seam проверяет production collector без SQL/RouterOS. Busy guard не запускает повторных запросов, после отказа collecting сбрасывается. Permanent collector/history tests включены в test:alert-engine.
GRE/BGP reader берёт8 newest completed runs со status ok/error, включая null result_json: более новый отказ не скрывается фильтром успешных прогонов. Invalid/version-mismatched/null/malformed payload становится barrier с пустыми current collections и явным fatalError. Valid partial snapshot сохраняет успешную группу. Current peer/tunnel keys берутся только из newest run; прошлые строки используются только как previous state существующего текущего объекта. Удалённые/непрочитанные объекты не воскресают как current. GRE duplicate labels/history barrier также исключают cross-peer transitions; BGP163 guards сохранены. Остальные collector families, age disabled jobs и stable-ID legacy target migration этим блоком не закрыты.
Unit cases проверили concurrent start до GRE completion, busy/no second fetch, scoped sync/async failures, recovery/empty, failed/null/malformed history, successful partial BGP, deleted peers и GRE alias ambiguity. Alert/outbox HTTP/JWT profiles passed; SQL confirm-stability skipped без PG подключения и не записан как pass. Backend build/996 emitted parity passed. Actual production PG SELECT выполнен compiled candidate через default_transaction_read_only=on:8 history rows, newest BGP0/current BGP0/GRE0, old owned peers0; bootstrap/writes/RouterOS/messages отсутствовали. В этих real latest rows не доказан positive error/partial fixture — отдельный seeded SQL сценарий запланирован166.
ux-collector165 развёрнут с rollback env, backend/PG healthy, frontend ux-bfd158 сохранён;3 readonly GET и2 live UI1440/320 passed/no errors/overflow. Source frontend/primitives ReUI/Frame/base-nova не менялись; широкая UI regression157 не повторялась. Пароли/RouterOS config сохранены, fixtures не создавались этим блоком.
Протоколы: [compiled996](ux-ui/acceptance/collector-compiled-2026-10-12.json), [real readonly PG](ux-ui/acceptance/collector-postgres-readonly-2026-10-12.json), [deployed API/UI](ux-ui/acceptance/collector-deployed-2026-10-12.json). Следующий166 — own isolated PG с positive error/partial fixtures и полная backend regression при доступном PG, затем проверка удаления собственной DB/containers.12.5 открыт.
## 12.5.166 — полная backend-регрессия с доступным PostgreSQL (2026-10-12)
Общий npm --prefix backend test теперь запускает прежние24 профиля последовательно через cross-platform Node runner, устанавливая NODE_ENV=test без shell environment assignment. Pool использует [штатный allowExitOnIdle](https://node-postgres.com/apis/pool) только в test: завершённый SQL файл не ждёт30s idle socket. Production/development сохраняют обычный lifecycle; active queries не подменяются early exit. Permanent pool test проверяет оба режима без SQL подключения. Исходный список сохранён в test:all; прямой test:all — legacy chain без test-mode wrapper.
В отдельном Docker test image Node22/dev dependencies/PG18 tools создана собственная mm_accept_166_1791779292730. До bootstrap проверены уникальность, current_database и пустая public schema. Все SQL-тесты получили URL этой базы; основные server credentials не клонировались в тестовую DB, URL/env/полный лог остаются в private0600 вне Git. Все24 профиля завершились exit0 за286958ms (4m47s), PostgreSQL-unavailable skip отсутствовал. SQL confirm-stability тест, ранее skipped локально, выполнился и passed. Это измерение одного прогона, не процент ускорения без сопоставимого baseline.
Permanent owned SQL test перед DDL проверяет explicit MMAPP_OWN_SQL_DB/166 name/current_database.6 реальных scheduler_runs rows: old success, newest error с успешным BGP/failed GRE, SQL NULL result, malformed JSON string, successful empty и duplicate labels/keys. Actual reader/builder сохранили valid partial BGP, не восстановили старые/удалённые peers, не выдали malformed/null за success и подавили ambiguity. Собственные test rows удалены. Optional network-disabled SQL fixture152/156 без специального MMAPP_OWN_TEST_DB остался skipped;33 disabled/bigint guards156 не считаются повторно принятыми здесь.
Database owner проверен, только собственная DB удалена WITH FORCE после завершения child tests; main server id/host/name/username/password/type/enabled/country/site до/после совпали (в публичном отчёте только boolean, без значений). Own full-test container удалён после exact cidfile/state exited0 check. Main background polling продолжался, RouterOS сценарии не повторялись, реальные сообщения не отправлялись. Другие multi-instance/physical disconnect/real integrations границы прежние.
Backend production build и996 emitted parity passed; отдельный NODE_ENV=production readonly actual PG probe подтвердил allowExitOnIdle=false. ux-pg166 развёрнут с rollback env, backend/PG healthy, frontend ux-bfd158 сохранён;3 readonly GET/2 live UI1440/320 passed/no errors/overflow. Frontend source/ReUI/Frame/base-nova не менялись, UI/context regression157 не повторяли после backend-only delta.
Протоколы: [full24/own SQL/cleanup](ux-ui/acceptance/backend-postgres-regression-2026-10-12.json), [compiled996](ux-ui/acceptance/backend-postgres-compiled-2026-10-12.json), [production pool/read-only PG](ux-ui/acceptance/backend-postgres-production-pool-2026-10-12.json), [deployed API/UI](ux-ui/acceptance/pg-regression-deployed-2026-10-12.json). Следующий167 — freshness/disabled collector-job audit; newest completed snapshot сам по себе не доказывает свежесть после остановки collector.12.5 открыт.
## 12.5.167 — устаревшие GRE/BGP снимки не подтверждают новые оповещения (2026-10-12)
Audit scheduler показал, что GRE/BGP сейчас всегда enabled, отдельного UI switch для него нет; interval30s фиксирован. Выдуманный disabled-job guard не добавлен. После остановки процесса/сборщика latest completed row может оставаться старым: reader теперь проверяет newest finished_at и producer sampledAt. Окно freshness —3 периода (90s), future clock tolerance —1 период (30s), привязанные к одной константе с scheduler timing/metadata. Старый, слишком будущий, invalid/nonstring sampledAt даёт unavailable/stale barrier и не порождает GRE/BGP current events. Прежние rows остаются last-known history при наличии свежего current; ambiguity guards163/165 сохранены. Это явно выбранная прикладная граница для30s collector, не RouterOS SLA или физическое обнаружение отказа.
Unit clock injection проверяет stale/future completion и sample, malformed/nonstring date,90s boundary; local alert/scheduler profiles/build passed. Local PG branches skipped, затем отдельный Node22/PG18.6 owned профиль test:alert-engine выполнился exit0 за31154ms:8 SQL rows (6 error/partial/NULL/malformed/empty/duplicate +stale/future sample) и actual confirm-stability passed, PostgreSQL-unavailable skip0. Полные24 profiles166 без необходимости не повторялись. Guarded integration test по-прежнему использует166 namespace; создана новая собственная mm_accept_166_1791781079670, прежняя166 база не переиспользована. Own rows/DB/container удалены; main server static fields до/после совпали. Приватный лог/env не попали в Git.
Backend production build/1000 emitted parity passed, ux-fresh167 развёрнут с rollback env, backend/PG healthy, frontend ux-bfd158 сохранён.3 readonly catalog/selected GET и2 live UI1440/320 passed/no errors/overflow. Source frontend/ReUI/Frame/base-nova и RouterOS правила/пароли не менялись, native tunnels не создавались, сообщения не отправлялись. Running containers после cleanup только3 основных сервиса. Свежесть других collector families/отключаемых jobs и stable-ID target migration этим блоком не закрыты.
Протоколы: [owned SQL8/cleanup](ux-ui/acceptance/collector-freshness-sql-2026-10-12.json), [compiled1000](ux-ui/acceptance/collector-freshness-compiled-2026-10-12.json), [deployed API/UI](ux-ui/acceptance/collector-freshness-deployed-2026-10-12.json). Следующий168 — audit остальных alert source families: stale/disabled config не должны создавать current facts.12.5 остаётся открытым в матрице внешних ограничений.
## 12.5.168 — карта оставшихся источников оповещений (2026-10-12)
Выполнен source audit и чтение метаданных production PG с default_transaction_read_only=on. Source/database settings не менялись, default-seeding getters не вызывались, bootstrap/RouterOS/messages отсутствовали. Реальные текущие настройки: resources enabled/15s, traffic enabled/30s, REST disabled/120s, active Ping probes0. Builder в момент audit выдавал1 server signal (max age3.197s), traffic1 (max age18.24s), probes0. Это возраст наблюдаемого снимка, не controlled stale fixture. Одновременно обнаружена1 группа одинаковых имён у enabled servers: оба CHR называются одинаково,2 devices сворачиваются в1 name-based signal. Audit не исправляет это поведение.
Source findings: non-GRE/BGP reader выбирает только status=ok; resource/REST/traffic/probe reducers восстанавливают ключи из старых runs; evaluation не проверяет sampledAt age; builder не применяет текущие enabled flags источников. Resource reducer превращает всякое не-online значение в offline; одинаковые имена могут смешать current и previous разных устройств. Это подтверждённые свойства кода, но runtime disabled/stale/malformed fixture пока не выполнен. Не считать найденные проблемы устранёнными только по этому документу.
| Источник | Интервал / особенность | Требование к следующему блоку |
| --- | --- | --- |
| Resources | Настраиваемый intervalSec, на стенде15s; default300s | Effective resourcesEnabled; уникальная identity/current known state; возраст по своему периоду |
| REST availability | Отдельные enabled/intervalSec; сейчас выключен | Выключенные/старые REST данные не переопределяют свежий resource result и не подтверждают recovery |
| Ping | probeIntervalSec и individual uptime_probes.intervalSec; snapshot содержит только due probes | Фильтр enabled probes/source servers; latest observed row каждого probe и его собственный TTL, не latest-run-only |
| Traffic | Настраиваемый enabled/intervalSec; сейчас30s | Отсутствие/старое/disabled не превращается в zero/low traffic; identity не смешивает одинаковые имена |
Период GRE/BGP30s/границу90s167 нельзя механически распространить на resources default5min или Ping с индивидуальным расписанием. Для169 сначала определить effective config каждого family и per-probe timing, затем coherent current states/previous known history без cross-device aliases. Проверить own PG: disabled source с retained history, stale/future times, newer error/null, empty/deleted object, duplicate labels, частичный due-probe batch и controlled recovery. Локальные unit/profile tests + scoped SQL; production build только backend после окончательной delta. Полную UI/context regression повторять лишь при frontend foundation change, остальные native протоколы не переснимать без новой причины.
Схема доработки:
~~~mermaid
flowchart LR
A["Текущий источник и устройство"] --> B["Enabled и уникальная identity"]
B --> C["Последнее наблюдение и свой интервал"]
C --> D{"Свежий известный факт?"}
D -->|да| E["Условие правила и last-known history"]
D -->|нет| F["Нет подтверждения события"]
E --> G["Outbox после подтверждения"]
~~~
Протокол: [readonly audit168](ux-ui/acceptance/alert-source-audit-2026-10-12.json). Source/build/runtime не менялись после167, новые тесты и исправления не заявляются. Следующий169 — выполнить этот единый блок, сохранить profile/owned SQL результаты и локальный коммит без push. Реальные Telegram/Portal/внешние accounts, client OS/physical WAN/multi-instance остаются отдельными условиями12.5.
## 12.5.169 — идентификация устройств в сигналах оповещений (2026-10-12)
По поручению пользователя выполнить небольшой объём при оставшихся7% лимита. Исходный единый объём169 ограничен самостоятельной локальной частью; полная приёмка источников не заявляется. Добавлен server-signal-identity.ts, builder читает только id/name/host/enabled из текущего servers. До name-based timeline и traffic reducer каждая строка resource/REST/traffic сопоставляется с текущим активным устройством по ID, имени и адресу. Сигналы отключённых/удалённых устройств, старого имени/адреса и повторяющегося ID внутри одного run исключаются. Если несколько enabled устройств имеют одинаковое имя после trim/lowercase, их сигналы не выдаются: существующие правила адресуют цель по имени и не позволяют безопасно выбрать конкретное устройство. Имена/настройки самих CHR не менялись. На текущем стенде оба CHR имеют одинаковое имя; после будущего развёртывания такие цели будут подавлены до явного устранения неоднозначности или миграции правил на ID. Это консервативное отсутствие подтверждённого события, не offline и не нулевой traffic.
Новый постоянный тест добавлен в test:alert-engine: уникальная цель; отключённая/удалённая; два одноимённых устройства и перестановка каталога; отключение дубликата; изменение имени/адреса; другой ID; повторные строки; строковый безопасный PG ID и небезопасный ID; неизменность входа. Прошли доступные проверки alert-engine (identity/groups/evaluate-rule/collector/history), backend production build и ESLint трёх изменённых TS файлов. GRE/BGP SQL пропущен без явно выделенной own DB; confirm-stability SQL пропущен из-за PostgreSQL connect EACCES127.0.0.1:5432. Это не положительная SQL-приёмка. Полная UI/context regression не запускалась: frontend не менялся.
Ограничения сохранены явно: only-ok history всё ещё может поднимать старый факт, disabled flags самих jobs и sampledAt age не применяются; resource unknown и traffic отсутствующее значение требуют отдельного исправления; probe identity/enabled/individual interval остаются в170. Duplicate row guard не заменяет latest-current/error barrier. SQL/live fixtures и source/runtime parity для169 отсутствуют; удалённый backend/frontend не развёртывались, RouterOS writes/messages0, новые сетевые объекты не создавались. Доступность серверов в этом локальном блоке не перепроверялась. Runtime остаётся ux-fresh167/ux-bfd158; изменений169 в браузере пока нет.
Протокол: [локальная проверка169](ux-ui/acceptance/alert-server-identity-2026-10-12.json). Следующий170 — source enabled/freshness/current known guards, per-probe timing и identity с owned SQL positive/negative fixtures, затем coherent backend build/deploy/live и локальный коммит без push. Этап12.5 остаётся открытым.
## 12.5.170 — достоверность серверных, пробных и трафиковых сигналов (2026-10-12)
Завершён оставшийся объём169 в одном coherent backend блоке. Новый collector-source-signals отделяет чтение от чистого построения фактов. Builder читает текущие настройки и identity без seeding getters и без credentials: resourcesEnabled/pingEnabled имеют тот же fallback на legacy enabled, что scheduler; REST/traffic используют собственные enabled. Выбираются последние завершённые ok/error runs, включая NULL/error JSON, вместо only-ok history. Текущие server/traffic keys берутся только из newest run: empty/error/malformed/unknown не восстанавливают старую цель. Частичная ошибочная коллекция сохраняет известные строки других устройств. ServerID/name/host/enabled/duplicate guards169 сохранены; пустое имя может использовать host, как collector. producer sample и completion проверяются по3 effective periods, future tolerance1 period; минимумы5s resources/traffic и10s REST повторяют scheduler. Resource неизвестное значение не становится offline; Traffic требует ok=true и конечные неотрицательные RX/TX, отсутствующее/ошибка не становится0. Подтверждённый нулевой трафик остаётся0.
Ping сопоставляется с текущим probeId/name/target/sourceServerId/interface/source label, enabled probe и enabled source. Повторные цели/строки исключаются; более новое unknown/null/fatal/error observation не подменяется старым. Valid due-only batch может не содержать медленную пробу: её latest observed row сохраняется в пределах своего TTL. Effective probe period учитывает individual interval и глобальный tick, default минимум5s; future tolerance привязана к глобальному tick. Чтение охватывает3 максимальных настроенных probe periods, с защитным пределом4096 rows (при очень большом масштабе возможен консервативный пропуск, масштаб этим блоком не принят). Сэмплы до server/probe updatedAt не подтверждают новую конфигурацию. Server timelines прекращают recovery history на unknown/invalid/ambiguous barrier; свежие resource/REST подтверждения объединяются без выдуманного cross-source recovery. Выбирается реальное собственное history успешного источника.
Постоянные чистые тесты проверяют config/identity/time/empty/error/partial/unknown/numeric boundaries, медленные due probes, изменения конфигурации, recovery и настоящий evaluateRule путь с положительным и отрицательным control (server offline, loss и RX low). Локальные alert-engine и scheduler profiles прошли, backend build и ESLint прошли. Локальный PostgreSQL недоступен, SQL branches там skipped; положительная SQL-приёмка выполнена отдельно на Node22/PostgreSQL18.6: test:alert-engine за18622ms,16 новых SQL cases (включая31 Ping batches, больше прежнего лимита24),8 GRE/BGP SQL rows и actual confirm-stability passed без PG skips.
Автоматическая проверка отклонила копирование всех production env в persistent файл; этот способ не использован. Для SQL созданы собственная база mm_accept_166_1791791913287 и отдельная LOGIN роль без SUPERUSER/CREATEDB/CREATEROLE/BYPASSRLS, пароль сгенерирован временно и не публиковался. URL/роль ограничены own DB; main credentials/JWT не копировались. Тестовые строки/контейнер, база и роль удалены и отсутствие проверено. Main SQL fixtures/RouterOS/messages отсутствуют; обычные фоновые сборщики main не останавливались. Полная24-profile/UI1260/context221 regression157/166 без новой причины не повторялась.
Production backend собран инкрементально на прежней базе ux-fresh167 с прежними зависимостями: backend dependency hash совпал.433 source inputs и1008 emitted files совпали поSHA256 с LF normalization, запущенный imageId совпал с проверенным образом. Развёрнут ux-sources170/version1.0.0-test.sources170, backend/PG healthy; frontend ux-bfd158 прежний. В.env изменён только BACKEND_IMAGE_TAG, для rollback сохранён прежний tag ux-fresh167, копия всего secret env не создавалась. После cleanup только3 основных running containers.
Readonly production PG builder подтвердил1 группу одинаковых enabled labels и0 server/traffic/probe signals. Ноль проб соответствует отсутствию configured probes, server/traffic подавлены из-за неоднозначности двух CHR с одним именем; это не отказ устройств и не доказательство положительных измерений (они проверены в owned SQL). Имена/пароли не менялись.4 read-only API checks включают оба selected CHR BGP endpoints и catalog без failures;6 UI cases /alerts,/servers,/uptime при1440/320 passed, pageerrors/API writes/overflow0. Первые локальные network calls получили sandbox EACCES, повтор с разрешённым network доступом passed; UI helper сначала ожидал отсутствующий в существующей странице h1, исправлен на фактический main без изменения frontend. Это scoped smoke, не новая полная accessibility сертификация.
Протоколы: [SQL16/cleanup](ux-ui/acceptance/collector-sources-sql-2026-10-12.json), [source433](ux-ui/acceptance/collector-sources-source-2026-10-12.json), [compiled1008](ux-ui/acceptance/collector-sources-compiled-2026-10-12.json), [readonly production](ux-ui/acceptance/collector-sources-production-2026-10-12.json), [runtime](ux-ui/acceptance/collector-sources-runtime-2026-10-12.json), [API/UI](ux-ui/acceptance/collector-sources-deployed-2026-10-12.json).
Следующий171 — понятная диагностика неоднозначных/отключённых целей оповещений: silent suppression безопасен для engine, но пользователь должен понимать причину отсутствия события. Миграция name-based rules на stable ID, scale/multi-instance/physical WAN/внешние Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
## 12.5.171 — понятные причины недоступности целей оповещений (2026-10-12)
При conservative suppression170 пользователь должен понимать, почему событие не подтверждается. Добавлен чистый collectAlertTargetIssues и optional public meta.targetIssues: kind server/traffic/probe, подпись и причина ambiguous/disabled-object/disabled-source. Диагностика строится из текущих настроек внутри того же repeatable read/read only transaction, что основной overview; getters defaults не создают. Учитываются dedicated source switches, enabled REST как разрешённый availability source по конфигурации, enabled устройства/пробы, duplicate labels и fallback имени на host. Это диагностика конфигурации; она не заявляет свежесть измерений, online устройств или фактическую доставку Telegram. Поля credentials не выбираются и не публикуются. Engine правила, target representation и права не изменены.
На /alerts добавлен существующий ReUI/shadcn Alert warning в base-nova/Frame композиции без изменения vendor files/theme. Строки доступности и трафика одной цели объединены; причина и дальнейшее действие читаются вместе. Длинный список раскрывается native details/summary клавиатурой, большой список изначально свёрнут; длинные подписи переносятся на телефоне. Ссылки ведут к серверам, пробам и сбору данных. При устранении причины warning исчезает после подтверждённого обновления; legacy API без optional поля не подменяется догадкой. Имена двух CHR и targets действующих правил автоматически не переписывались.
| Эталон | Доработка | Проверка |
| --- | --- | --- |
| Существующие Alert и Frame проекта | Подпись → причина → понятный переход → обновление | [ПК1440](ux-ui/screens/alerts-target-issues-1440-2026-10-12.png), [телефон320](ux-ui/screens/alerts-target-issues-320-2026-10-12.png) |
Локально прошли12 скриптов test:alerts-telegram (unit/transaction/config/queue/HTTP/JWT), application-source TypeScript, backend build и ESLint. Полный root tsc сначала захватил ignored tmp с давними test/build artifacts и выдал их ошибки; source check с исключением tmp/backend/packages прошёл, contracts/backend проверены собственной сборкой. Root tsconfig не менялся.42 unique E2E:22 readers/targets/pickers/rules/new diagnostics за44.7s;19 history/outbox/Telegram за30.6s;1 новый keyboard/long-label mobile за6.2s. Реальная отправка Telegram отсутствовала: HTTP пути подменены тестовыми receipts. Последняя проверка хронологии старым check-progress168 ожидала прежний header168; сам сохранённый historical slice имел12 dated blocks/35 существующих evidence links. Это устаревшее ожидание helper, не удаление журнала; актуальная сверка обновлена отдельно.
Owned Node22/PostgreSQL18.6 profile passed19540ms:16 source SQL cases плюс проверки actual getAlertsMeta (known empty, disabled-source reasons, ambiguous server/traffic kinds),8 GRE/BGP SQL rows и actual stability;PG unavailable skips0. Временная own DB/ограниченная роль mm_accept_166_1791794042576 и test container удалены. Main fixtures/RouterOS writes/messages0. Обе production сборки прошли; source434 backend+518 frontend inputs и1012 emitted backend/contracts files совпали SHA256 (text CRLF→LF, binary unchanged). Полную UI1260/context221/backend24 regression без новой причины не повторяли.
Развёртывание staged: frontend ux-targets171/version1.0.0-test.targets171 сначала принял реальный прежний API ux-sources170 без targetIssues; затем обновлён backend ux-targets171. На старом cached frontend строгий прежний DTO не знает additive поле: после обновления backend следует перезагрузить страницу для получения совместимого frontend. Менялись только image tags в existing.env; rollback tags сохранены отдельно без копирования secret env. Backend/PG healthy; frontend running/HTTP/browser подтверждён, отдельного healthcheck нет. Запущенные imageIds совпадают с проверенными образами; после cleanup3 основных running containers.
2 real UI1440/320 показали настоящий CHR warning:1 сгруппированная подпись,2 affected kinds, ссылка /servers, overflow/pageerrors/API writes0. Scoped axe нового блока WCAG2A/AA violations0, full WCAG certification не заявляется. Снимки просмотрены; исходные пользовательские GRE/VXLAN images сохранены без staging/revert. Настройки/имена/пароли CHR и исходные правила не менялись.
Протоколы: [SQL/cleanup](ux-ui/acceptance/alert-target-issues-sql-2026-10-12.json), [source](ux-ui/acceptance/alert-target-issues-source-2026-10-12.json), [compiled](ux-ui/acceptance/alert-target-issues-compiled-2026-10-12.json), [interop](ux-ui/acceptance/alert-target-issues-interop-2026-10-12.json), [runtime](ux-ui/acceptance/alert-target-issues-runtime-2026-10-12.json), [live UI](ux-ui/acceptance/alert-target-issues-deployed-2026-10-12.json).
Следующий172 — отдельная обнаруженная ветка: синтезированный monitoring history в alerts-service читает raw latest samples, пока не применяет enabled/freshness/current-error guards170 и требует проверки реального PG timestamp→public string на positive sample. Source finding не является уже выполненным исправлением или доказанной runtime ошибкой. Stable-ID target migration, отсутствующие цели удалённых правил, physical WAN/scale/multi-instance и реальные Telegram/Portal/client OS остаются отдельными условиями12.5. Локальный коммит без push.
## 12.5.172 — подтверждённые текущие проблемы в журнале мониторинга (2026-10-12)
Внешнее воспроизведение выполнено на compiled ux-targets171 с own PostgreSQL/ограниченной ролью. Прежний overview принимал положительный raw sample и корректно выдавал timestamp string: гипотеза Date/schema failure НЕ подтвердилась. Первая baseline попытка ожидала ошибку и завершилась assertion failure; её результат сохранён, own fixture/DB/role очищены. Уточнённый baseline прошёл: один и тот же live offline оставался после disabled server, disabled resources source и замены sampledAt на часовой давности. Это положительное независимое подтверждение реального disabled/freshness дефекта прежней ветки, не вывод только из кода.
Raw uptime_resource_samples/uptime_probe_samples больше не используются как самостоятельное доказательство текущей проблемы в alerts history. Выделен readCollectorSourceSnapshot с injectable reader: engine и history используют одинаковые current/config/identity/unknown/freshness/per-probe guards170. History читает source facts через параметризованный Drizzle adapter в том же repeatable read/read only transaction overview, без глобального pool обхода snapshot. Значения запроса остаются bound params, raw fragments — только внутренние постоянные SELECTs. Network GRE/BGP не перечитывается для этой ветки. Конфигурация, источники и lookup metadata остаются readonly; defaults/credentials не загружаются.
monitoringHistory строит live problems только по подтверждённым offline/degraded серверам и down/warn пробам. Заголовок сервера «Доступность сервера» соответствует объединению resource/REST, а не выдуманному outage CPU. Live sent=false/source=live сохраняются: это мониторинг, не факт отправки Telegram. ISO timestamps нормализованы, IDs используют stable hash вместо удаления символов, чтобы разные подписи не схлопывались. Persisted source=db receipts и sent flags сохранены независимо от доступности устройства/источника. Сортировка merged history сравнивает реальное время, чтобы новый ISO live timestamp и PostgreSQL datetime string не нарушали порядок. Это совместимость форматов; старый overview уже корректно проходил schema, driver Date bug не заявляется.
Source/build/unit/ESLint прошли. Локальные alert-engine и12 скриптов alerts-telegram прошли в доступных ветках; локальный PG skipped.4 профильных reader/history E2E прошли11.0s; frontend исходники не менялись, полную UI/context regression не повторяли. Owned Node22/PG18.6 сначала выполнил25 source/history cases; после дополнительного chronology control финальный профиль26 cases прошёл19421ms, плюс GRE/BGP8 и actual stability, PG skips0.9 history scenarios поверх прежних16 и1 chronology: positive live+synthetic stored receipt, disabled device/source, stale JSON при свежих raw tables, newer NULL/error, empty/current absence, same-name server ambiguity с независимой пробой, changed probe identity, raw-only samples без подтверждения; более новая DB receipt стоит первой при смешанном формате дат. Синтетический receipt в own DB не доказывает реальную Telegram доставку.
Все известные baseline/fix DB names и роли удалены, test containers отсутствуют. Один SCP connection закрылся после задержки authentication; финальный bundle повторно передан и verified перед deploy. Промежуточные25-case результаты не выданы за финальные26. Source437 и1020 emitted files совпали SHA256/LF normalization. Production build прошёл; backend ux-history172/version1.0.0-test.history172 развёрнут, imageId совпал с проверенным, backend/PG healthy, frontend ux-targets171 прежний. Existing.env изменён только backend tag, rollback ux-targets171 сохранён без копии secret env. Running containers3.
Первый live GET совпал с закрытием старого контейнера и получил socket closed; после healthy повтор прошёл.3 API reads (/api/alerts и оба selected CHR BGP)200,2 /alerts UI1440/320 accepted/overflow/pageerrors0, configuration warning171 сохранён. Source engine facts и UI journal теперь согласованы в проверенных границах. Raw-only/manual measurements без подтверждённого scheduler snapshot не синтезируются как текущие alerts; их provenance требует отдельного профиля. Native configs/пароли не менялись, RouterOS writes/messages0. Реальная packet loss/current state для scope устройств в этом блоке не создавалась: собственные SQL fixtures, не новый data-plane тест.
Протоколы: [first baseline hypothesis](ux-ui/acceptance/monitoring-history-baseline-attempt-2026-10-12.json), [real baseline](ux-ui/acceptance/monitoring-history-baseline-2026-10-12.json), [SQL26/cleanup](ux-ui/acceptance/monitoring-history-sql-2026-10-12.json), [source437](ux-ui/acceptance/monitoring-history-source-2026-10-12.json), [compiled1020](ux-ui/acceptance/monitoring-history-compiled-2026-10-12.json), [runtime](ux-ui/acceptance/monitoring-history-runtime-2026-10-12.json), [API/UI](ux-ui/acceptance/monitoring-history-deployed-2026-10-12.json).
Следующий173 — source finding: collectPingProbesOnce/pingProbesNow catch превращает ошибку REST-команды в lossPct100/down; decoder пока разрешает ok=false/down/null/100. Это не независимое доказательство потери пакетов. Проверить и исправить подтверждение измерений/empty payload; не объявлять legacy raw UI stats и manual provenance уже исправленными. Также остаются unconfirmed/missing target diagnostics, stable-ID migration, scale/multi-instance/physical WAN и внешние Telegram/Portal/client OS.12.5 открыт. Локальный коммит без push.
## 12.5.173 — ошибка Ping не подменяет измеренные потери (2026-10-12)
Завершён целый раздел producer→SQL→API→UI. parsePing теперь возвращает measured: empty/unsupported replies, zero sent и противоречивые/malformed counts не подтверждают процент потерь. Подтверждённые received0/sent4 остаются100%/down с RTTnull; успешный настоящий RTT0/loss0 сохранён. Scheduled и manual collectors различают успешное измерение и ошибку REST/недостаточный ответ; after-bandwidth Ping при неизвестном результате возвращает null metrics/error, а не выдуманный outage. Alert decoder принимает только ok=true и известное состояние; retained legacy ok=false/down/100 не срабатывает как измеренная потеря. Malformed due-probe rows без ID — barrier, не разрешение восстановить старое измерение.
Миграция0010 добавляет uptime_probe_samples.measurement_known boolean defaulttrue и observation_error text; CHECK/legacy storage status и integer loss не ломаются. Raw100/down в failed rows — прежние storage sentinel с явным measurement_known=false, не публичное измерение. Snapshot/public observations/API loss становятсяnull/statusunknown, есть причина ошибки. Новые flags пишутся при scheduled и manual error/empty response. Старые scheduled failure samples переклассифицируются readonly по точному probeId+sampledAt retained v1 JSON provenance; genuine100% без failure flag не меняется. Старые manual/retention-lost failures без provenance надёжно восстановить нельзя: они остаются legacy ambiguity, полного historical cleanup не заявляем. Migration additive, прошлые данные не удаляет; source JSON internal v1 теперь допускает nullable loss/unknown. Для rollback старый код не интерпретирует measurement_known, поэтому совместимость хранения не означает корректное чтение новых unknown attempts старой версией.
Overview выдаёт unknown/null без fallback100/down и без padded historical0. Observations timestamps канонизированы; parser проверяет согласованность unknown/null. /uptime использует тот же observed decoder, что dashboard: «Нет данных», — для RTT/loss, причина execution error, отдельный filter/URLstatus=unknown. Новая draft probe тоже не объявляется заранее up/0. Мини-Sparkline сохраняет gaps; expanded RTT chart больше не превращаетnull в0 и не дублирует одиночную точку для выдуманной линии. Dashboard status tooltip получает причину. Source/speed-interface read endpoints теперь409 до RouterOS при disabled server; ошибочная подпись «для ping всё равно можно выбрать выключенный» исправлена. Это соответствует прямому правилу пользователя не опрашивать выключенные устройства любых типов. UI/ReUI primitives/theme не заменены.
| Состояние | Эталон | Результат |
| --- | --- | --- |
| Ошибка REST/нет измерения | Существующие probe rows/StatusDot/Sparkline | [ПК1440](ux-ui/screens/ping-measurement-unknown-1440-2026-10-12.png), [телефон320](ux-ui/screens/ping-measurement-unknown-320-2026-10-12.png) — API-fixture, не production positive sample |
| Подтверждённые100% | Тот же public observed path | Down и100% сохранены отдельным positive control |
Unit parser/observations/frontend dashboard-probes/URL guards прошли; backend build, application-source TypeScript и ESLint прошли (в uptime-collector два прежних unused settings warnings, functional scope не расширен). Первый npm --prefix exec взял неверный cwd, повтор direct tsx корректен; новый тест сначала использовал неверное имя Zod package, исправлен на установленный @fastify/type-provider-zod. Local cancellation test получил sandbox EACCES, разрешённый сетевой профиль прошёл; local own SQL skipped без выделенной базы.85 unique E2E Uptime/Ping/Speed: initial83passed/2failed были новые ambiguous test selectors (имя есть в sidebar и строке); selector исправлен на конкретную причину ошибки, delta3passed9.5s. Existing83 scenarios повторно не запускались;2 screenshot captures passed8.5s отдельно. Это не85 clean single-run и не87 новых сценариев. Два перезаписанных тестами прежних speed images восстановлены SHA256;8 user dirty GRE/VXLAN images не тронуты. Новые снимки просмотрены, nullable состояние читаемо при320px.
Owned Node22/PG18.6 профили alert-engine+probes прошли42380ms:26 source/history SQL cases, GRE/BGP8/actual stability и8 новых Ping cases. Последние проходят через реальный MikrotikClient HTTP к loopback simulator, persisted flags, GET overview Fastify path:401,empty,manual,real loss/zero,API,legacy exact provenance и disabled no-outbound requests. Simulator не является физическим RouterOS/network failure. Финальные unit guards zero/inconsistent counts/malformed probe проверены перед scoped rerun; temporary DB/role/container удалены. Production credentials/JWT не копировались. Type/producer tests подключены к стандартному test:probes; default profile count не увеличен.
Source440 backend+518 frontend inputs/1020 emitted parity совпали SHA256. Both production builds passed, backend image включает новый drizzle0010. Staged deploy: frontend ux-ping173 сначала принял старый API ux-history172, затем backend ux-ping173/version1.0.0-test.ping173. Migration0010 и2 новых columns подтверждены readonly в main PG. Backend/PG healthy, frontend running/HTTP/UI, imageIds verified, running containers3. В.env менялись толькоimage tags; rollback tags сохранились отдельно без secret env копии. Cached прежний frontend следует перезагрузить: новые nullable/unknown DTO требуют совместимого reader.
Независимо выполнен настоящий native Ping4 packets194.226.121.150→104.165.244.7 иобратно через running compiled173: обе команды приняты, обе4/4,0%loss, parsed RTT53ms. Это короткое наблюдение, не WAN SLA/max throughput. Main DB read-only, native конфигурация/пароли не менялись;2 operational Ping commands, routerConfigWrites0/messages0. На production configured probes0:2live UI1440/320 подтверждают actual empty catalog/new filter/reader/overflow/pageerrors0; nonempty/error UI доказан fixtures, не выдан за main positive measurement. Collector row/error flags проверены ownSQL, real parser отдельно native payloads.
Протоколы: [SQL/HTTP8+cleanup](ux-ui/acceptance/ping-measurement-sql-2026-10-12.json), [native4/4](ux-ui/acceptance/ping-measurement-native-2026-10-12.json), [source](ux-ui/acceptance/ping-measurement-source-2026-10-12.json), [compiled](ux-ui/acceptance/ping-measurement-compiled-2026-10-12.json), [interop](ux-ui/acceptance/ping-measurement-interop-2026-10-12.json), [runtime](ux-ui/acceptance/ping-measurement-runtime-2026-10-12.json), [live UI](ux-ui/acceptance/ping-measurement-deployed-2026-10-12.json).
Следующий174 — audit first-wave/invalid traffic rate confidence: ok request и numeric sum не всегда доказывают измеренный rate без previous wave. Не заявлять эту гипотезу как уже выполненное исправление. Source unconfirmed/missing target diagnostics, manual history provenance, unsupported/compound time formats, legacy ambiguous samples, scale/multi-instance/physical WAN/external integrations остаются отдельными условиями12.5. Полная acceptance открыта. Локальный коммит без push.
## 12.5.174 — достоверность суммы трафика: аудит и локальное исправление (2026-10-12)
На исходном8fb46b1 гипотеза подтверждена исполнением настоящих private sampleRate/toNum, извлечённых TypeScript AST, затем существующих collectSourceSignals/evaluateRule. Семь source fixtures: first-wave/reset/equal timestamps/missing/malformed counters дают0 и ложный RX<1; genuine zero даёт правильное срабатывание, positive1Mbps не срабатывает. Протокол [baseline audit](ux-ui/acceptance/traffic-confidence-audit-2026-10-12.json) намеренно fixed=false и относится к исходной версии, а не к финальному исправлению. Это локальное source воспроизведение; отправки Telegram, реальной SQL persistence и физического сброса RouterOS не было.
Добавлен pure traffic-observation: строгие safe nonnegative integer counters, без parseFloat prefix/negative clamp/missing→0; observed rate подтверждается только двумя валидными дельтами. Traffic collector оставляет numeric stored-rate shape, но публикует sumRxMbps/sumTxMbps только при наличии учитываемых интерфейсов и measured=true у всех. First wave, reset, равное/invalid время, частично неизвестный интерфейс и отсутствие учитываемых интерфейсов не становятся измеренным нулём; genuine zero сохраняется. Некорректный interface counter завершает текущий server snapshot с ok=false до insert. WG peers остаются optional: ошибка их чтения/декодирования не превращает корректный interface snapshot в failure; частичные валидные peer rows могут остаться. Это не новая гарантия полноты peer history.
Existing snapshot types уже имеют optional суммы; source decoder174 не менялся и исключает отсутствующие суммы. Таблица snapshots уже показывает — при отсутствии значения; ReUI/theme не менялись. Historical traffic builder уже различает первый sample и measured zero при includeObservations=true. Старые загрязнённые counters/rates не переписаны: ошибку прежнего missing-counter→0 нельзя надёжно реконструировать без provenance. Consumer raw numeric-rate compatibility, freshness/failed attempts history, безопасный baseline после смены объекта, unsafe integer counters и масштаб требуют отдельной SQL/HTTP-приёмки.
npm --prefix backend run test:traffic-rate прошёл: существующие формулы/observations, новый counter/rate/source guard и actual collectTrafficOnce body через AST с in-memory DB/HTTP boundaries (first wave, zero, reset, malformed/no insert, excluded interfaces). Извлечение исполняет исходный collector, не копию алгоритма; это не реальный PostgreSQL или RouterOS. npm --prefix backend run build прошёл. [Local check](ux-ui/acceptance/traffic-confidence-local-2026-10-12.json) фиксирует хеши изменённых source и границы доказательства. Full regression/remote deployment не выполнялись, поскольку изменён только локальный producer guard.
Следующий175: real MikrotikClient loopback HTTP→owned PostgreSQL→scheduler resultJson→source decoder с first-wave/next-zero/reset/malformed/mixed-interface controls; проверить очистку своих объектов и исключение stale historical samples. После profile acceptance собрать backend и развернуть guard на тестовом стенде; frontend ux-ping173 совместим с absent optional totals. Сейчас оба сервиса удалённого стенда всё ещё ux-ping173, native Ping4/4 подтверждён в173; новое исправление там ещё не доступно. Пароли, конфигурация CHR и тестовый runtime этим блоком не менялись. Локальный коммит без push.
## 12.5.175 — SQL/HTTP-приёмка достоверности трафика и развёртывание (2026-10-12)
Producer guard174 проверен через настоящий MikrotikClient к loopback HTTP simulator, actual collectTrafficOnce, PostgreSQL18.6 и buildSignalSnapshotFromCollectors. Девять SQL controls: first wave без суммы/со stored valid counters; следующая genuine zero; reset без суммы; malformed123bad и missing counter дают ok=false/no insert; новый второй интерфейс не даёт частичную сумму; следующая полная zero wave; положительная скорость; disabled server без outbound HTTP. Каждая актуальная wave сохраняется в scheduler_runs и проходит реальный source reader. Fixture clock не задерживает тест: в своей базе сохраняется только последняя baseline wave и сдвигается её время на30s. Это не проверка длинной historical continuity/retention и не физический RouterOS counter reset.
Профиль test:traffic-rate дополнен тестом traffic-observation-sql.test.ts. Локально SQL явно skipped без own database; удалённый Node22/PG18.6 профиль прошёл9358ms без SQL skip. База mm_accept_166_1791803283546 принадлежала временному LOGIN без SUPERUSER/CREATEDB/CREATEROLE/BYPASSRLS. Актуальные production DB/JWT secrets не копировались. Тестовые rows убраны finally, база/роль/container удалены trap и отсутствие DB/role проверено каталогами; остались только3 основные контейнера. [SQL](ux-ui/acceptance/traffic-confidence-sql-2026-10-12.json).
Production backend build прошёл локально и на Debian; [1024 compiled artifacts](ux-ui/acceptance/traffic-confidence-compiled-2026-10-12.json) совпали SHA256 с локальными, different/missing0. Backend ux-traffic175/version1.0.0-test.traffic175 развёрнут; frontend ux-ping173 сохранён и совместим с optional sums. До сборки исправлена строка Docker base, которую ошибочно заменила blanket tag substitution; неисправный Dockerfile не собирался и не выпускался. В.env менялся только BACKEND_IMAGE_TAG, rollback tag ux-ping173 сохранён без копии секретного env. [Runtime](ux-ui/acceptance/traffic-confidence-runtime-2026-10-12.json): verified imageIds, backend healthy/frontend running.
[Read-only live smoke](ux-ui/acceptance/traffic-confidence-deployed-2026-10-12.json): /traffic1440/320, traffic servers200/no pageerrors/no overflow; /servers,/traffic/servers,/scheduler/runs?jobKey=traffic200. Это проверка доступности/совместимости UI, не доказательство доставки Telegram или возникновения всех edge cases в main DB. Нет manual scheduler run/config/password/message writes; автоматический scheduler остаётся штатным. Пароли CHR не менялись; native Ping4/4 в обе стороны подтверждён ранее в173, здесь повторно не заявлен.
Следующий176 — inspect native compound durations53ms561us и parseFloat prefix fallback в Ping parser; положительные source payloads уже сохранены в173, не требуются новые сетевые сущности для первоначального доказательства. Legacy invalid traffic counters/raw-rate consumers, history freshness/failed attempt barriers, interface identity/config changes, scale/multiple backend и внешние интеграции остаются условиями12.5. Не считать guard174–175 полной приёмкой трафика. Локальный коммит без push.
## 12.5.176 — точность составных длительностей Ping RTT (2026-10-12)
В native payloads173 обоих CHR есть53ms561us и другие ms/us. Прежний parseFloat fallback терял microsecond component; например53ms900us превращалось в53ms вместо rounded54ms,1s53ms561us — в1ms вместо1054ms. parsePingTimeMs теперь разбирает ordered s/ms/us, простые decimal units, comma decimal, clock c minute/second<60 и полную bare millisecond numeric string; duplicate/reverse units, negative, exponent, unknown suffix и numeric-prefix garbage возвращаютnull. Значения хранят дробную точность до прежнего integer rounding общего RTT. Success-reply fallback теперь требует валидную duration; garbage time без explicit counts/loss не изображает успешное измерение. Summary с подтверждённым packet loss может иметь RTTnull — loss от этого не подменяется.
Добавлены unit positive/negative controls, genuine0,53ms900us→54 и1s53ms561us→1054. Offline replay двух сохранённых настоящих CHR responses173 подтвердил дробные значения53.xms и прежний правильный rounded mean53ms/0%loss. Это повторная интерпретация записанного ответа, не новый физический Ping. [Local/native replay protocol](ux-ui/acceptance/ping-duration-local-2026-10-12.json). Файл evidence optional в test runner: если отсутствует в image, replay явно skipped, форматные guards продолжают исполняться.
Backend production build и полный профиль test:probes прошли (8.0s): HTTP/allowlist/cancellation/actual local fake RouterOS POST, parser/observations. SQL test явно skipped локально без own database; предыдущая SQL173 не выдана за приёмку изменённого176. Это не подтверждает полную RouterOS duration grammar или malformed summary loss/count consistency; остальные источники unknown/provenance и legacy rows остаются открыты. Новые Docker build/deploy/remote SQL на этом остатке квоты не запускались.
Следующий177 — owned SQL/HTTP regression Ping8 на изменённом parser, при необходимости добавить compound/raw-garbage producer cases; затем incremental backend build, compiled parity, deploy и read-only browser smoke. Backend удалённого стенда остаётся ux-traffic175 healthy, frontend ux-ping173. Отдельный реальный success replay не заменяет SQL error persistence. Конфигурация/пароли CHR, production DB, отправки сообщений этим блоком не менялись. Все изменения176 сохранены локальным коммитом без push;12.5 не закрыта.
## 12.5.177 — SQL-регрессия составного RTT и обновление стенда (2026-10-12)
Ping ownSQL173 расширен двумя controls: summary53ms900us сохраняется как RTT54ms/loss0; raw53bad без подтверждённых counts/loss сохраняется как unknown/null/error. Остальные8 controls сохранены:401/empty/manual/actual100%/zero/API/legacy exact provenance/disabled no outbound. Node22/PG18.6 полный test:probes прошёл24383ms,10 SQL cases без skip. Тесты используют настоящий MikrotikClient к локальному HTTP simulator и действующий collector/PG observations; физический RouterOS malformed response не создавался. Native replay2 выполнен локально176; в удалённом test image evidence file отсутствует и replay явно skipped, не выдан за повторную physical проверку. [SQL](ux-ui/acceptance/ping-duration-sql-2026-10-12.json).
Временная ownDB mm_accept_166_1791803917983 и ограниченная роль удалены trap; отсутствие проверено PG-каталогами, отсутствие test container — docker inventory. Рабочие DB/JWT secrets не копировались. Новая backend image ux-rtt177/version1.0.0-test.rtt177 собрана поверх ux-traffic175; [1024 compiled files](ux-ui/acceptance/ping-duration-compiled-2026-10-12.json) совпали с локальными SHA256/missing0/different0. В.env изменён только BACKEND_IMAGE_TAG; rollback tag ux-traffic175. [Runtime](ux-ui/acceptance/ping-duration-runtime-2026-10-12.json): backend healthy, frontend ux-ping173 running, imageIds совпали.
[Live UI1440/320](ux-ui/acceptance/ping-duration-deployed-2026-10-12.json) прошёл: uptime overview200, unknown filter, no overflow/pageerrors. Actual production probes catalog пустой — эта smoke проверка не изображает main compound/error sample; они подтверждены отдельной ownSQL. Новых native Ping/config/password/Telegram операций не выполнялось. Пароли CHR не менялись. Исправления Ping173/176 и traffic174–175 теперь совместно доступны на тестовом backend; UI layout не менялся.
Следующий178 — read-only audit traffic history freshness при failed collection и legacy invalid-counter provenance; не объявлять старые неоднозначные строки исправленными по новому producer guard. Source unconfirmed/missing diagnostics, summary loss/count consistency, scale/multi-backend, физические WAN и внешние интеграции остаются условиями12.5. Журнал/план синхронизированы; локальный коммит без push. Новых блоков до следующего окна не начинать.
## 12.5.178 — достоверная история трафика, ручной сбор и свежесть UI (2026-10-12)
Подтверждены source gaps: исторические deltas могли выдавать старую скорость как текущую после failed collection; manual collect-now игнорировал snapshot failures и публиковал success. Добавлена migration0011/traffic_collection_state (одна актуальная запись на server): pending до HTTP, ok/error после записи, lastAttemptAt/lastSucceededAt и конфигурационный updatedAt fingerprint. Pending/error не стирают successful history. Completion обновляет только свою lastAttemptAt; pending не переписывает более новую попытку. Это ограничивает гонки записей, но не является распределённым lock/полной приёмкой нескольких backend.
Freshness reader read-only: enabled device/source, совпадение config fingerprint, state.ok и exact latest sample/success/attempt, TTL3periods (min5s), future tolerance1period. Error/pending/stale/disabled/config change/unknown маскируют current RX/TX; historical observed masks сохраняются. API серверов, клиентов и привязок получает observations/provenance; interface inventory больше не использует stored-rate fallback и не смешивает WG peer rows с interface counters. Source facts дополнительно учитывают новую attempt barrier, поэтому manual error/pending не оставляет старое traffic alarm активным. Для устройств без новой state пока читается прежняя scheduler provenance; первая новая попытка создаёт authoritative barrier. Не считать этот переход доказательством точности каждого старого snapshot.
В flags зарезервирован bit4 countersKnown, выставляется только новым strict collector. Старые/imported rows не переписаны и не объявлены достоверными; previous wave отбирает known counters. Исторический builder не строит deltas между legacy/unknown counters. Учтённые bytes суммируются по подтверждённым соседним дельтам; reset не добавляет произвольный новый counter как объём. Это lower-bound accounted volume, не утверждение полного покрытия периода. В UI подпись «Учтено RX/TX по замерам»; неизвестные скорости/пики/объёмы — —, chart gaps — null. Genuine measured0 сохраняется. Сортировка держит unknown после measured values. Dashboard existing decoder продолжает использовать masks.
Manual collect-now теперь через runSchedulerJobNow/общую запись результата и execution lock. Busy409; fatal/partial failures502 c failures/succeeded и сохранённым scheduler error; confirmed success200. Scheduler traffic ok=false теперь execution limitation, а genuine0 — success; valid offline/down других collectors не изменены. Ошибка setup больше не оставляет collecting=true навсегда: getSettingsRow находится внутри try/finally. Existing event/journal-unknown semantics сохранены.
Frontend projectTrafficObservations валидирует metadata/метрики, маскирует legacy numeric-only DTO, допускает RX/TX histories разной длины при корректных собственных masks. local10s clock переводит expired DTO в stale без новых сетевых запросов. Видны причина failed collection, последняя попытка и successful collection (не выдаётся за подтверждение measured rate). Offline object не скрывает сохранившуюся историю. ReUI Frame/installed Alert/KpiStatGrid/chart-23 adaptation и theme/base-nova сохранены; новые blocks/vendor components не устанавливались.
| Сценарий | Эталон и схема | Артефакт |
| --- | --- | --- |
| Ошибка опроса | Существующая ReUI Alert → current — → сохранённая RX/TX история | [ПК1440](ux-ui/screens/traffic-history-error-1440-2026-10-12.png), [телефон320](ux-ui/screens/traffic-history-error-320-2026-10-12.png), API-fixture |
| Genuine0 → TTL | Подтверждённая0 → expiry → —, история остаётся | E2E clock/control; без clock-based refetch |
| Legacy counters | Нет происхождения → unknown → новая baseline → measured delta | Owned SQL/HTTP collector path |
Backend test:traffic-rate прошёл: existing formulas, producer body/in-memory boundaries, strict counter/rate guards, freshness/merge. Frontend projection/dashboard unit tests, traffic flags, scheduler11, application-source TypeScript/backend production build/ESLint passed (unused obsolete ifaceNow helper удалён). Первоначальная freshness unit ошиблась default-param undefined, исправлена на прямой missing-state вызов; backend type adapter учитывает PG Date/string. Scheduler regression assertion разделена: traffic command failure является ошибкой исполнения, не device offline observation.
35 unique E2E eventually passed: initial31=27pass/4fail выявили лишнее требование равной RX/TX длины и положительные fixtures без explicit observations; malformed negative gap fixture заменена правильным null. Delta14=13pass/1fail выявил shorthand-json fixture без metadata; исправлено, delta1 passed. Остальные изменённые positive fixtures21 passed29.5s. Новые4 cases error1440/320/history retained even offline, true0/TTL/no refetch, numeric legacy unknown прошли. Screenshot-only scoped repeats2×2 для видимого warning/history внутри main scroller не считаются новыми сценариями; финальные изображения просмотрены. Existing8 user GRE/VXLAN dirty screenshots не тронуты. Full UI1260/backend24 не повторялись без необходимости.
Owned PG18.6/Node22: test:traffic-rate15709ms,9 counter/source +14 history controls (legacy/first/current/error/old-alarm barrier/users/interfaces/manual failure/success/stale/pending/config/disabled). Real MikrotikClient к loopback HTTP simulator, real SQL + Fastify GET/POST; не physical CHR fault. Common test:alert-engine20075ms:26 source/history SQL/GRE8/actual stability. Второй runner имел старую command label в report; corrected по actual command/harness и asserts before public recording, профиль не подменён повторным traffic run. Own DBs mm_accept_166_1791809970201 иmm_accept_166_1791810266923/ограниченные roles/test containers удалены; отсутствие проверено каталогами/docker. Production secrets не копировались. [SQL](ux-ui/acceptance/traffic-history-sql-2026-10-12.json).
[Source448 backend+521 frontend](ux-ui/acceptance/traffic-history-source-2026-10-12.json)/[1032 compiled](ux-ui/acceptance/traffic-history-compiled-2026-10-12.json) совпали SHA256. Обе production builds прошли (frontend185s Next phase); frontend ux-history178 staged with old backend ux-rtt177 [interop](ux-ui/acceptance/traffic-history-interop-2026-10-12.json), затем backend ux-history178/version1.0.0-test.history178. [Runtime](ux-ui/acceptance/traffic-history-runtime-2026-10-12.json) healthy/running/verified imageIds; в.env менялись только tags, rollback ux-rtt177/ux-ping173 без копии секретного env. Migration0011 подтверждена main PG. Новый frontend следует перезагрузить: прежняя вкладка не получает новый truth reader автоматически. Additive storage не гарантирует truthful interpretation старым UI.
[Native read-only](ux-ui/acceptance/traffic-history-native-2026-10-12.json): оба CHR194.226.121.150/104.165.244.7, GET identity/interface200, по2 interfaces, counters valid;4 native GET, no routerConfigWrites/password changes/messages. Это не loss/speed/WAN proof. [Live smoke1440/320+3 APIs](ux-ui/acceptance/traffic-history-deployed-2026-10-12.json) подтверждает actual provenance/UI/overflow/pageerrors0; error/legacy branches — отдельно fixtures/ownSQL. Main DB read-only только для native checker; schema migration и штатный scheduler writes были частью deploy.
Следующий179 — inspect/fix live monitor-traffic empty/partial/malformed rates (текущий parseMonitorTraffic заменяет их нулями), per-interface fallback и disabled-after-stream-start polling. Не объявлять этот путь принятым по history guards. Peer collection completeness, long sparse intervals, interface recreation/identity, snapshot after restore, scale/multiple instances и external integrations остаются условиями12.5. Локальный коммит без push.
## 12.5.179 — достоверный live-трафик, остановка и переподключение (2026-10-12)
parseMonitorTraffic больше не превращает empty/missing/malformed/negative/prefix values в0. Требуются именованные уникальные интерфейсы и обе конечные неотрицательные скорости; для aggregate — полный expected set актуальных активных интерфейсов, loopback исключён. Duplicate/wrong/missing interface и неполный ответ дают error. Настоящий measured0 сохраняется. Дельты и Mbps больше не округляются до хранения/передачи: positive1byte/30s не исчезает; legacy bigint rxBps/txBps округляются только при insert, read consumers используют counters. sum snapshot сохраняет полную точность. UI positive меньше разрешения отображается «<1 Кбит/с», а не fake idle0. Это не подтверждение максимальной производительности интерфейса.
Новый readTrafficLiveSample revalidates enabled/current config перед каждым новым native request и перед публикацией. Device disabled/deleted/config change закрывает SSE с причиной; HTTP401/403 закрывают поток без повторного опроса. Inventory обновляется каждый aggregate tick. Только joined HTTP400 при нескольких интерфейсах допускает per-interface fallback; failures не заглушаются пустыми массивами, partial sum не публикуется. Fallback≤4 concurrent commands, complete-wave budget8s; parent abort/deadline отменяет POST/ожидаемые продолжения. Существующий GET транспорт не принимает AbortSignal, его already-started read ограничен4s; после abort не запускаются следующие commands. Нельзя отозвать уже отправленную native команду. Multiple instances/large inventory/long WAN/revocation of already-established JWT streams отдельно не приняты.
Hook сохраняет конкретную причину error при end-of-stream, закрывает transport после decoding/HTTP failure и cleanup, валидирует timestampKind. «Переподключить live» создаёт новый request key в том же object scope, сохраняет последнее подтверждённое значение как historical до нового sample. При смене scope значения не переносятся. Connecting/error состояния явные; disabled retry during connecting предотвращает повторный запуск. Короткая подпись «Последнее live» помещается на320px, причина видна отдельной Alert. TimestampKind backend-receipt подписан «ответ RouterOS получен приложением»: at не выдаётся за часы устройства. Existing ReUI primitives/layout/theme сохранены.
| Состояние | Схема | Артефакт |
| --- | --- | --- |
| Source выключен / SSE закрыт | Причина → последнее значение → переподключить → новый sample | [ПК1440](ux-ui/screens/traffic-live-error-1440-2026-10-12.png), [телефон320](ux-ui/screens/traffic-live-error-320-2026-10-12.png), API-fixture |
| Partial native response | Inventory → expected set → unknown/error вместо partial0 | Real TCP/HTTP owned SQL |
Unit tests parser/completeness/fallback/auth/source/abort/10-interface concurrency/positive-small-rate прошли; frontend formatter/projection, application-source TypeScript/backend build/ESLint прошли. Новая unit initially использовала undefined default argument вместо missing field; fixture исправлена.7 unique E2E (2new retry/cause/320/1440 +5 existing SSE), final pass13.3s. Screenshot scoped repeats2 не новые scenarios; visual review выявила clipped long hint, caption сокращена и final frontend пересобран. Hidden tooltip duplicates в production smoke selector исключены filter visible, functional UI не менялся ради теста.
Owned Node22/PG18.6 profile test:traffic-rate24570ms без skip:9 counters/source+14history+10 live transport cases. Последние — actual Fastify TCP SSE и MikrotikClient HTTP к loopback simulator:0,empty,malformed,partial,complete fallback,failed fallback,401 terminal,disable after first sample/no further native requests,initial disabled404/no native requests,config change/closed stream. Fake RouterOS response не объявлен физической неисправностью CHR. Budget/concurrency refinement вызвала оправданный scoped rerun; финальный DB mm_accept_166_1791814796307/ограниченная role/container удалены, отсутствие проверено. Предыдущий временный mm_accept_166_1791813403915 также удалён trap. Production env/credentials/JWT не копировались. [SQL](ux-ui/acceptance/traffic-live-sql-2026-10-12.json).
[Source451 backend+522 frontend](ux-ui/acceptance/traffic-live-source-2026-10-12.json)/[1036 compiled](ux-ui/acceptance/traffic-live-compiled-2026-10-12.json) совпали. Production builds прошли; первый frontend build с длинной caption superseded до deploy. Staged frontend ux-live179 с backend ux-history178 [interop](ux-ui/acceptance/traffic-live-interop-2026-10-12.json), затем both ux-live179/version1.0.0-test.live179 [runtime](ux-ui/acceptance/traffic-live-runtime-2026-10-12.json) healthy/running/imageIds. Только.env tags, rollback both ux-history178 без secret env copy; storage migration не добавлялась.
[Настоящие CHR SSE](ux-ui/acceptance/traffic-live-native-2026-10-12.json) получили первый полный sample на обоих sourceId1/2, затем streams отменены: native interface GET + monitor-traffic read-only POST. Пример краткого наблюдения194 RX0.031584/TX0.002016Mbps,104 RX/TX0.002112Mbps; это не SLA/capacity/WAN proof. Пароли/конфигурация не менялись, messages0. [Production browser1440/320](ux-ui/acceptance/traffic-live-deployed-2026-10-12.json): actual live labels/receipt provenance,3APIs200,no overflow/pageerrors. Lab AUTH_REQUIRED=false; JWT/RBAC scopes не объявлены полностью принятыми по этой smoke.
Следующий180 — volume precision/binary units. Read-only baseline уже показал: measured1KiB/1MiB API round to0;100×1MiB также aggregate0;1GiB подписан1.0GB. Baseline сохранён в ignored tmp/volume180-baseline.json и пока не выдан за исправление. Sparse intervals/peer completeness/identity recreation/restore/multi-instance/scale и внешние integrations остаются12.5. Локальный коммит без push.
## 12.5.180 — точность учтённых объёмов и бинарные единицы (2026-10-12)
Read-only [baseline](ux-ui/acceptance/traffic-volume-baseline-2026-10-12.json) подтверждён до правки: measured1KiB/1MiB превращались в API0 и0.0GB;100×1MiB также aggregate0;1GiB выдавался с decimal labelGB. Убрано toFixed(1) из buildTrafficFromSamples/mergeBuiltTraffic: округление отдельных слагаемых больше не теряет суммарный трафик. Учёт остаётся по known соседним counter deltas, reset/unknown не добавляют выдуманные bytes. Отсутствующий baseline и coverage gaps по-прежнему ограничивают полноту периода.
DTO серверов, пользователей и привязок объявляет volumeUnit=GiB. Frontend принимает эту единицу явно, absent unit оставляет volume — без потери known speed/history; unsupportedGB marker отклоняет DTO. fmtGiB отображает Б/КиБ/МиБ/ГиБ/ТиБ/ПиБ, positive ниже1B как<1B, true0 как0B. Число округляется только при форматировании. Existing rate formatter остаётся decimal Кбит/Мбит/Гбит, binary объёмы не смешиваются с decimal rates. TotalsRow получил semantic group label. ReUI layout/theme/components сохранены. Удалён N+1 server-status SELECT на каждую binding: используется уже прочитанный catalog snapshot.
| Состояние | Схема | Пример |
| --- | --- | --- |
| Small positive bytes | bytes → exact GiB DTO → подходящая binary unit | [ПК](ux-ui/screens/traffic-volume-1440-2026-10-12.png), [320](ux-ui/screens/traffic-volume-320-2026-10-12.png), API-fixture component capture |
| Old response without unit | unknown unit → —, speeds/history retained | E2E actual API path fixture |
Backend formulas/volume assertion (known positive delta counts; reset does not), frontend unit boundary/unknown/zero/projection, TypeScript/backend build/ESLint passed.18 E2E passed36.3s (2new volume+10detail+6mobile), screenshot delta2 passed10.5s не новые cases; final widget captures просмотрены. Новые positive fixtures явно объявляют GiB. Existing user8 GRE/VXLAN screenshots не тронуты.
Owned Node22/PG18.6 test:traffic-rate31474ms:9 counters+14history+10actual TCP SSE+6new volume SQL cases, без SQL skip. Новые6 — storage/API GET для1B/1KiB/1MiB/1GiB на server/user/binding;100-part aggregate100MiB; reset lower-bound1MiB+512B. Seeded marker5 rows — собственные SQL fixtures, не физические device counts; отсутствие RouterOS calls в volume-only case не объявлено native acceptance. OwnDB mm_accept_166_1791816469068/ограниченная role/container удалены, absence verified. [SQL](ux-ui/acceptance/traffic-volume-sql-2026-10-12.json).
[Source452/522](ux-ui/acceptance/traffic-volume-source-2026-10-12.json)/[compiled1036](ux-ui/acceptance/traffic-volume-compiled-2026-10-12.json) SHA256 parity passed. Обе production builds прошли. Frontend ux-volume180 staged with backend ux-live179 [interop](ux-ui/acceptance/traffic-volume-interop-2026-10-12.json): volumes без unit unknown до backend update. Затем both ux-volume180/version1.0.0-test.volume180 [runtime](ux-ui/acceptance/traffic-volume-runtime-2026-10-12.json) healthy/running/imageIds. Только.env tags, rollback both ux-live179; no secret env copy/new migration. Старую вкладку следует перезагрузить для новых unit labels.
[Actual volume API](ux-ui/acceptance/traffic-volume-api-2026-10-12.json) показывает GiB и неокруглённые quantities обоих CHR из штатных collector rows; этот checker не отправлял новых native commands. [Browser1440/320](ux-ui/acceptance/traffic-volume-deployed-2026-10-12.json):3APIs200, actual live/receipt labels/provenance, no errors/overflow. Рабочая конфигурация/пароли не менялись, messages0; auto collectors остаются штатными. Это не WAN byte billing/capacity/SLA proof и не exact arithmetic acceptance за пределами safe integer/scale bounds.
Следующий181 — freshness статуса привязанных интерфейсов: enabled device+old running flag не должен объявлять online после failed/stale poll; peer enabled не доказывает handshake. Проверить native flag provenance и scalar shape, не переписывать legacy rows по догадке. Coverage/peer completeness/recreated interfaces/restore/multi-instance/scale/external integrations остаются12.5. Локальный коммит без push.
## 12.5.181 — достоверность статусов привязанных интерфейсов (2026-10-12)
Статус привязки теперь требует свежего успешного опроса текущей конфигурации устройства и подтверждённых native флагов. Ошибка, pending, disabled source, истёкший TTL или legacy row без status-known marker дают «Нет данных». Первое корректное измерение интерфейса может подтвердить его running, даже когда ещё недостаточно соседних counters для скорости. История и объёмы сохраняются.
Producer строго принимает true/false и native строки true/false/yes/no; missing/invalid flags больше не подменяются false. Новый бит8 status-known добавляется только новым успешным измерениям; bit4 counter-known не меняется, legacy rows не переписываются. Interface inventory проверяет имена/дубликаты. Включённый WG peer означает конфигурацию, поэтому даёт unknown без handshake proof; disabled peer — «Неактивен». Это не проверка реального VPN-туннеля.
DTO привязок содержит statusObservedAt/statusExpiresAt. Frontend проверяет provenance и TTL, обновляет состояние по своему clock даже без повторной загрузки; прежний payload без дат не считается подтверждением. Общие ReUI layout/base-nova и компоненты сохранены.
| Состояние | Схема | Проверка |
| --- | --- | --- |
| Native running + свежий успешный poll | native flag → known marker → TTL → Работает | own SQL и UI1440/320 |
| Ошибка / старый flag / истёкший TTL | последнее измерение → Нет данных | own SQL и UI1440/320 |
| Enabled WireGuard peer | configuration flag → Нет данных | own SQL; handshake не заявлен |
TypeScript/backend build/ESLint и профильные unit проверки прошли.8 E2E15.7s (2new+6mobile), после последней правки final delta2 passed10s. Один повтор первоначально не запустился из-за Windows sandbox/SWC access denied; корректный разрешённый запуск прошёл, это не UI failure.
[Own PG SQL](ux-ui/acceptance/traffic-status-sql-2026-10-12.json):48 cases9counter+14history+10TCP SSE+6volume+9status,36163ms, без unavailable skip. Новые9 проверяют настоящий collector→SQL→GET bindings на локальном HTTP RouterOS fixture: первое измерение, enabled/disabled peer, inactive interface, malformed flag,401,legacy bit,stale и disabled source. OwnDB mm_accept_166_1791818856762/ограниченная role/container удалены, отсутствие проверено. Первый запуск harness имел неверный путь распаковки; тесты не начались, его временная база/роль также удалены; пути исправлены до приведённого успешного результата.
[Source454/524](ux-ui/acceptance/traffic-status-source-2026-10-12.json)/[compiled1036](ux-ui/acceptance/traffic-status-compiled-2026-10-12.json) SHA256 parity, обе production builds прошли. Frontend ux-status181 сначала проверен с backend ux-volume180 [interop](ux-ui/acceptance/traffic-status-interop-2026-10-12.json); затем [both ux-status181](ux-ui/acceptance/traffic-status-runtime-2026-10-12.json) healthy/running/imageIds. Только .env tags, rollback ux-volume180, без копирования secret env и новой миграции.
[Native GET](ux-ui/acceptance/traffic-status-native-2026-10-12.json): оба CHR доступны, interface counters и boolean flags валидны; DB read-only, RouterOS config writes0/password changes0/messages0. [Browser1440/320](ux-ui/acceptance/traffic-status-deployed-2026-10-12.json): actual API/live/receipt labels без ошибок/overflow. Положительные binding branches доказаны собственными SQL/UI fixtures, не выданы за существующие пользовательские привязки стенда. Вкладку следует перезагрузить.
Следующий182 — полнота peer-среза при optional endpoint failure и пропуски истории. Interface running не доказывает end-to-end connectivity, enabled peer не доказывает handshake. Coverage/recreated identity/restore/multi-instance/scale/external integrations остаются открыты в12.5. Локальный коммит без push.
## 12.5.182 — атомарный приём измерений WireGuard peers (2026-10-12)
Разбор optional peers раньше добавлял каждую строку в общий массив сразу: ошибка следующей строки перехватывалась, а корректный префикс сохранялся как свежий срез. Отсутствующие ключи также молча пропускались. Теперь parseTrafficPeers сначала проверяет весь ответ: массив, объекты, непустые interface/public-key, уникальность пары interface+key, counter values и boolean disabled. Только полностью корректный массив передаётся collector. Ошибка не сохраняет ни одного peer из этого ответа; обычные интерфейсные измерения остаются доступны. Пустой массив — корректный пустой срез.
| Ответ | Схема результата | Проверка |
| --- | --- | --- |
| Все peers валидны | полная проверка → запись полного среза | existing SQL collector profile |
| Корректный peer → некорректный counter | полный срез отклонён → interface сохранён → peer Нет данных | новая own SQL проверка |
| Повторная пара / ответ не массив | полный срез отклонён → interface сохранён | ещё2 own SQL проверки |
[Owned PG](ux-ui/acceptance/traffic-peer-sql-2026-10-12.json):51 cases9counter+14history+10TCP SSE+6volume+12status,37534ms, без SQL skip.3 новые проверки используют настоящий HTTP fixture→collector→SQL→GET bindings; проверяют отсутствие partial peer rows, unknown peer status и online native iface. Временная база mm_accept_166_1791819465644, ограниченная роль и контейнер удалены, отсутствие проверено.
Backend TypeScript/build passed; [source455/524](ux-ui/acceptance/traffic-peer-source-2026-10-12.json), [compiled1040](ux-ui/acceptance/traffic-peer-compiled-2026-10-12.json) SHA256 parity. Frontend не менялся: используется уже собранный и проверенный ux-status181. Новая backend production build ux-peer182 [развёрнута и healthy](ux-ui/acceptance/traffic-peer-runtime-2026-10-12.json); frontend imageId также проверен. Только backend tag в .env, rollback ux-status181, без новой миграции и копирования секретов.
[Native read-only](ux-ui/acceptance/traffic-peer-native-2026-10-12.json) проверил ответы identity/interface/peers обоих CHR; оба доступны. Фактическое число peers сохранено в отчёте: пустой native список не выдан за приёмку активного туннеля. Положительные/некорректные peer случаи доказаны собственными fixtures; новые VPN объекты не создавались, этот блок исправляет collector parser. DB read-only, RouterOS config writes0/password changes0/messages0. [Production UI1440/320](ux-ui/acceptance/traffic-peer-deployed-2026-10-12.json) проверен с actual API/live/receipt labels без ошибок/overflow.
Следующий183: optional peer endpoint failure пока не получает отдельной видимой причины — interface success остаётся успешным, stale peer становится unknown по предыдущему181. Нужно сохранить причину частичного сбоя, не превращая успешные interface measurements в ошибку. Покрытие пропусков истории, recreated identity, масштаб и внешние интеграции остаются12.5. Локальный коммит без push.
## 12.5.183 — понятная причина частичного сбоя peer-опроса (2026-10-12)
Optional WireGuard peer error больше не исчезает в catch. Collector сохраняет причину в текущей записи traffic_collection_state, snapshot.warning и trafficSettings.lastError. Успешный interface poll остаётся status=ok: известные interface скорости/история не теряются из-за ошибки отдельного peer endpoint. Перезапуск с корректным peer ответом очищает прежнюю причину.
Existing observations.error передаёт причину в DTO. ReUI Alert показывает «Часть измерений недоступна» при current measurements с предупреждением; при unknown/stale остаётся профильная подпись и та же причина. Manual collect response содержит warnings с serverId; event получает warning level и «завершён с ограничениями». Нового schema/state enum и миграции нет. Общий scheduler не объявляет interface poll неуспешным из-за optional peers; ограничение сохранено в его snapshot.
| Состояние | Схема | Результат |
| --- | --- | --- |
| Interface success + peer401/invalid | measured rates + warning → пользователь видит часть недоступных данных | known0 остаётся0; peer Нет данных |
| Следующий полный poll | warning очищен → обычное текущее состояние | причина прежнего сбоя не остаётся ложной |
TypeScript/backend build/ESLint прошли.4 E2E11.2s:2 новых на1440/320 сохраняют measured0/history и показывают WireGuard401 reason,2 проверяют status TTL/legacy. Это API-fixture UI, не отказ реальных credentials.
[Own PG SQL](ux-ui/acceptance/traffic-warning-sql-2026-10-12.json):53 cases9counter+14history+10TCP SSE+6volume+14status,37478ms, без skip.3 предыдущих malformed/duplicate/shape cases теперь также проверяют сохранение warning;2 новые — peer-only401 с успешным iface+DTO cause и recovery с очищением причины. Временная база/ограниченная role/container удалены; exact namespace и отсутствие отражены в публичном отчёте.
[Source455/524](ux-ui/acceptance/traffic-warning-source-2026-10-12.json)/[compiled1040](ux-ui/acceptance/traffic-warning-compiled-2026-10-12.json) SHA256 parity. Обе production builds прошли. Frontend ux-warning183 сначала проверен с backend ux-peer182 [interop](ux-ui/acceptance/traffic-warning-interop-2026-10-12.json), затем [both ux-warning183](ux-ui/acceptance/traffic-warning-runtime-2026-10-12.json) healthy/running/imageIds. Только .env tags; rollback frontend ux-status181/backend ux-peer182, без secret env copy.
[Actual API](ux-ui/acceptance/traffic-warning-api-2026-10-12.json)/[browser1440/320](ux-ui/acceptance/traffic-warning-deployed-2026-10-12.json) подтвердили нормальный runtime/live/receipt labels без page errors/overflow. Оба CHR доступны в preceding182 native read; этот checker не отправлял новых native commands и не создавал искусственный отказ на реальных устройствах. Пароли/конфигурация не менялись, messages0. Туннельное соединение не заявлено: native peers182 были пустыми, fault/recovery доказаны в изолированном SQL/HTTP сценарии. Перезагрузить вкладку для нового Alert.
Следующий184 — явно определить покрытие периода при отсутствующих poll waves/переименовании или пересоздании интерфейса и не выдавать lower-bound за полный период. Внешние интеграции/масштаб и итоговая12.5 остаются открыты. Локальный коммит без push.
## 12.5.184 — сохранение истории после отключения интерфейса (2026-10-12)
[Read-only baseline](ux-ui/acceptance/traffic-membership-baseline-2026-10-12.json) воспроизвёл потерю истории: ether1 имеет2048 known bytes, ether2 — measured0; когда последнее состояние ether1 inactive или disabled, серверная сумма становится0, тогда как explicit interface detail сохраняет2048. Active control даёт2048 в обоих случаях. Это следствие фильтра по последнему running/disabled, а не ошибка RouterOS counters.
Исторический builder больше не исключает весь ряд или delta по состоянию линка на конце интервала. Валидные соседние counter deltas учитываются независимо от последнего link state. Статусы/число активных sessions по-прежнему зависят от native running/disabled. Live monitor/collector snapshot sum и правила исключения loopback/peer остаются прежними. Rate из истории — среднее между counter measurements; это не instantaneous native live rate и не доказательство доступности линка. Reset/unknown counter pair не добавляет bytes.
| Сценарий | До | После |
| --- | --- | --- |
| inactive/disabled ether1 + active ether2 с0bytes | общая сумма0, detail2048 | сумма/detail2048, sessions1 |
| оба active | сумма/detail2048 |2048 без изменения |
[Fixed formulas](ux-ui/acceptance/traffic-membership-fixed-2026-10-12.json):3 control cases, input rows/source SHA сохранены; no device/DB writes. [Own PG](ux-ui/acceptance/traffic-membership-sql-2026-10-12.json):55 cases9counter+14history+10TCP SSE+8volume+14status,36245ms, без skip.2 новых SQL cases проверяют GET server detail+summary, known history/peak и sessions1 после inactive/disabled last sample; seeded legacy counter-known flags не заявлены native status proof. Own namespace/role/container удалены и отсутствие проверено.
Backend TypeScript/build, [source455/524](ux-ui/acceptance/traffic-membership-source-2026-10-12.json), [compiled1040](ux-ui/acceptance/traffic-membership-compiled-2026-10-12.json) SHA256 parity passed. Backend ux-history184 [healthy/imageId verified](ux-ui/acceptance/traffic-membership-runtime-2026-10-12.json), frontend ux-warning183 без исходных изменений/повторной сборки. Только backend.env tag; rollback both ux-warning183. [Actual API](ux-ui/acceptance/traffic-membership-api-2026-10-12.json)/[production browser1440/320](ux-ui/acceptance/traffic-membership-deployed-2026-10-12.json) passed с actual live/receipt labels, без ошибок/overflow. Checker не менял credentials/config и не отключал реальные интерфейсы CHR.2 CHR доступны по последнему native182; новые native commands API-checker0, messages0.
Следующий185 — оценка покрытия периода при пропусках и смене идентичности/пересоздании интерфейса. Подтверждённые bytes остаются учтённым объёмом, не полным billing за период; восстановление идентичности по одному имени не доказано.12.5/внешние интеграции открыты. Локальный коммит без push.
## 12.5.185 — граница доверия скорости после пропусков: baseline (2026-10-12)
Блок начат; реализация и приёмка не завершены. [Чистый read-only пример](ux-ui/acceptance/traffic-gap-baseline-2026-10-12.json) проверил один и тот же достоверный delta1MiB между двумя counters с интервалами30s,90s,1h,24h. Учтённый объём во всех случаях1MiB — корректное свойство counter difference. Но observations.rxNow=true также для среднего за1h/24h; длительность последнего интервала пока не влияет на доверие текущей скорости. Это не native monitor-traffic: среднее за интервал не доказывает instantaneous rate в конце интервала.4 baseline cases не являются4 новыми принятыми production сценариями.
| Интервал | Текущий mask сейчас | Что проверить |
| --- | --- | --- |
|30s/90s | true | допустимый предел относительно trafficSettings.intervalSec |
|1h/24h | true | текущая скорость unknown при слишком длинном интервале; history и known bytes сохраняются |
Точный следующий шаг: передавать длительность последней пары measurements в provenance и ограничить current counter-derived rate согласованным пределом относительно collector period. Аналогичный guard нужен в snapshot collector, чтобы новое чтение после длительного сбоя не объявляло старое среднее текущей скоростью. Подтвердить normal/threshold/long gap/recovery/reset на собственном SQL/HTTP и UI. Не подменять average/unknown нулём и не менять actual SSE monitor rate. Отдельно остаётся неоднозначность пересоздания интерфейса с прежним именем и увеличившимся counter: существующая sample identity не доказывает непрерывность.
Стенд остаётся backend ux-history184/frontend ux-warning183, source/runtime184 не менялись. Аудит не обращался к CHR/DB, writes0/native commands0, пароли/конфигурация не менялись. Состояние сохранено локальным коммитом без push для продолжения185 после сброса лимита.
## 12.5.185 — доверие текущей скорости после длительного пропуска (2026-10-13)
Завершает baseline185 от2026-10-12. Builder сообщает measurementIntervalMs последней пары counter samples; для агрегата используется максимальный интервал всех составляющих, отсутствие interval в одной из новых составляющих даёт null. applyTrafficFreshness разрешает текущую counter-derived скорость только при положительном конечном interval≤3×max(5s,configured period). Это тот же запас3периода, что у TTL. При периоде30s граница90s включительно; более длинный или неизвестный интервал даёт unknown и понятную причину. Историческое среднее и подтверждённые counter bytes сохраняются.
Collector использует тот же предел в observedTrafficRate: после длинного пропуска snapshot не содержит sumRxMbps/sumTxMbps как измеренную текущую скорость. Следующая нормальная пара восстанавливает current, включая measured0. Native SSE monitor-traffic не изменён; native link status не зависит от длительности counter pair. Legacy вручную сформированная meta без interval сохраняет прежнюю совместимость; production builder выдаёт interval/null явно. Это не подтверждение native identity или полного billing за период.
| Состояние | Схема | Проверка |
| --- | --- | --- |
|30s/90s | свежая пара → current | unit threshold |
|90.001s/1h/24h | history+known bytes → текущая скорость неизвестна | unit, own SQL, UI1440/320 |
| Новый poll после пропуска | нормальная пара → current0 допустим | own collector/SQL recovery |
Unit threshold/invalid interval/merge/collector guards, backend/application TypeScript и ESLint passed.6 E2E14.7s (2new gap+2binding freshness+2peer warnings) passed. UI использует существующий ReUI Alert/base-nova без новой темы или компонентов. [Owned SQL](ux-ui/acceptance/traffic-gap-sql-2026-10-13.json):58 cases9counter+14history+10TCP SSE+10volume+15status/37008ms, no unavailable skip.3 новые cases: API сохраняет1MiB/history при120s gap, API recovery30s возвращает current и2MiB, actual fixture collector long gap не выдаёт current sum и второй poll подтверждает0. Первоначальный SQL запуск выявил fixture duplicate PK при переносе всех исторических timestamps; fixture оставляет только последнюю волну перед сдвигом. Ошибка не выдана за passed, обе временные базы/роли удалены. Последняя ownDB mm_accept_166_1791827374886/role/container удалена и отсутствие проверено.
[Source456/524](ux-ui/acceptance/traffic-gap-source-2026-10-13.json)/[compiled1040](ux-ui/acceptance/traffic-gap-compiled-2026-10-13.json) SHA256 parity. Backend production ux-gap185 [healthy/imageIds](ux-ui/acceptance/traffic-gap-runtime-2026-10-13.json), frontend ux-warning183 без исходных изменений/повторной сборки. Только backend.env tag, rollback backend ux-history184/frontend ux-warning183; secret env copy0, migration0. [Actual API](ux-ui/acceptance/traffic-gap-api-2026-10-13.json)/[production UI1440/320](ux-ui/acceptance/traffic-gap-deployed-2026-10-13.json) passed с actual live и backend receipt labels, no errors/overflow. Checker не отправлял новых native commands и не создавал отказ на CHR. Password/config/message changes0.
Следующий186 — provenance native interface/peer identity и конфигурации источника: positive counter difference по одному прежнему имени не доказывает непрерывность после пересоздания/смены устройства. Старую историю не переписывать по догадке. Общая12.5 и внешние зависимости остаются открыты. Локальный коммит без push.
## 12.5.186 — подтверждение идентичности пары счётчиков (2026-10-13)
Имя интерфейса больше не является единственным основанием новой counter pair. Nullable native_counter_identity хранит нормализованные source.updatedAt и native RouterOS.id (*HEX). Producer подтверждает continuity только когда identity непустая и совпадает с предыдущей строкой того же interface/peer key. Новый native ID, конфигурация источника или missing/invalid ID дают первую pair unknown; следующий подтверждённый poll восстанавливает измерение. Для WG используются peer.id и существующий public-key/iface series key, не ID самого интерфейса.
Биты16/32 различают confirmed continuity и сам факт проверки новым producer; running/disabled/counter/status markers не меняют смысла. Builder исключает неподтверждённую или несовпадающую pair из новых rates/bytes, сохраняя остальные подтверждённые исторические пары. Первый корректный counter остаётся baseline для следующей pair, даже если его собственная предыдущая continuity неизвестна. Legacy rows не переписываются: absent new marker/native identity оставляет прежнюю явно ограниченную историю. Это не доказательство непрерывности legacy, повторного использования того же native ID после перезагрузки или физической доступности.
| Изменение | Схема результата | Проверка |
| --- | --- | --- |
| Same name, новый native ID | old counter → unknown boundary → новый baseline → confirmed0 | own SQL interface+peer |
| Config version изменилась | не переносить counter pair между источниками → normal next poll | own SQL |
| Missing native ID | новые pair unknown, без guessed zero/bytes | own SQL/unit |
Миграция0012 добавляет nullable TEXT к partitioned traffic_samples, включая существующие partitions; нет массового UPDATE/переписывания flags. Downgrade старого reader может игнорировать новый столбец, migration removal не выполнялась. Реальный backup/restore с новой колонкой — следующий187, пока не принят данным блоком.
Unit identity/config/legacy-marker/pair guards, backend/application TypeScript и diff checks passed. [Own PG SQL](ux-ui/acceptance/traffic-identity-sql-2026-10-13.json):62 cases9counter+14history+10TCP SSE+10volume+19status/37613ms, no skip.4 новые cases: interface ID replacement/config version/missing ID/peer ID replacement с positive counters, unknown boundary, no extra bytes и последующим measured0. Fixtures явно объявляют native IDs; VM actual-collector unit получил настоящий identity/peer parser dependencies вместо отсутствовавших globals. Первая попытка остановилась до SQL scenarios на прежнем VM fixture; временная база/role удалены. Последний namespace mm_accept_166_1791828561251/role/container удалён, absence verified.
[Source458/524](ux-ui/acceptance/traffic-identity-source-2026-10-13.json)/[compiled1040](ux-ui/acceptance/traffic-identity-compiled-2026-10-13.json) SHA256 parity. [Backend ux-identity186](ux-ui/acceptance/traffic-identity-runtime-2026-10-13.json) healthy/imageIds; frontend ux-warning183 без изменений/новой сборки. Only backend.env tag, rollback backend ux-gap185/frontend ux-warning183; additive migration остаётся. Secret env copy0.
[Native GET](ux-ui/acceptance/traffic-identity-native-2026-10-13.json): оба CHR доступны, interface native IDs/flags/counters валидны;0012 applied. Peers фактически0 — positive peer replacement доказан изолированным fixture, не реальным VPN-туннелем. DB read-only/RouterOS config writes0/password changes0/messages0. [Initial API](ux-ui/acceptance/traffic-identity-api-2026-10-13.json) ожидаемо unknown при первом baseline после нового writer; [штатное восстановление](ux-ui/acceptance/traffic-identity-recovery-2026-10-13.json) подтвердило current/rxKnown/txKnown обоих CHR с30s interval без manual collector invocation. [Production UI1440/320](ux-ui/acceptance/traffic-identity-deployed-2026-10-13.json) actual live/receipt labels/no errors/overflow. Native SSE не изменён; предшествующие6E2E185 UI guard checks не пересчитываются как новые186.
Следующий187 — own-schema archive restore для nullable native counter identity/continuity flags и старого schema archive с повторным bootstrap migration. Потом отдельная приёмка многопроцессной координации/масштаба/внешних доступов.12.5 открыта. Локальный коммит без push.
## 12.5.187 — совместимость архивов после миграции counter identity (2026-10-13)
[Воспроизводимый runner](../backend/scripts/acceptance/traffic-identity-restore.mjs) проверяет namespace/role/current_database до операций; допускает только отдельную mm_accept_166_* базу с ограниченной ролью. Реальные pg_dump/pg_restore/psql18.6 работают с ней через restorePartitionedDatabase из production ux-identity186: archive decode → known-parent preparation → one transactional psql. Production database/env не копируются и не восстанавливаются. Архивы/SQL остаются внутри временного контейнера, только публичный JSON сохранён в Git.
[4 принятых случая](ux-ui/acceptance/traffic-identity-restore-2026-10-13.json): старый schema archive возвращает отсутствие native_counter_identity; последующий bootstrap добавляет0012 с NULL identities и прежними flags13/counters0,1024 без догадки; новый archive возвращает identity и markers45/61/counters0,1024 после удаления собственных rows; partitioned parent/child restore и migration record0012 остаются корректными. Старый archive fixture сформирован исключительно в собственной базе удалением новой nullable колонки и0012 record: это совместимый pre-0012 shape, не реальный пользовательский backup. Positive native fields — контролируемые fixtures, не counter proof устройства.
| Архив | Схема результата |
| --- | --- |
| Pre-0012 fixture | old schema/data → restore → bootstrap0012 → identityNULL, flags unchanged |
| Native identity fixture | dump → собственные rows удалены → actual restore → exact identity/flags/counters |
PostgreSQL server/client18.6, Node22 from production image; отдельный test-client image на официальном postgres:18 собран с проверкой Node/pg_dump. Docker socket в контейнер не передавался. Script SHA256 совпал с локальными байтами. ESLint passed. OwnDB mm_accept_166_1791829512285/role/container удалены, независимая проверка catalog/container absence passed. Рабочие3 контейнера и их runtime186/183 не менялись, реальных серверных/network writes/messages0; отдельная приёмка PostgreSQL restore в полном API/RBAC/multi-writer сценарии этим коротким тестом не заявляется.
Следующий188 — временный состав измерений: текущая реализация сравнивает количество известной wave с количеством всех series за период. Проверить rename/delete/add interfaces и active sessions, чтобы старый ряд не делал текущий срез навсегда unknown, а новое измерение без baseline не превращалось в measured0. Историю сохранить; причины absent object/optional peer failures и multi-instance остаются явными ограничениями.12.5 открыта. Локальный коммит без push.
## 12.5.188 — состав временных измерений после изменения интерфейсов (2026-10-13)
[Baseline/fixed](ux-ui/acceptance/traffic-wave-baseline-2026-10-13.json): при удалении одного ряда прежний186 builder навсегда оставлял current unknown и sessions2, хотя последний complete native wave содержал1 интерфейс.188 даёт current known/sessions1 с теми же4096 accounted bytes. Теперь expected count определяется для каждой wave, если все её строки имеют declared continuity marker нового producer. Счётчик активных интерфейсов берётся из последней такой wave. Legacy без marker сохраняет консервативный общий count; отсутствие строки не объявляется нулём по догадке.
Новый интерфейс без предыдущего baseline присутствует в expected count, но не в known pair sum: current остаётся unknown до следующей пары. Rename оставляет отдельный baseline нового имени, byte gap не додумывается, обе подтверждённые исторические части сохраняются. Declared confirmed continuity с NULL/empty native identity не доверяется. Поиск latest wave не использует неограниченный spread массива timestamps.
| Сценарий | Результат |
| --- | --- |
| Delete/rename старого series | latest complete wave снова current; stale series не увеличивает current sessions |
| Новый interface с единственным counter | unknown sum, current active count включает интерфейс |
| Следующая confirmed pair с0delta | measured0 допустим |
Unit membership deletion/addition/baseline/zero/history и backend build passed. [Own PG SQL](ux-ui/acceptance/traffic-wave-sql-2026-10-13.json):65 cases9counter+14history+10TCP SSE+13volume+19status/38880ms, без skip.3 новые GET detail cases: deletion и rename возвращают known current/history/correct active count; добавление одного baseline оставляет current unknown. Markers/native-identity strings этих cases — собственные controlled fixtures, не native device mutation. OwnDB mm_accept_166_1791830718064/role/container удалены и отсутствие проверено.
[Source460/524](ux-ui/acceptance/traffic-wave-source-2026-10-13.json)/[compiled1040](ux-ui/acceptance/traffic-wave-compiled-2026-10-13.json) SHA256 parity; [backend ux-membership188](ux-ui/acceptance/traffic-wave-runtime-2026-10-13.json) healthy/imageIds, frontend ux-warning183 unchanged/no rebuild. Only backend.env tag, rollback ux-identity186, migration0/secret env copy0. [Actual API](ux-ui/acceptance/traffic-wave-api-2026-10-13.json)/[browser1440/320](ux-ui/acceptance/traffic-wave-deployed-2026-10-13.json) current/live/receipt/no errors/overflow passed. Реальные interfaces/пароли не менялись, messages0; rename/delete проверены собственным SQL dataset, не выданы за native VPN tunnel test.
Следующий189 — collector после отключения/смены источника между /interface и optional peer request: source.enabled/updatedAt должны проверяться перед каждой следующей командой и перед публикацией успешной записи. Live SSE уже проверяет каждую команду179. Затем проверить temporal peaks/частичные bins отдельно; этот блок не принимает sum-of-individual-peaks за общий одновременный пик.12.5 открыта. Локальный коммит без push.
## 12.5.189 — прекращение фонового опроса при изменении источника (2026-10-13)
Collector теперь повторно читает enabled/updatedAt по ID перед /interface, после его ответа до cache, перед /wireguard/peers, перед INSERT samples и перед успешной receipt. Выключенный/удалённый/изменённый источник прекращает цикл с явной причиной. Форма source check одинакова для всех типов серверов, Home exception отсутствует. Уже отправленный native request невозможно отменить задним числом; guard препятствует следующему request и публикации известного устаревшего результата. Межпроцессная атомарность source edit/native call/DB commit не заявляется.
[Owned PG SQL](ux-ui/acceptance/traffic-sourceguard-sql-2026-10-13.json):67 cases9counter+14history+10TCP SSE+13volume+21status/39536ms, no skip.2 новые cases обновляют own server.enabled/config внутри первого loopback HTTP handler до его ответа: snapshot.ok=false, peer request count не растёт, samples count не меняется. Сервер re-enabled только в own fixture для следующего case. Actual-collector VM граница стала поддерживать limit() read, unit и backend build passed. OwnDB mm_accept_166_1791831842508/role/container удалены, absence verified.
| Событие | Схема |
| --- | --- |
| Source выключен/config changed во время first request | завершение in-flight read → guard → no peer request/cache/new rows/ok receipt |
| Source неизменён | read → verify → validated rows → verify before publication |
[Source460/524](ux-ui/acceptance/traffic-sourceguard-source-2026-10-13.json)/[compiled1040](ux-ui/acceptance/traffic-sourceguard-compiled-2026-10-13.json) SHA256 parity passed. [Backend ux-sourceguard189](ux-ui/acceptance/traffic-sourceguard-runtime-2026-10-13.json) healthy/imageIds, frontend ux-warning183 unchanged. Only backend.env tag, rollback ux-membership188; migration0/secret env copy0. [Actual API](ux-ui/acceptance/traffic-sourceguard-api-2026-10-13.json)/[browser1440/320](ux-ui/acceptance/traffic-sourceguard-deployed-2026-10-13.json) passed current/live/receipt/no errors/overflow. Real CHR не отключались/не перенастраивались; passwords/messages changes0.
Следующий190 — пик не должен вычисляться из partial/unconfirmed aggregate wave. Разные времена индивидуальных пиков user bindings также требуют отдельной temporal aggregation, а сумма индивидуальных максимумов не является общим одновременным максимумом.12.5 и внешние dependencies остаются открыты. Локальный коммит без push.
## 12.5.190 — пик только по подтверждённым волнам периода (2026-10-13)
Builder раньше брал максимум всех numeric points, включая partial wave с неизвестным вкладом нового интерфейса и точки за пределами range. Теперь RX/TX peak учитывает только свой observed flag, полный expected count соответствующей wave и timestamp внутри выбранного периода. Known bytes остаются учтёнными даже когда общий мгновенный срез неполон: это отдельные достоверные counter deltas, а не known whole-wave sum.
Unit проверил partial high point → последующая complete0 wave: current известен, observed peak0,1MiB volume сохранён. Future point вне range не повышает peak. [Own PG](ux-ui/acceptance/traffic-peak-sql-2026-10-13.json):68 cases9counter+14history+10TCP SSE+14volume+21status/38553ms, no skip.1 новый actual GET case с known native identity fixtures проверяет exact0 peak/current, history и сохранение1MiB после partial high wave. Own namespace/role/container removed и отсутствие проверено.
[Source460/524](ux-ui/acceptance/traffic-peak-source-2026-10-13.json)/[compiled1040](ux-ui/acceptance/traffic-peak-compiled-2026-10-13.json) SHA256 parity; backend build passed. [Backend ux-peak190](ux-ui/acceptance/traffic-peak-runtime-2026-10-13.json) healthy/imageIds, frontend ux-warning183 unchanged/no rebuild. Only backend.env tag, rollback ux-sourceguard189; migration0/secret env copy0. [Actual API](ux-ui/acceptance/traffic-peak-api-2026-10-13.json)/[browser1440/320](ux-ui/acceptance/traffic-peak-deployed-2026-10-13.json) passed actual live/receipt/no errors/overflow. RouterOS config/password/message changes0; никаких deliberate failures на реальных CHR не вводилось.
| Срез | Результат |
| --- | --- |
| Частичная high wave | не участвует в общем observed peak |
| Complete known0 wave |0peak/current допустим, accumulated known bytes retained |
| Point вне range | не влияет на peak периода |
Следующий191 — mergeBuiltTraffic пока суммирует индивидуальные пики частей, которые могли происходить в разное время. Нужно воспроизвести async peaks и определить общий пик по подтверждённым временным срезам с явным unknown при отсутствии совместимого времени.190 не выдаётся за исправление этого отдельного случая. Полный billing/coverage, scale/multi-instance/external integrations и12.5 остаются открыты. Локальный коммит без push.
## 12.5.191 — общий пик нескольких привязок: baseline (2026-10-13)
Блок начат, реализация/приёмка не завершены. [Read-only baseline](ux-ui/acceptance/traffic-aggregate-peak-baseline-2026-10-13.json) воспроизводит A=100Mbps на первой wave и B=100Mbps на следующей. Каждый индивидуальный peak100; mergeBuiltTraffic возвращает200, но complete combined wave builder показывает100. Учтённые объёмы совпадают. Это дефект временной агрегации пика, не потеря byte counters. Данные/стенд не менялись, writes0/native commands0.
Точный следующий шаг: общий peak вычислять из подтверждённых совпадающих временных срезов, сохраняя исходные timestamp/confidence внутренних parts; не складывать индивидуальные maxima. При отсутствии совместимого времени показывать неизвестное значение, сохраняя volumes/history/current metadata. Проверить разные времена peaks, совпадающий peak, missing contributor, jitter/неполные bins и recovery. Не подменять raw point peak максимумом bucket average без явной семантики. Нужны meaningful own SQL/API/UI cases перед production rollout.
Стенд остаётся backend ux-peak190/frontend ux-warning183. Source/runtime190 и real CHR/config/passwords unchanged; messages0. После191 — scoped control затронутых разделов и одна согласованная общая регрессия; внешние Portal/Telegram/client OS/multi-WAN/scale требуют доступов/сценариев из матрицы.12.5 открыта. Локальный commit без push сохраняет точное продолжение.
## 12.5.191 — подтверждённый общий пик привязок: реализация и приёмка (2026-10-13)
Исправлен baseline ниже: индивидуальные максимумы в разные моменты больше не складываются. A=100Mbps на первой волне и B=100Mbps на следующей дают общий пик100, совпадающие интервалы —200. Сумма byte deltas/учтённый объём сохранена. Пик является максимумом подтверждённых средних скоростей соседних счётчиков за совпадающие интервалы, а не мгновенным максимумом линии или максимумом chart bucket average.
Исходные интервалы и confidence parts хранятся во внутреннем WeakMap и не попадают в DTO/JSON. Merge, включая вложенный, требует совпадения начала и конца интервала и подтверждённых вкладов всех выбранных привязок для каждого направления. Jitter, отсутствие part, несовместимые интервалы или сериализованные parts без исходных точек не доказывают общий пик: observations.rxPeak/txPeak=false, UI показывает «—», а не ложный ноль. Подтверждённый ноль остаётся0. Для старого backend новый reader сохраняет прежнюю совместимость при отсутствии новых optional flags; interop проверен до переключения backend. История, объём и freshness metadata сохраняются. Данные разных серверов не интерполируются и не сдвигаются ради создания искусственного общего пика.
Изменены traffic-rate.ts, lib/traffic-observations.ts и профильные тесты. ReUI PRO/base-nova/Frame/KpiStatGrid переиспользуются, vendor/theme/layout не менялись. Проверены different/coincident peaks, nested merge, measured zero, missing/empty/legacy parts, jitter внутри одинаковых chart bins, одинаковый конец с разным началом и recovery. Реальный PostgreSQL/API fixture добавляет3 сценария пользователя с двумя привязками, включая неизменный объём750000000bytes. Все71 профильных SQL-проверок прошли41228ms без postgres-unavailable skip; собственные временная БД, роль и контейнер удалены.
Backend build и frontend TypeScript passed. Все77 уникальных E2E трафика прошли1.6m; начальные4 focused cases22.4s входят в77 и повторно не считаются. Production backend/frontend build passed; source manifests совпали461 backend+524 frontend файлов,1040 compiled backend artifacts совпали. Runtime backend/frontend ux-peak191, PostgreSQL healthy; frontend healthcheck отсутствует, работа подтверждена HTTP/browser. До backend rollout новый frontend принят с backend190. Actual API200 и fresh measurements обоих CHR, live UI1440/320 без page errors/overflow. Native конфигурация/пароли не менялись, messages0.
Протоколы: [SQL](ux-ui/acceptance/traffic-peak191-sql191-result.json), [source](ux-ui/acceptance/traffic-peak191-source191-result.json), [compiled](ux-ui/acceptance/traffic-peak191-compiled191-result.json), [runtime](ux-ui/acceptance/traffic-peak191-runtime191-result.json), [API](ux-ui/acceptance/traffic-peak191-peak191-api-result.json), [E2E](ux-ui/acceptance/traffic-peak-e2e-2026-10-13.json), [interop](ux-ui/acceptance/traffic-peak-interop-2026-10-13.json), [live UI](ux-ui/acceptance/traffic-aggregate-peak-deployed-2026-10-13.json).
| Референс | Схема |
| --- | --- |
| [ReUI Stats12](https://reui.io/preview/base/stats-12?ref=mcp) | Совпадающие интервалы всех привязок → подтверждённая сумма → максимум периода; нет совпадения → «—», объём сохранён |
Следующий192: одна согласованная общая backend-регрессия; фиксировать реальные skipped/external ветки отдельно. Последующий объём определяется результатом этой проверки и матрицей внешней приёмки. Portal/Telegram/client OS/multi-WAN/scale не приняты по fixture-тестам.12.5 открыта.
## 12.5.193 — трафик пользователей: одно чтение истории общего сервера (2026-10-13)
Устранены повторные одновременные SELECT истории при Promise.all пользователей. Cache раньше заполнялся только после await, поэтому100 пользователей с общим сервером успевали начать100 независимых чтений. Теперь Promise сохраняется перед await, потребители используют одну выборку этого сервера в рамках текущего запроса. Cache не сохраняется между запросами/периодами; другой serverId читает собственные данные. Ошибка распространяется как прежде, следующий запрос выполняет новое чтение и восстанавливается. Это не глобальный cache и не обещание транзакционно согласованного snapshot всех серверов/каталога.
Изменён traffic-users.ts, добавлен traffic-users-cache.test.ts в профиль traffic-rate. Проверка выполняет actual function body из исходника с подменой DB boundaries:100 concurrent consumers →1 server history read, unchanged1024bytes/user, новый запрос →новое чтение, другая serverId →отдельная выборка, failure/recovery. Это подтверждение call count алгоритма, не production SQL benchmark. Реальный профиль PostgreSQL/API прошёл все71 SQL cases41959ms без unavailable skip, включая100 bindings/user, volume/temporal peak/source/freshness. Собственные DB/role/container удалены.
Backend build passed. Production backend ux-peak193/version1.0.0-test.peak193 развёрнут, frontend ux-peak191 сохранён.462 backend source files и1040 compiled artifacts совпали. Frontend не пересобирался; его источник/production bundle остаются подтверждёнными191. Backend/PG healthy, frontend HTTP/browser passed. Actual API200 и current measurements обоих CHR, live UI1440/320 без page errors/overflow. Native конфигурация и пароли не менялись, messages0.
Протоколы: [cache](ux-ui/acceptance/traffic-users-cache-2026-10-13.json), [SQL](ux-ui/acceptance/traffic-users193-sql193-result.json), [source](ux-ui/acceptance/traffic-users193-source193-result.json), [compiled](ux-ui/acceptance/traffic-users193-compiled193-result.json), [runtime](ux-ui/acceptance/traffic-users193-runtime193-result.json), [API](ux-ui/acceptance/traffic-users193-peak193-api-result.json), [live UI](ux-ui/acceptance/traffic-users-cache-deployed-2026-10-13.json).
Общая регрессия192 начата на backend191; её24 backend профиля passed, текущий cache193 отдельно принят полным traffic-rate профилем. Не повторять общие неизменённые разделы. Полный браузерный прогон1286 ещё выполняется — не считать его завершённым. Исправлена ссылка live UI191: его evidence теперь хранится отдельно от исторического190, исходный протокол190 восстановлен. Следующий шаг — завершить192, разобрать ошибки полного E2E и восстановить только снимки текущего тестового запуска с сохранением8 исходно изменённых пользовательских PNG. Затем multi-instance/scale и внешние группы матрицы.12.5 открыта.
## 12.5.194 — трафик: координация опроса разных backend-процессов (2026-10-13)
На независимых Node-процессах подтверждён baseline: локальный collecting не препятствовал двум одновременным опросам одного источника и двум записанным волнам общей БД. Проверка использует собственную временную PostgreSQL БД и HTTP-эмулятор RouterOS на127.0.0.1, реальные CHR не менялись. [Baseline](ux-ui/acceptance/traffic-concurrency-baseline-2026-10-13.json).
Добавлена nonblocking session advisory lock8723105 на весь collectTrafficOnce в пределах общей PostgreSQL БД. Второй процесс возвращает существующий skipped snapshot до чтения настроек/истории, native GET и записи samples/receipt. Manual API уже преобразует skipped в409 «Сбор трафика уже выполняется», существующая семантика scheduler сохранена. Отложенная очередь опросов не создаётся. Локальный collecting сохранён для быстрых повторов внутри процесса. Неопределённый ответ acquisition не запускает run, соединение уничтожается; unconfirmed/failed unlock тоже уничтожает соединение вместо возврата в pool. Ошибка получения блокировки возвращает fatal snapshot без ложного успешного сбора.
Изменены traffic-collector.ts, добавлен traffic-collection-lock.ts и профильные unit/owned SQL tests. Actual collector body test обновлён под wrapper, не заменён копией алгоритма. Проверены busy/no work, malformed acquisition, run error, unlock false/error и destroy. Два настоящих процесса: первый удерживает HTTP-чтение, второй завершается skipped без второго запроса и samples; после первого следующий процесс выполняет новый опрос — lock released/recovery. SQL profile принял все71 ранее определённых cases и дополнительную cross-process sequence53237ms без unavailable skip; не считать её произвольным количеством новых тестов. DB/role/test container удалены. Production backend build passed;465 source files и1044 compiled artifacts совпали.
Backend ux-peak194/version1.0.0-test.peak194 развёрнут, frontend ux-peak191 сохранён. Backend/PG healthy, frontend HTTP/browser passed. API200, current measurements обоих CHR, live UI1440/320 без page errors/overflow. Native конфигурация/пароли не менялись, messages0.
Протоколы: [SQL](ux-ui/acceptance/traffic-lock194-sql194-result.json), [source](ux-ui/acceptance/traffic-lock194-source194-result.json), [compiled](ux-ui/acceptance/traffic-lock194-compiled194-result.json), [runtime](ux-ui/acceptance/traffic-lock194-runtime194-result.json), [API](ux-ui/acceptance/traffic-lock194-peak194-api-result.json), [live UI](ux-ui/acceptance/traffic-collection-lock-deployed-2026-10-13.json).
Границы: принято отсутствие параллельного traffic run при двух исправных process/session в одной БД, не координация всех writers приложения. Физическая потеря lock connection во время native GET/записи других pool connections не проверена; session lock не является fencing token. Не считать этот блок полной multi-instance/restore-drain/failover приёмкой. Следующий шаг — закончить и разобрать общую E2E192; затем отдельные multi-instance failures и внешние зависимости матрицы.12.5 открыта.
## 12.5.192 — общая регрессия после накопленных изменений (2026-10-13)
Завершена одна согласованная общая проверка:24 профиля backend из test:all прошли321237ms на собственной временной PostgreSQL БД с ограниченной ролью. Набор выполнялся на источнике191; backend193 request cache и194 collection lock после этого отдельно приняты актуальными полными traffic-rate SQL-профилями, build/source/compiled/API/live UI. Общие неизменённые разделы повторно не запускались. Протокол не приравнивает количество profiles к числу assertions или native операций.
В исходном общем прогоне были3 реальные skip-сообщения: Monthly SQL, IPv6 UDP/worker/SQL и replay сохранённого CHR Ping payload. Они проверены отдельно: Monthly на собственной БД mm_accept_149_* подтвердил5 точных месячных интервалов, leap-year и exclusion outside rows; IPv6 на собственной mm_accept_144_* прошёл через собранный production worker с UDP/SQL/minute-hour-day totals и shutdown; Ping replay использовал сохранённый публичный payload без новых команд CHR. Первая IPv6 попытка на TypeScript worker harness не загрузила src/db/index.js; это ошибка запуска harness, исправлена запуском того же теста в JavaScript с реальным compiled worker. Не скрывать исходный отказ и не выдавать loopback UDP за public IPv6 WAN. DB/roles/containers всех проверок удалены, production DSN не копировался.
Frontend:59 lib test files прошли с одной исправленной устаревшей проверкой dashboard-readers.test.ts. Ранее тест запрещал series:[null]; актуальная модель Ping намеренно допускает пропуски и переводит legacy measurements в unknown. Исправлен только тест: unknown/null проверен положительно, отрицательная/NaN series остаются rejected. Повторно прошли2 reader tests и4 соседних probe tests; runtime source/семантика не менялись. Scoped ESLint passed.
Общий настроенный браузерный набор:1286 уникальных сценариев в217 файлах passed1936347ms (32.3min), unexpected0/skipped0/flaky0. Включены77 сценариев трафика; их повторные focused/full runs не прибавляются к1286. Настроенные testIgnore context suites и внешние native сценарии в эту цифру не входят. Промежуточный сигнал ошибки по форматированному выводу не подтвердился: итоговый JSON содержит0 unexpected.125 исходно чистых отслеживаемых screenshots, перезаписанных тестами, восстановлены;8 исходно изменённых пользовательских PNG сохранены отдельно и восстановлены с проверкой SHA256. Пользовательские skills/AGENTS/config не включались в commits.
Протоколы: [backend profiles](ux-ui/acceptance/general192-owned192-result.json), [monthly SQL](ux-ui/acceptance/general192-special-149-result.json), [IPv6 pipeline](ux-ui/acceptance/general192-special-144-result.json), [Ping replay](ux-ui/acceptance/general192-ping-replay-result.json), [frontend units](ux-ui/acceptance/general-frontend-units-2026-10-13.json), [E2E](ux-ui/acceptance/general-e2e-2026-10-13.json).
Актуальный стенд backend194/frontend191, backend/PG healthy; production API и live UI приняты в194. Debian161.104.46.222 имеет только loopback/link-local IPv6, public IPv6/default IPv6 route отсутствуют по read-only проверке. Настоящие Portal SSO/Telegram/client OS/independent WAN/scale и полный distributed writer/restore drain не закрыты общей fixture-регрессией. Следующий195 — отдельная bounded failure/recovery проверка межпроцессного опроса; внешние группы требуют соответствующих стендов/параметров.12.5 остаётся открытой.
## 12.5.195 — реальный Portal1.3.1 и доставка Telegram (2026-10-13)
По прямому поручению пользователя установлен предоставленный auth-portal1.3.1 на том же Debian-стенде. Исходник прочитан из git.shx.one/denozord/auth-portal, точный tagv1.3.1=2e947b5a31d7bd6c17aff8dba3917fabf6640b91; опубликованный образ закреплён digestsha256:2bdf42400a1b35caa43303b9d01078b054b2a9041eba7019c1fffde71b7e4489. Byte/compiled совпадение образа с исходником не заявлено. Отдельная SQLite/data и bootstrap admin, случайные собственные admin password/HS256 secret, JWT lifetime900s, issuer/portal http://localhost:5175, allowlist только localhost/127.0.0.1:3000. Portal доступен через loopback/SSH, не публичный порт. Исходный .env приложения не копировался и не переписывался: новая закрытая compose.override.yaml задаёт только Portal и AUTH_* overrides. Portal/backend/PG healthy, frontend running. Backend194/frontend191 сохранены, source build не требовался для настройки.
Настоящий login API выдал Portal JWT с appmm и ожидаемым issuer. Приложение работает с AUTH_REQUIRED=true: без JWT401, реальный admin200, читатель mm:servers:read GET200/валидный create POST403, пользователь без appmm GET/POST403, повреждённая подпись401. Настоящий browser без API mocks прошёл MM→Portal login→callback→dashboard→servers; токен записан в storage, fragment удалён, page errors0. Начальные UI-harness ожидания h1«Обзор/Серверы» не соответствовали существующему PageHeader с breadcrumbs; тест исправлен под реальные route/button, UI source не менялся. Два основных own пользователя и оставшиеся fixtures первых попыток удалены через Portal API; bootstrap admin сохранён для доступа к стенду.
Отзыв проверен с явной границей: revoke-all отменяет refresh sessions, disabled user не логинится/Portal me401. Уже выданный access JWT MikrotikManager продолжает принимать200 доexp, поскольку backend проверяет подпись/issuer/exp offline и не проверяет состояние пользователя в Portal. Это не мгновенное глобальное revoke. Реальное истечение900s, passkey/OIDC и физические client OS в этом блоке не приняты.
По предоставленным тестовым bot/chat_id сохранены параметры через штатный API под настоящим Portal JWT. До настройки groups/rules0/outbox0: старых сообщений для рассылки нет. Первая send попытка получила502/unknown: с Debian недоступен TCP443 на DNS endpoint149.154.166.110; getMe и curl подтвердили connection timeout. Проверенный TLS endpoint149.154.167.220 того же api.telegram.org доступен. Для backend добавлен временный lab-only extra_hosts; TLS verification не отключался, произвольный proxy/mirror не использовался. После getMe200 (botId совпал) одна контролируемая send через штатный API принята. Всего2 send requests: initial unknown и verified transport control; не утверждать, что неизвестная отправка доказанно не состоялась. Пользователь подтвердил получение текста «MikroTik Manager — тест оповещений (Telegram).». Токен находится в закрытой конфигурации/БД стенда, в Git/публичные отчёты не включён. Автоматические rule/recovery/outbox/retry delivery ещё отдельная приёмка.
Протоколы: [runtime](ux-ui/acceptance/portal195-runtime-2026-10-13.json), [actual JWT/RBAC/revoke](ux-ui/acceptance/portal-live-api-2026-10-13.json), [real browser SSO](ux-ui/acceptance/portal195-browser-admin-2026-10-13.json), [Telegram + human receipt](ux-ui/acceptance/telegram195-provider-2026-10-13.json). Данные входа bootstrap admin — локальный gitignored tmp/portal195-login.txt и закрытый файл стенда; секреты не публиковать в журнале.
Найден следующий196: настоящее reader JWT получает plaintext password CHR через GETservers. Подтверждён только boolean совпадения, секрет не выведен. Также authPortalBaseUrl для ссылки AppsMenu использует NEXT_PUBLIC_AUTH_PORTAL_URL сборки вместо текущего runtime Portal URL; hook switcher fetch уже использует runtime. Исправить оба API/UI недостатка, проверить reader/writer/admin и реальный Portal на ПК/телефоне, собрать/развернуть и создать локальный commit. Это ограничивает принятие приватности/навигации, но не отменяет доказанный базовый SSO/Telegram transport.
Пользователь подтвердил отсутствие public IPv6 на всех его стендах — внешняя IPv6 outer приёмка сейчас недоступна. Проверку crash/lock-connection loss из прежнего следующего195 перенести после Portal/Telegram.12.5 открыта.
## 12.5.196 — приватность серверов и согласованный runtime Portal (2026-10-13)
Реальное reader JWT в195 подтверждённо получало plaintext password CHR. Теперь serverReadForUser на HTTP list/detail возвращает password="" для пользователя без mm:servers:write/admin. Writer/admin и прежний AUTH_REQUIRED=false сохраняют existing DTO для редактирования. is_admin сам по себе не заменяет permission. Проекция создаёт копию и не меняет repository rows, хранимые/native credentials или работу collectors. Изменены servers-mapper.ts и два GET handlers routes/servers.ts; внутренние get/listServersRead остаются пригодными для native операций. Это защита этих endpoints, не аудит всех экспортов/secret-bearing DTO проекта.
authPortalBaseUrl теперь предпочитает runtime config, как существующий hook switcher fetch. Ссылка «Настроить на портале» больше не ведёт к build-time auth.shnt.top при отдельном тестовом issuer. ReUI PRO/base-nova/Frame/AppsMenu переиспользованы, vendor/стили/разметка не менялись. Unit подтвердил build fallback/runtime override/trailing slash.
Owned SQL test выполняет actual buildApp/auth middleware/handlers с подписанными test JWT на отдельной ограниченной роли: reader/writer/admin ×list/detail,401 безtoken, password вБД unchanged. Passed10996ms, own DB/role/container удалены. Новый test:server-privacy включён вtest:all, обычный прогон без явной own DB честно skip. Source TypeScript/backend build/scoped ESLint passed.41 unique E2E (runtime links2,header4,servers35) passed1.4m. Изолированные JWT не выдаются за реальный Portal: он проверен отдельно.
Production backend/frontend ux-peak196 развёрнуты.466 backend+525 frontend source files и1044 compiled backend artifacts совпали. Portal1.3.1/SQLite/shared lab secret и AUTH_REQUIRED=true сохранены новой закрытой Compose override; оригинальные credentials/.env не копировались. Реальный Portal admin API сохраняет необходимые поля редактирования, реальный reader list/detail не содержитпароль, валидная попытка создания403.4 live UI (reader/admin1440/320) безmocks/page errors/overflow: readonly control disabled, admin enabled, runtime Portal link http://localhost:5175/admin/apps. Собственные Portal users удалены. CHR config/passwords не менялись, новых Telegram send в196 нет.
Протоколы: [SQL](ux-ui/acceptance/portal196-sql196-result.json), [source](ux-ui/acceptance/portal196-source196-result.json), [compiled](ux-ui/acceptance/portal196-compiled196-result.json), [runtime](ux-ui/acceptance/portal196-runtime196-result.json), [fixture E2E](ux-ui/acceptance/portal196-e2e-2026-10-13.json), [actual Portal API](ux-ui/acceptance/portal-live196-api-2026-10-13.json), [live UI4](ux-ui/acceptance/portal196-live-ui-2026-10-13.json).
| Референс | Схема |
| --- | --- |
| [ReUI App Shell12](https://reui.io/preview/base/app-shell-12?ref=mcp) | Runtime issuer/Portal → меню приложений → тот же Portal; reader → masked DTO + blocked edit, writer → existing editor |
Следующий197: реальная доставка из outbox через собственную временную БД, dedupe/two senders, controlled lost receipt после реального Telegram acceptance, no automatic repeat, explicit acknowledged retry/stale version/RBAC. Планируется3 помеченных test messages, включая намеренный повтор№2; не превращать controlled receipt suppression в физическую WAN/lost-ACK приёмку. Portal JWT revocation доexp, настоящее expiry/refresh/client OS и crash/lock-loss остаются отдельными границами.12.5 открыта.
## 12.5.197 — доставка Telegram и управляемый повтор (2026-10-13)
Production compiled outbox проверен в собственной временной PostgreSQL БД и ограниченной роли, с реальными JWT Portal и тестовым Telegram bot/chat. Первый live прогон: enqueue с одинаковым dedupeKey сохранил одну запись; два независимых Node sender процесса выполнили одну отправку, одна запись sent и одна history. Telegram принял№2, затем драйвер намеренно подавил ответ: статус unknown, следующая автоматическая диспетчеризация не отправила сообщение повторно. Это контролируемая имитация потерянного ответа, не физический обрыв WAN.
Reader retry403, отсутствие acknowledgedDuplicateRisk400, admin expectedVersion0→1 с подтверждением риска200, повтор старой версии409. Однако завершающий assert первого полного live прогона sent=1 не прошёл; outcome тогда не был записан. Причина не установлена. Исходный failed протокол сохранён, цельный непрерывный live сценарий не объявляется пройденным. Для локализации полный сценарий с реальной БД/Portal JWT и симулированным Telegram ответом прошёл без сетевых отправок. Далее только оставшаяся ручная отправка проверена на новой собственной unknown fixture: Telegram accepted, status sent, resolutionVersion1, history одна. Это отдельный успешный live тест, не продолжение прежней БД.
Всего реально приняты3 сообщения: одно TEST197№1 и два одинаковых TEST197№2, последние являются намеренным повтором. Пользователь подтвердил именно это количество. Три own DB/role/container и собственные Portal reader users удалены; временный private bot file на сервере удалён. Рабочие настройки Telegram приложения сохранены для следующих пользовательских проверок. Пароли/конфигурация CHR не менялись, runtime остаётся ux-peak196. Драйвер не входит вtest:all, требует own DB, явный чат и подтверждение риска, имеет отдельный resume режим. Диагностика завершающей отправки теперь сохраняет outcome/статус; отрицательный provider response не превращается assert в искусственный unknown, счётчик учитывает начало request.
Протоколы: [первый partial/failed live](ux-ui/acceptance/telegram197-partial-2026-10-13.json), [полный SQL с simulated provider](ux-ui/acceptance/telegram197-dry-result-2026-10-13.json), [отдельный live retry](ux-ui/acceptance/telegram197-resume-result-2026-10-13.json), [итог и ограничения](ux-ui/acceptance/telegram197-summary-2026-10-13.json).
Следующий198: настоящий expiry/logout/reissue Portal и безопасный return_to. Первый непрерывный Telegram live сценарий остаётся диагностической границей; повторять его только при достаточной диагностике и основании, а не отправлять дополнительные дубли ради зелёного счётчика.12.5 открыта.
## 12.5.198 — срок действия Portal JWT, права и выход (2026-10-13)
Использован настоящий JWT, выданный Portal в195 и естественно истёкший к проверке: MM GET servers401, Portal me401 и reissue401. Токен не редактировался и TTL не менялся. На собственном временном reader через документированный PUT /api/v1/admin/users/:id/access удалён доступmm: прежний JWT по-прежнему200 доexp, reissue200 выдаёт текущие claims и новый MM JWT403. Возвращённый доступ и новый reissue восстановили200. Первый неверно адресованный PATCH в диагностическом драйвере был исправлен на PUT/access; изменение source продукта не требовалось. User fixture удалён204.
Logout200 очищает refresh cookie(Max-Age0), но ранее выданный bearer MM JWT остаётся200 и Portal reissue с ним также200 доexp. Это подтверждённая граница offlineJWT и Portal1.3.1: cookie/session logout не означает немедленный отзыв access token. Свежие JWT/credentials в Git не сохранялись.
Live UI1440/320 с настоящим expired JWT: MM очистил mmapp_token, направил на Portal, реальный login/callback восстановил приложение, fragment удалён, overflow/page errors нет. Однако callback открыл /dashboard вместо исходного /servers: контекст не сохранён, следующий199 исправляет это. Внешний https://outside.invalid/auth/callback не вызвал попытки навигации после login; Portal остался на /admin. Browser /logout очистил token storage и показал login. Защитный browser route только блокировал возможную недоверенную навигацию, ответы API не подменял.
Оставшиеся return_to на другой localhost port и похожий hostname не приняты: серия диагностических входов достигла rate limit Portal. HTTP GET / и /api/v1/auth/config подтвердили429 с Retry-After18/17s; это не объявлено ошибкой защиты return_to. Промежуточные успехи сохранены отдельно, полный UI прогон не claimed. Повторять только эти оставшиеся случаи после cooldown, без нового полного цикла. Source/runtime/ReUI не менялись.
Протоколы: [actual lifecycle API](ux-ui/acceptance/portal198-lifecycle-2026-10-13.json), [live UI и границы429](ux-ui/acceptance/portal198-live-ui-2026-10-13.json).
Следующий199: восстановить исходный same-origin раздел и query после SSO с проверкой permissions и запретом внешних/auth callback redirect. Затем профильные E2E/deploy и два оставшихся Portal return_to.12.5 открыта.
## 12.5.199 — восстановление раздела и параметров после SSO (2026-10-13)
Из198 подтверждено: expired session на /servers попадала после login в /dashboard. redirectToPortalLogin теперь добавляет исходный pathname+query в next callback URL. AuthCallbackPage после valid claims выбирает permittedAuthReturnPath и проверяет существующее permissionForPath/can; недопустимый путь или недостаточные права используют firstAllowedPath. При повторном handoff next сохраняется. JWT fragment не включается в сохранённый путь.
Новый pure helper отклоняет внешние/protocol-relative URL, backslash/control/space, слишком длинный путь, auth/api/access-denied loop, нормализованный dot traversal вauth и percent-encoded pathname. Query, включая percent-encoded filter values, сохраняется; hash удаляется. Консервативное ограничение касается pathname: приложение использует обычные фиксированные пути/ID; percent-encoded pathname не восстанавливается, выбирается fallback. Это не расширение существующей карты permissions и не замена backend RBAC.
Unit unsafe/normalization/query/permissions passed, frontend TypeScript и scoped ESLint passed.12 unique E2E/24971ms/0unexpected:10 query/denied/external/auth-loop/handoff cases1440/320 и2 runtime Portal links. Это fixtures, не реальные подписи Portal. Отдельно production frontend ux-portal199 собран и развёрнут,527 source files совпали перед build. Backend ux-peak196/Portal1.3.1/AUTH_REQUIRED=true сохранены.2 live UI с настоящим naturally expired JWT и login Portal1440/320 восстановили /servers?server=42&tab=details, fragment удалён, errors/overflow нет. CHR/native config и backend не менялись, новых Telegram sends нет.
Оставшиеся return_to198 проверены адресно: http://localhost:3001/auth/callback и http://localhost.evil.invalid:3000/auth/callback не вызывают external navigation, Portal остаётся /admin. Browser logout очищает storage. Предыдущий lookalike URL в драйвере был синтаксически ошибочным (порт3000.evil.invalid), поэтому login form отсутствовала; это исправлено в тесте. Подтверждённый429198 сохраняется в историческом протоколе, но не объявляется причиной этого отдельного malformed-URL сбоя. Повторные full cycles прекращены; реальные endpoints не mock. Доверенные allowlist origins сохранены.
Протоколы: [E2E12](ux-ui/acceptance/portal199-e2e-2026-10-13.json), [deployment](ux-ui/acceptance/portal199-deployment-2026-10-13.json), [actual expired recovery2](ux-ui/acceptance/portal199-live-ui-2026-10-13.json), [remaining return_to](ux-ui/acceptance/portal199-return-to-2026-10-13.json).
| Референс | Схема |
| --- | --- |
| [ReUI App Shell12](https://reui.io/preview/base/app-shell-12?ref=mcp) | Раздел + фильтры → expired session → Portal → callback с проверкой прав → тот же раздел + фильтры |
Следующий200: owned PostgreSQL/child-process crash и advisory-lock loss traffic collector. Цельный непрерывный Telegram live197 остаётся отдельно с исходным failed evidence; успешные chunk tests не отменяют его. Logout не отозвал offlineJWT доexp, publicIPv6/clientOS/independentWAN/scale остаются внешними ограничениями.12.5 открыта.
## 12.5.200 — восстановление коллектора после падения и потери блокировки (2026-10-13)
В отдельной own DB/ограниченной роли на Linux два сценария действительного сбоя: SIGKILL дочернего коллектора при удержанном ответе локального RouterOS fixture и pg_terminate_backend только собственного lock PID, выбранного по точным datname/usename/key8723105. Production PID/CHR не затрагивались. Старый production compiled ux-peak196 воспроизвёл Unhandled error event и nonzero exit при потере session-lock connection. После SIGKILL PostgreSQL освободил advisory lock, новый процесс собрал первую волну. Baseline не выдаётся за passed исправление.
withTrafficCollectionLock теперь слушает error/end dedicated client, фиксирует потерю соединения, уничтожает его и снимает listeners. Callback получает assertActive, helper проверяет его также после callback. collectTrafficRun проверяет active guard перед проходом/источником, после чтения source-state, перед итоговыми writes и в catch ветках; известная потеря lock больше не приводит к записи error/settings старого прохода. collectTrafficOnce возвращает fatal snapshot, collecting сбрасывается finally. Unit подтвердил error/end без unhandled event, guard abort, destroy/listener cleanup; прежние busy/acquire/unlock cases сохранились.
Production compiled ux-lock200 на own DB: SIGKILL recovery passed; lock connection terminated во время held native response — процесс survived, fatal snapshot, ноль новых traffic_samples, last_collected_at не переписан. Следующий независимый процесс успешно собрал новую волну.3 own DB/role/container (baseline/fixed/profile) удалены и отсутствие проверено.71 профильная SQL case + cross-process skip/release/recovery passed57603ms, TypeScript build и scoped ESLint passed. Перед build468 source files совпали,1044 compiled artifacts matched. Backend ux-lock200 healthy развёрнут, frontend ux-portal199/Portal/AUTH_REQUIRED сохранены.3 real API200 и live UI1440/320 — provenance/received live labels, noerrors/overflow. Native CHR config/passwords не менялись.
Граница: active guard реагирует на наблюдённые error/end; это не fencing token и не атомарная защита всех writes на других pool connections. Окно между проверкой и write, задержка TCP detection и физическая network partition остаются ограничениями. Уже отправленный native HTTP GET не отменяется; tested response fixture лишь удерживал ответ. Не объявлять гарантию exactly-once при произвольном разрыве.
Протоколы: [baseline](ux-ui/acceptance/lifecycle200-baseline-result.json), [fixed lifecycle](ux-ui/acceptance/lifecycle200-fixed-result.json), [SQL profile](ux-ui/acceptance/owned200-result.json), [compiled](ux-ui/acceptance/compiled200-result.json), [deployment/bounds](ux-ui/acceptance/lock200-deployment-2026-10-13.json), [live traffic](ux-ui/acceptance/traffic-lock200-deployed-2026-10-13.json).
Следующий201: цельный Telegram live197 с диагностикой начала requests/response codes/dispatch outcome/status и ограничением3 сообщений в собственном чате. Controlled lost receipt остаётся имитацией; первоначальный failed evidence не удалять.12.5 открыта.
## 12.5.201 — цельный живой сценарий очереди Telegram (2026-10-13)
Обновлён acceptance driver: ограниченный TEST label, request-start counters, safe HTTP status/accepted trace, dispatch outcome и финальная строка очереди; Telegram send pacing1500ms, отрицательные ответы provider не искажаются assertion в unknown. Драйвер не входит вtest:all, явный own DB/chat/duplicate-risk ACK обязательны, число live sends ограничено3 (resume1). Изменение только приёмочного инструмента; продуктовая очередь не менялась.
Actual production compiled backend ux-lock200, ограниченная PostgreSQL own роль и real Portal JWT. В одном непрерывном прогоне/одной БД: duplicate dedupeKey → одна запись; два независимых sender процесса → один provider send и одна sent/history. Telegram accepted№2, receipt intentionally suppressed → unknown; повторная автоматическая диспетчеризация не отправляет. Reader retry403, missing acknowledgement400, admin version0→1 pending200, stale retry409. После подтверждённого ручного retry Telegram accepted, sent1/failed0/held0, итог две sent строки/две history. Provider принял три сообщения TEST201(IDs6/7/8); пользователь подтвердил одно№1 и два№2.
Own DB/role/container и Portal reader user удалены, отдельный private bot file удалён; рабочие настройки приложения сохранены. Нативные CHR и runtime images не менялись, дополнительных отправок вне бюджета не было. Полный успешный201 теперь дополняет partial/failed197 и отдельный resume197; исходный failed evidence сохраняется. Точная причина первого сбоя197 не установлена: pacing/новая диагностика не выдаются за доказательство его причины или исправление продуктового дефекта. Controlled receipt loss не является физическим WAN timeout/доказательством exactly-once на стороне Telegram.
Протокол: [цельный live тест и подтверждение пользователя](ux-ui/acceptance/telegram201-live-2026-10-13.json). Следующий202 — reader API аудит секретов административных интеграций; широкие публичные IPv6/clientOS/independentWAN/scale/external jobs остаются в матрице.12.5 открыта.
## 12.5.202 — чтение административных интеграций без раскрытия секретов (2026-10-13)
На actual deployed ux-lock200 создан собственный Portal reader с mm:servers/alerts/backups/uptime/traffic:read, без writer/admin.10 real GET endpoints: servers, alerts, outbox, backup storage, uptime settings/speed probes, traffic flow settings, GeoIP200; EvoBGP settings/scheduler403. Для тех же10 endpoints безJWT401. Дополнительно server details200 с password пустым. Recursive response check не нашёл непустых password/botToken/token/apiKey/secretAccessKey/privateKey/licenseKey и известных CHR/bot test secrets. Значения credentials в evidence не сохранены.
Telegram в рабочем приложении действительно настроен и доставлял сообщения201: reader alerts DTO не содержит raw bot token. S3/EvoBGP secrets в текущем стенде не заполнены; их маскирование populated credentials не объявляется доказанным данным read-only прогоном. Source audit подтвердил DTO secretConfigured уbackup/EvoBGP, GeoIP только metadata, speedProbeRead безpassword. App config/credentials не менялись, native commands не запрашивались. Собственный reader удалён204. Вспомогательный драйвер сначала ошибся на JSON parsing пустого204cleanup; исправлен на nullable response body, actual removal уже произошёл; финальный прогон successful/cleaned.
Протокол: [actual reader API](ux-ui/acceptance/reader202-live-api-2026-10-13.json). Это scoped DTO audit10 endpoints, не аудит binary backup/cert export или произвольных embedded credentials в errors. Следующий203: собственная ограниченная PostgreSQL DB с синтетическими заполненными S3/EvoBGP/Telegram secrets, actual compiled handlers/JWT, без send/network probe.12.5 открыта.
## 12.5.203 — маскирование заполненных секретов интеграций (2026-10-13)
Actual compiled buildApp/auth/GET handlers ux-lock200 проверены на собственной ограниченной PostgreSQL роли/БД с непустыми синтетическими S3 secret access key, EvoBGP API key и Telegram bot token. JWT подписаны штатным Fastify тестовым RAM-secret/issuer: это изолированные test JWT, не real Portal login (реальный reader был проверен202). startScheduler=false, global fetch запрещён и считает обращения.
9 проверок reader/admin/noJWT ×backup storage/EvoBGP settings/alerts: разрешённые DTO200 содержат secretConfigured/tokenConfigured=true, но не сохранённые секреты. Reader EvoBGP403, безJWT401. Хранимые значения всех3 секретов неизменны, externalRequests0. S3 provider local/EvoBGP disabled, реальных probe/send/job не выполнялось. Own DB/role/container удалены. Первый драйвер попытался импортировать dev-only jose из production image и не запустил cases; исправлен на штатный app.jwt.sign, никакой зависимости/продуктового кода не добавлялось. Оба временных окружения очищены. PostgreSQL выдал warning о concurrent query наclient в существующем repeatable-read alerts overview; это совместимо с текущим pg8, не объявлено pg9 acceptance.
Протокол: [owned SQL masks9](ux-ui/acceptance/secret203-sql-2026-10-13.json). Это scoped DTO proof, не S3 connectivity, EvoBGP execution, Telegram transport (принят201) или аудит всехexport/error text. Runtime не менялся. Следующий204: actual Portal reader/admin navigation основных разделов ПК/телефон после auth199, GET/overflow/page errors и отсутствие mutation requests.12.5 открыта.
## 12.5.204 — навигация основных разделов с реальными ролями (2026-10-13)
Actual Portal1.3.1 issued admin/own reader JWT, deployed frontend ux-portal199/backend ux-lock200.13 разделов: dashboard, servers, uptime, traffic, statistics, WireGuard, IPsec, GRE, VXLAN, BGP, OSPF, alerts, backups ×reader/admin×1440/320 =52 scoped live сценария. Перед проверкой каждого маршрута дождались HTTP200 его профильного API (dashboard использует servers read gate), а не только общего header/auth config. Сохранены успешные пути API и non200 ответов нет. Reader server Add disabled/admin enabled; fragment отсутствует, JavaScript errors0, overflow нет, mutation requests0.
Первый диагностический обход проверял любой shared GET200 и был недостаточен для подтверждения data fetch; финальный52 усилен specific endpoint ожиданием. Counts не складываются. API/Portal ответы не mock, JWT storage seed использует реально выданный token. Своя reader fixture удалена204. Tunnel/form actions не выполнялись и новые native объекты не создавались; обычные GET могут опрашивать RouterOS. Это проверка navigation/session/section API/адаптивности после общих auth changes, не полная приёмка каждой формы/native state или throughput.
Протокол: [live navigation52](ux-ui/acceptance/section204-live-navigation-2026-10-13.json). Source/runtime не менялись. Следующий205: scoped automated WCAG-tagged audit data sections(light/dark,ПК/телефон) на реальном приложении; не считать его полным WCAG сертификатом.12.5 открыта.
## 12.5.205 — контраст живых данных и предупреждения целей (2026-10-13)
Actual admin Portal JWT, без API mocks: traffic/alerts/backups ×light/dark×1440/320, axe-core4.11.3 tags WCAG2A/AA,2.1A/AA,2.2AA вmain-content иосновной навигации. Baseline выявил4 failing combinations: light traffic RX/TX2.07–3.76:1 иlight alerts warning4.32:1 при требовании4.5:1. Dark иbackup passed. Baseline сохранён, не переписан successful result.
В app traffic6 numeric spans RX/TX теперь используют semantic text-foreground; стрелки/графики/форматеры сохранены. AlertsTargetIssues переиспользует установленный ReUI Alert вместоlegacy UI Alert, предупреждениеvariant warning/role status исуществующее содержимое сохранены. Vendor/shared theme не менялись. API прочитан через ReUI MCP: [docs](https://reui.io/docs/components/base/alert?ref=mcp), [preview](https://reui.io/components/alert?ref=mcp). Замечание axe ксерой кнопке «Обновить» перепроверено после actual enabled state: initial snapshot был вtransition загрузки. Стили кнопки не менялись, финальный тест ждёт завершения загрузки данных, ане исключает contrast rule.
TypeScript/scoped ESLint passed;25 unique E2E34060ms,0unexpected/skips (target warning +shell accessibility/keyboard/layers).4 clean shell screenshots восстановленыпослетеста,8 исходных dirty GRE/VXLAN скриншотов сохранены. Production build/source527 matched, frontend ux-accessibility205 развёрнут, backend ux-lock200/Portal/AUTH_REQUIRED сохранены. Повторный actual tagged audit12/12 безviolations, includinglight numbers/warning. Incomplete checks сохраняются вprotocol, не объявлены passed WCAG критериями. Это default visible admin states, не полный WCAG сертификат, manual keyboard audit всехforms или reader dialogs.
Протоколы: [baseline](ux-ui/acceptance/accessibility205-baseline-2026-10-13.json), [fixture E2E25](ux-ui/acceptance/accessibility205-e2e-2026-10-13.json), [live audit12](ux-ui/acceptance/accessibility205-live-2026-10-13.json), [deployment](ux-ui/acceptance/accessibility205-deployment-2026-10-13.json).
Следующий206: actual live keyboard/focus для общихmenus итиповых Dialog/Sheet, ПК/телефон/роли, безapply/native mutation.200 collector loss реагирует только наobserved errors/end (неfencing);201 whole Telegram accepted, initial197 cause unproven.12.5 остаётся открытой из-за остальныхграниц внешней матрицы.
## 12.5.206 — живая клавиатура и возврат фокуса (2026-10-13)
Actual Portal reader/admin JWT, deployed frontend ux-accessibility205/backend ux-lock200.6 сценариев ×1440/320×reader/admin =24: Tab skip-link→main-content; Enter/ArrowDown/Escape apps menu; Enter/Escape system monitor; keyboard server row menu иEscape возврат; reader Add disabled/admin server create Dialog; GRE history Sheet выбранного enabled CHR. Вdialog/sheet Tab проходит числоfocusable controls+3 иShift+Tab3, фокус остаётся внутри, Escape возвращает original trigger. Форму не заполняли/не применяли, config restore не нажимали, mutations0/page errors0/nooverflow; собственный Portal reader удалён204.
Первоначальная мгновенная проверка DOM containment после Tab иногда видела асинхронный focus transition Base UI; финальный тест ждёт стабильногоcontainment черезpoll. Product focus code не менялся. Это проверка listed states, не full keyboard/screen-reader certification всехформ. Source/runtime unchanged. Протокол: [actual keyboard24](ux-ui/acceptance/keyboard206-live-2026-10-13.json).
В source review обнаружено: GRE caller не передаёт существующий restoreDisabled вобщий ConfigHistorySheet, defaultfalse. Backend write guard не отменяет необходимость корректного UI. Следующий207 — аудит всехcaller иread-only/disabled/device state запреты кнопки отката, профильныеfixtures иlive UI безapply.12.5 открыта.
## 12.5.207 — права отката общей истории конфигураций (2026-10-13)
Actual Portal reader настаром frontend ux-accessibility205 видел50 enabled restore buttons GRE; безнажатия подтверждёнbaseline.5 из6 ConfigHistorySheet caller не передавалиrestoreDisabled,defaultfalse. Теперь propобязателен, defaulttrue дляuntyped omission; GRE/WireGuard/IPsec/Filters/Firewall передаютpermission/device/busy guards. Recursive routes ужеимелиguard. Reader требуетnetwork:write (Filters filters:write), disabled/missing device запрещаетaction; GRE/IPsec/Firewall используютexisting readiness guards. Callbacks пятиcaller повторно проверяютpermission непосредственно передrequest. ШаблоныReUI/Timeline/Sheet/vendor unchanged; текст объясняет недоступностьотката.
Перваяширокая Filters readiness condition заблокировала прежнийдопустимыйretry послеapplied+failed read.3 regression failures обнаружены иисправлены: Filters используетpermission/enabled/operation guards, stale/failed read не добавляетновый запретrollback. Существующие правиласетевыхопераций сохранены.40 unique E2E(24 role/devicefixtures+16 existing restore/error/retry/lock),68987ms,0unexpected/skips. TypeScript/ESLint0errors;12 старыхunused import warnings Filters не менялись. Native apply толькоmocked tests, наCHR откатне выполнялся.
Production frontend ux-history207/source527 matched, backend ux-lock200/Portal/AUTH_REQUIRED сохранены.24 actual live UI6sections×reader/admin×1440/320 наpopulated historical metadata: readerbuttons disabled, adminenabled послеstable device read, informativecopy, nooverflow, Escape→trigger, mutationrequests0. Первыйadminrecursive check сделан доокончанияread ивиделcorrect temporarybusy; тестисправлен наожиданиеready, productguard неослаблялся. Own Portal users удалены204. Credentials/native configs не менялись.
Протоколы: [live baseline](ux-ui/acceptance/history207-baseline-live-2026-10-13.json), [E2E40](ux-ui/acceptance/history207-e2e-2026-10-13.json), [live24](ux-ui/acceptance/history207-live-2026-10-13.json), [deployment](ux-ui/acceptance/history207-deployment-2026-10-13.json). Следующий208: source GET WireGuard includePrivateKey флагне проверяетwrite permission; scoped nativekey privacy +read-only network workspaces.12.5 открыта.
## 12.5.208 — приватные ключи WireGuard и режим просмотра сетевых разделов (2026-10-13)
Старый production backend выдавал синтетический непустой приватный ключ reader при GET WireGuard с includePrivateKey=1/true. Baseline подтверждён actual compiled auth/mapper на собственной ограниченной PostgreSQL БД и локальном RouterOS HTTP fixture. Теперь явный запрос приватного ключа требует mm:network:write/admin, иначе403 до любых native requests. Обычный GET200 сохраняет public key и не содержит private key. is_admin без необходимого permission не заменяет право. Writer/admin сохраняют прежнее действие, legacy AUTH_REQUIRED=false не менялся.
WireGuard, IPsec, GRE, Firewall и Filters показывают режим просмотра и запрещают writer controls при read-only JWT. Использованы существующие readiness/mutation helpers; WireGuard toolbar/import/key-export/peer actions и callbacks дополнительно защищены. Backend RBAC остаётся авторитетной проверкой. Установленные ReUI primitives, vendor files и theme не менялись: добавлены operation-state props/copy.
11 fixed SQL cases: reader/writer/admin ×обычный GET/два private flags, is_admin alone, безJWT401; reader denied native request count0. Baseline/fixed/profile own DB/role/container удалены. WireGuard profile прошёл14.6s, включая56 node:test проверок; другие скрипты профиля не прибавляются к этому числу. Скопированный JSON label ошибочно называл traffic-rate, фактически runner запускал test:wireguard; label исправлен с сохранением originalReportedCommand. TypeScript/backend build/ESLint0errors,12 старых warnings Filters остаются.53 unique E2E:20 readonly PC/mobile +33 history/readiness/refresh. Два первоначальных GRE writer failures были некорректной fixture без обязательного ipsec:null; исправлены только данные теста,20 повторных cases прошли. Повторы не складываются.
Backend/frontend ux-native208 развёрнуты;470/527 source files и1044 compiled artifacts совпали, backend healthy. На каждом CHR через реальный admin API создан собственный WG-интерфейс с уникальным именем/свободным портом. Real reader обычный GET200 безключа, private flags403, admin получает ключ/public key сохранён. Private material вevidence не сохранялся.20 live UI5sections×reader/admin×1440/320 проверили создание/import/key-export controls, mutation requests0. Затем оба собственных интерфейса иPortal reader удалены; отсутствие интерфейсов проверено. Пароли и исходные native объекты не менялись. Это API privacy/UI proof, не WireGuard handshake/data-plane тест.
Протоколы: [baseline](ux-ui/acceptance/wireguard208-baseline-result.json), [fixed SQL11](ux-ui/acceptance/wireguard208-fixed-result.json), [profile](ux-ui/acceptance/native208-profile-result.json), [E2E53](ux-ui/acceptance/native208-e2e-2026-10-13.json), [live UI20](ux-ui/acceptance/native208-live-ui-2026-10-13.json), [native privacy/cleanup2](ux-ui/acceptance/wireguard208-native-live-2026-10-13.json), [compiled](ux-ui/acceptance/compiled208-result.json), [deployment](ux-ui/acceptance/native208-deployment-2026-10-13.json).
Следующий209: GRE mapper содержит ipsecSecret иipsec.secret, проверить оба публичных GET иограничить выдачу секретов reader, сохранив crypto-state/public metadata иwriter editing.12.5 открыта.
## 12.5.209 — доступ к GRE PSK и достоверность каталога IPsec (2026-10-13)
В production baseline читатель получал PSK через GET /gre/tunnels. Каталог /filters/gre-tunnels ключ не раскрывал, но всегда возвращал ipsec:null, скрывая сам факт настройки IPsec. Основной GET теперь копирует публичный DTO и очищает secret при отсутствии mm:network:write/admin; алгоритмы и наличие объекта IPsec сохраняются. Internal snapshot и право редактирования для writer/admin не меняются. is_admin без permission не даёт доступ к ключу. Legacy AUTH_REQUIRED=false сохранён. Общий каталог Filters возвращает только признак IPsec и пустой secret для всех ролей.
Экспорт скрытого PSK явно помечен как шаблон, содержит <IPSEC_PSK> и указание заменить ключ перед применением. Пустой ipsec-secret не подставляется как готовая конфигурация. Установленные ReUI компоненты и тема не изменялись.
Проверки: baseline и исправленный production backend — по 12 уникальных SQL/API-кейсов на собственных ограниченных PostgreSQL DB/role, с синтетическим PSK и настоящим auth middleware. Snapshot сохраняет исходный PSK; native writes 0. Оба комплекта DB/role/container удалены. Локальный test:live-maps, frontend TypeScript, backend build и ESLint прошли. Четыре E2E: скрытый ключ/шаблон на 1440 и 320px, прежние изменение/очистка PSK writer. Полную регрессию 192 не повторяли.
Backend/frontend ux-gre209 развёрнуты; 473/527 source files и 1048 compiled artifacts совпали, backend healthy. Live: по одному собственному отключённому GRE с PSK на каждом CHR, реальные Portal admin/reader JWT; reader не получает ключ, admin сохраняет его, каталог обеих ролей показывает IPsec без ключа. Четыре UI-кейса reader/admin × 1440/320, без API mocks и без UI mutations. Оба интерфейса и временный Portal user удалены; отсутствие интерфейсов проверено. Пароли и исходные объекты не менялись. Это проверка privacy/configured state, не шифрованного data plane.
Первоначальная сборка имела неверную ссылку на базовый Docker image; исправлена до развёртывания. Финальный frontend собран с mock=false и live default. Два первых native create отказали: опущенный keepalive превращался в 0, который RouterOS отклоняет. Cleanup прошёл; проверка завершена с явным 10s,3. Ошибка значения по умолчанию остаётся отдельным пунктом 210. Повторные проверки не складываются в число уникальных кейсов.
Протоколы: [baseline](ux-ui/acceptance/gre209-baseline-result.json), [fixed SQL/API](ux-ui/acceptance/gre209-fixed-result.json), [профиль](ux-ui/acceptance/gre209-profile-2026-10-13.json), [E2E](ux-ui/acceptance/gre209-e2e-2026-10-13.json), [native/UI/cleanup](ux-ui/acceptance/gre209-native-live-2026-10-13.json), [source](ux-ui/acceptance/source209-result.json), [compiled](ux-ui/acceptance/compiled209-result.json), [deployment](ux-ui/acceptance/gre209-deployment-2026-10-13.json).
Следующий блок 210: исправить создание GRE с опущенным keepalive, проверить фактический RouterOS ответ и прежнее редактирование. Этап 12.5 открыт; внешние ограничения в актуальной матрице сохраняются.
## 12.5.210 — GRE keepalive и совместимость публичного каталога (2026-10-13)
На обоих CHR собственные отключённые интерфейсы подтвердили: native REST отклоняет 0, none, пустую строку, disabled, no и ноль попыток. Дробные интервалы принимаются, но сокращаются RouterOS до целых секунд. Поэтому форма и write schema требуют целые значения 1..4294967295 вместо обещания «0 = откл.». Неверный ввод сохраняет форму и не отправляет запрос. Официальный default 10s,10: [MikroTik GRE](https://help.mikrotik.com/docs/spaces/ROS/pages/24805531/GRE).
Опущенные параметры создания теперь дают 10s,10; один заданный параметр сохраняется, второй получает default. Основной GET и каталог Filters используют общий разбор native единиц/clock: 1m = 60с, 1m30s = 90с. PATCH без параметров keepalive сохраняет исходную строку snapshot, не преобразует таймер при изменении комментария/PSK. Legacy snapshots не переписаны; произвольные legacy/unknown timers и их экспорт не приняты этим блоком.
Аудит потребителей выявил несовместимость 209: shared schema Filters допускала только ipsec:null. Теперь она принимает {secret:""} или null, отвергает реальный ключ. Карта сохраняет configured IPsec; Filters и диагностика используют обновлённую схему. ReUI primitives и theme не менялись.
Проверки: 24 direct native syntax cases на отключённых собственных GRE, с очисткой; production SQL/API14 на собственной ограниченной DB/role, включая 8 invalid cases до native requests, четыре создания, сохранение native timer и чтение минут. SQL DB/role/container удалены. Профиль live-maps, schema unit, 5 network-map units, TypeScript/backend build/ESLint прошли. 13 уникальных E2E: GRE формы/PSK/валидация9 и Filters gateway/retry4. Копии fixtures имеют configured IPsec; прежние повторные действия сохранены.
Runtime ux-gre210: backend healthy, source475/527 и compiled1048 matched. На каждом CHR приложение создало отключённый GRE без keepalive и с явным allowFastPath=false для PSK; native default10s,10 подтверждён. После native 1m,3 GET показывает60с, PATCH комментария сохраняет1m,3, explicit0 даёт400 без изменения native. Два UI GRE и два UI Filters на1440/320 проверили форму, отсутствие запроса при invalid input и доступность собственного GRE с IPsec в каталоге шлюзов. Оба интерфейса удалены, отсутствие проверено. Пароли не менялись; это не data-plane test.
Два первых create с PSK и опущенным allowFastPath получили502: текущий API default FastPath несовместим с PSK. Это отдельное обнаруженное ограничение, не скрытое успешным повтором; дальнейшая проверка задала false явно. Следующий приоритет211 — подтверждённый обход auth через encoded API prefix. После него исправить FastPath/PSK default и экспорт недопустимого/неизвестного keepalive.
Протоколы: [native syntax](ux-ui/acceptance/gre210-native-range-2026-10-13.json), [дополнительный синтаксис](ux-ui/acceptance/gre210-native-range-extra-2026-10-13.json), [SQL/API14](ux-ui/acceptance/gre210-keepalive-result.json), [профили](ux-ui/acceptance/gre210-profile-2026-10-13.json), [E2E13](ux-ui/acceptance/gre210-e2e-2026-10-13.json), [native/UI/cleanup](ux-ui/acceptance/gre210-native-live-2026-10-13.json), [source](ux-ui/acceptance/source210-result.json), [compiled](ux-ui/acceptance/compiled210-result.json), [deployment](ux-ui/acceptance/gre210-deployment-2026-10-13.json).
## 12.5.211 — JWT/RBAC для закодированных URL (2026-10-13)
Actual baseline: обычный /api/servers без JWT возвращал401, но /%61pi/servers возвращал200 и server rows с непустыми паролями. Fastify распознаёт encoded static segments; middleware сравнивал raw URL и пропускал auth для encoded /api prefix. Для encoded имени раздела можно было также получить fallback dashboard permission. В evidence сохранены только статусы, число строк и boolean наличия пароля; raw body, credentials и JWT не сохранялись и не выводились.
Общий preHandler и requireAuth теперь используют request.routeOptions.url — фактически выбранный Fastify маршрут. Проверка public auth config/health сохранена; percent decoding не выполняется повторно вручную. Permission mapping OSPF принимает доверенные parameter templates наряду с прежними numeric paths; HEAD получает те же read permissions, что GET. Политики ролей и AUTH_REQUIRED=false не расширены. Frontend и RouterOS конфигурация не менялись.
42 канонических auth fixtures: encoded static prefix/раздел, GET/HEAD/PATCH, denied handler count0, OSPF reader/preview и servers-only denial, public config/health. Прежние test:auth, GeoIP JWT и NetFlow private export guards прошли; backend build прошёл. Изменена общая auth-основа, поэтому добавлены профильные проверки разных ресурсов и параметризованных маршрутов; полный UI regression192 не повторялся для backend-only изменения.
Production compiled SQL/API29 на собственной ограниченной DB/role: anonymous401, dashboard-only403, network reader/writer GET и PSK redaction, denied PATCH403 до native, public config200. Native writes0; DB/role/container удалены. Backend ux-auth211 развёрнут healthy; source477 и compiled1048 совпали. Frontend ux-gre210 сохранён. Live26 с настоящими Portal JWT: анонимные GET/HEAD401, обычные/encoded server и GRE GET по ролям, пустой PATCH403. Пустое тело гарантирует отсутствие native apply даже при ошибке защиты. Два временных Portal user удалены; секреты не публиковались. Пароли CHR не менялись.
Протоколы: [actual baseline](ux-ui/acceptance/auth211-baseline-live-2026-10-13.json), [профиль](ux-ui/acceptance/auth211-profile-2026-10-13.json), [production SQL/API29](ux-ui/acceptance/auth211-production-result.json), [live26](ux-ui/acceptance/auth211-live-2026-10-13.json), [source](ux-ui/acceptance/source211-result.json), [compiled](ux-ui/acceptance/compiled211-result.json), [deployment](ux-ui/acceptance/auth211-deployment-2026-10-13.json).
Следующий212: GRE create с PSK и опущенным FastPath, explicit incompatible combination, экспорт недопустимого/неизвестного keepalive. 12.5 остаётся открытой по внешней матрице.
## 12.5.212 — GRE PSK/FastPath (2026-10-13)
Результат, проверки и ограничения: [полная запись212](ux-ui-progress.md#125212--совместимость-gre-pskfastpath-и-шаблоны-экспорта-2026-10-13). Runtime ux-gre212, SQL/API18, E2E10, native/UI и cleanup подтверждены; auth211 сохранён.
## 12.5.213 — GRE IPv6 export (2026-10-13)
Статический внутренний ULA и IPv6 fragment проверены на двух CHR и четырёх live UI. Backend ux-gre212, frontend ux-gre213; собственные интерфейсы/адреса/user удалены. Подробности и ограничения: [блок213 в журнале](ux-ui-progress.md). Public IPv6 и произвольный RSC import не приняты.
## 12.5.214 — GRE badge contrast (2026-10-14)
Подробности: [блок214 в журнале](ux-ui-progress.md). Scoped axe4 и live UI8 прошли; cleanup подтверждён. Backend ux-gre212, frontend ux-gre214.
## 12.5.215 — OSPF/BFD (2026-10-14)
Пять legacy endpoints возвращают503 при неполном опросе. Успешные envelopes сохранены; SQL25/localHTTP25 и live API/UI приняты. Подробности и границы — [журнал](ux-ui-progress.md#125215--явные-ошибки-legacy-ospfbfd-api-2026-10-14). Backend ux-ospf215, frontend ux-gre214; следующий216 — legacy BGP.
## 12.5.216 — BGP snapshots (2026-10-14)
Неполный BGP poll больше не считается успешным пустым ответом/снимком. GRE при ошибке BGP сохраняется. Production17 и реальный API/UI приняты. Подробности и границы — [журнал](ux-ui-progress.md). Backend ux-bgp216, frontend ux-gre214; следующий217 — WAN runtime.
## 12.5.217 — WAN runtime (2026-10-14)
Read failures/malformed collections дают502, выключенные устройства409 без native poll, empty success сохранён. Production15 и реальная сверка API/native прошли. Подробности и границы — [журнал](ux-ui-progress.md). Backend ux-wan217, frontend ux-gre214; следующий218 — routing table accessibility.
## 12.5.218 — заполненные routing tables (2026-10-14)
BGP/OSPF contrast: baseline22/fixed104 cells0 violations; E2E22 и real UI8 passed. Own GRE/OSPF/BGP objects удалены; статическая сверка10×2 прошла. Подробности и границы — [журнал](ux-ui-progress.md). Frontend ux-routing218, backend ux-wan217; следующий219 — GRE snapshot source errors.
## 12.5.219 — GRE snapshot source (2026-10-14)
Ошибки GRE source отражаются в snapshot; BGP при GRE failure сохраняется. SQL/native10 и actual compiled source2own GRE/UI passed; временные объекты удалены. Подробности и границы — [журнал](ux-ui-progress.md). Backend ux-gre219, frontend ux-routing218; следующий220 — неизвестные GRE flags.
## 12.5.220 — GRE operational flags (2026-10-14)
Общий reader catalog/config/alerts не подменяет неизвестные flags. Production30/local49 и цельный native lifecycle/Ping/source/UI прошли, own objects удалены. Первичный401 сохранён, причина неизвестна. Подробности и границы — [журнал](ux-ui-progress.md). Backend ux-gre220, frontend ux-routing218; следующий221 — GRE identity guards.
## 12.5.221 — GRE native identity (2026-10-14)
Общий identity boundary предотвращает fallback IDs/names и false config revisions. Local13/flags49, production22 и real source/API/UI passed; own objects удалены. Первичный500 сохранён, причина неизвестна. Подробности и границы — [журнал](ux-ui-progress.md). Backend ux-gre221, frontend ux-routing218; следующий222 — общая backend/профильная UI регрессия.
## 12.5.222 — backend/worker регрессия (2026-10-14)
Backend25/UI52, disabled33/months5 и оба IPv6 UDP/SQL worker режима прошли; own DB/roles удалены. Dev bootstrap исправлен, production entry сохранён. Подробности и границы — [журнал](ux-ui-progress.md). Backend ux-regression222, frontend ux-routing218; следующий223 — актуализация матрицы/статусов.
## 12.5.223 — текущая сводка (2026-10-14)
Runtime backend ux-regression222/frontend ux-routing218. Latest backend25/UI52 и специальные SQL/UDP222 passed; Portal/Telegram приняты195–201 в записанных границах. Остаток —7 групп в [плане](ux-ui-plan.md). Следующий224 — краткое наблюдение REST; источник причины единичных401/500 пока неизвестен.
## 12.5.224 — REST выборка (2026-10-14)
160 readonly requests: первый CHR80/80×200, второй78/80×200 и2 initial401; последний цикл200 обоих. Root cause/SLA не приняты, services/credentials не менялись. [Отчёт](ux-ui/acceptance/chr224-rest-observation-2026-10-14.json). Следующий225 — transient REST/auth диагностика104.
## 12.5.225 — диагностика REST с двух точек (2026-10-14)
36/36 GET200 с workstation/Debian. Часы согласованы; www max-sessions20 не доказывает нагрузку, retained failures9/890 не частота отказов. От Debian0, последние сторонние SSH/FTP не объясняют исходные401. Root cause неизвестна; mutations/services/credentials unchanged. [Workstation](ux-ui/acceptance/chr225-workstation-2026-10-14.json), [Debian](ux-ui/acceptance/chr225-debian-2026-10-14.json). Следующий226 — свежая общая UI-регрессия.
## 12.5.227 — Android full-tunnel подготовлен, приёмка ожидается (2026-10-14)
Реальный клиент mm-phone227/194.226.121.150, VIP198.18.227.250, NAT/full-tunnel policy, CA/server/client2дня;16 own objects intentionally retained, cleanup pending. Chain/password protection verified; профиль/пароль только ignored tmp, JWT удалён. Android Internet/Ping ещё не приняты; результаты пользователя и S3 credentials ожидаются. UI226 выполняется. [Подготовка](ux-ui/acceptance/android227-preparation-2026-10-14.json).
### Завершение Android227 — 2026-10-14
Пользователь подтвердил сайты/внешнийIPv4/Ping и повторное подключение. Все16 own objects удалены; исходные поля13 коллекций preserved, оба CHR доступны. Native sample0 peers/SA не синхронизирован с телефоном, packet counter proof отсутствует. [Приёмка/границы](ux-ui/acceptance/android227-human-acceptance-2026-10-14.json).
## 12.5.226 — общий UI-набор и scoped recovery (2026-10-14)
1366 unique accepted:1364 primary passed/2 failed,5/5 rerun recovered2. Whole fresh zero-failure run не заявляется. Сохранены364 исходных screenshots, изменён только artifact path GRE/VXLAN теста; application/runtime unchanged. [Итог](ux-ui/acceptance/general226-ui-regression-2026-10-14.json). Далее228 — S3 prerequisites.
## 12.5.228 — S3 runner подготовлен, реальная проверка ожидается (2026-10-14)
11 safety/dry-run checks passed, network0. Helper использует compiled S3 client, harmless own UUID prefix2 objects, HTTPS/explicit live guards и cleanup только attempted keys. Application jobs/native restore/versioned retention не приняты. Требуются endpoint/region/bucket/keys/path-style. [Guard протокол](ux-ui/acceptance/s3-guard-preflight-2026-10-14.json).
## 12.5.228–229 — Selectel S3/client/API/owned SQL приняты (2026-10-14)
2 roundtrip objects,12 unique API scenarios, synthetic native export/CHR contacts0. Own DB/roles/catalog/localfiles/currentobjects cleaned. Versioning Enabled:8versions+8markers removed,3 own prefixes remaining0; bucket configuration unchanged. Native backup/restore/live UI/смена storage origin/retention semantics остаются230. Private env удалены, secrets не в published files. [API](ux-ui/acceptance/s3-application229.json), [version cleanup](ux-ui/acceptance/s3-version-cleanup229.json).
Локальные .rsc после235: `/opt/mmapp-test/data/backups` → `/app/storage/backups`; см. [порядок переноса](../deploy/BACKUP-STORAGE.md). Две новые native copies после force-recreate проверены и удалены; десять старых catalog rows сохранены с зафиксированным отсутствием files.