feat(mcp): подготовить сервер и доступ к приёмке
This commit is contained in:
commit
bf3d50e1ff
3835 files changed
+537122
No files matched your search
@@ -0,0 +1,60 @@
|
||||
# Интеграция auth-portal ↔ MikrotikManager
|
||||
|
||||
App id: **`mm`**. Зеркало на стороне портала: [`auth-portal/docs/integrate-mikrotikmanager.md`](https://git.shx.one/denozord/auth-portal/src/branch/main/docs/integrate-mikrotikmanager.md).
|
||||
|
||||
## Flow
|
||||
|
||||
```
|
||||
Browser → MikrotikManager UI (нет token)
|
||||
→ redirect AUTH_PORTAL_URL/?return_to=…/auth/callback
|
||||
→ login
|
||||
→ redirect return_to#access_token=…
|
||||
→ /auth/callback сохраняет token (localStorage: mmapp_token)
|
||||
→ API Authorization: Bearer <JWT>
|
||||
```
|
||||
|
||||
## Permissions
|
||||
|
||||
| Permission | UI / API |
|
||||
|------------|----------|
|
||||
| `mm:dashboard:read` | `/dashboard`, sidebar-counts |
|
||||
| `mm:servers:read` / `write` | `/servers` |
|
||||
| `mm:filters:read` / `write` | filters / GRE |
|
||||
| `mm:bgp:read` / `write` | BGP |
|
||||
| `mm:uptime:read` / `write` | `/uptime` |
|
||||
| `mm:traffic:read` / `write` | `/traffic` |
|
||||
| `mm:alerts:read` / `write` | `/alerts` |
|
||||
| `mm:backups:read` / `write` | `/backups` |
|
||||
| `mm:certificates:read` / `write` | certificates |
|
||||
| `mm:network:read` / `write` | network / OSPF |
|
||||
| `mm:settings:admin` | `/settings`, system DB, scheduler |
|
||||
|
||||
## Env
|
||||
|
||||
```env
|
||||
# backend
|
||||
AUTH_REQUIRED=true
|
||||
AUTH_JWT_SECRET=<тот же JWT_SECRET портала>
|
||||
AUTH_ISSUER=https://auth.shnt.top
|
||||
AUTH_PORTAL_URL=https://auth.shnt.top
|
||||
CORS_ORIGIN=https://mm.shnt.top
|
||||
```
|
||||
|
||||
```env
|
||||
# frontend build (Docker)
|
||||
NEXT_PUBLIC_AUTH_PORTAL_URL=https://auth.shnt.top
|
||||
```
|
||||
|
||||
UI читает `GET /api/auth/config` (через Next rewrite) для `required` / `portal_url`.
|
||||
|
||||
В portal Admin → Apps выдайте app `mm` и нужные `mm:*`. URL в App Switcher: `https://mm.shnt.top`.
|
||||
|
||||
## Checklist
|
||||
|
||||
1. Общий `JWT_SECRET` / `AUTH_JWT_SECRET` и одинаковый `AUTH_ISSUER`
|
||||
2. Origin MM в `RETURN_TO_ALLOWLIST` портала
|
||||
3. Пользователю выдан app `mm`
|
||||
4. `AUTH_REQUIRED=true` на backend
|
||||
5. Logout → `{AUTH_PORTAL_URL}/logout`
|
||||
|
||||
Prod: [`deploy/docker-compose.cdn-mm.yml`](../deploy/docker-compose.cdn-mm.yml) или standalone Traefik compose.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Логи MikroTik
|
||||
|
||||
Раздел `/logs` использует общую панель выбора серверов, как `/filters` и `/firewall`.
|
||||
История хранится в PostgreSQL; live читает уже сохранённые события через SSE.
|
||||
|
||||
## Включение
|
||||
|
||||
При следующем запуске backend автоматически применяется миграция `0014_router_logs.sql`.
|
||||
В «Сбор данных → Логи MikroTik» администратор включает сбор. По умолчанию он выключен,
|
||||
фоновый интервал — 10 секунд, хранение — 14 дней. Настройки требуют `mm:settings:admin`;
|
||||
журнал, контекст, статистика и экспорт — `mm:servers:read` (также write/admin этой секции).
|
||||
|
||||
При открытом live выбранный включённый MikroTik опрашивается раз в 2 секунды.
|
||||
Вкладки разделяют опрос; одновременно опрашиваются не более четырёх устройств.
|
||||
Целевая задержка при штатной нагрузке — до 5 секунд. Ошибки сети вызывают backoff до минуты.
|
||||
«Все серверы», выключенные и удалённые устройства доступны в режиме истории.
|
||||
|
||||
Коллектор читает только buffer=memory и не меняет правила RouterOS. После очистки,
|
||||
перезагрузки или переполнения буфера возможны пропуски. Потеря пересечения снимков
|
||||
помечается как возможный разрыв без выдуманного числа пропущенных событий. Время без
|
||||
явного часового пояса не интерпретируется как UTC: журнал использует отмеченное время
|
||||
получения и сохраняет исходную строку RouterOS.
|
||||
|
||||
События удаляются пакетами по времени получения. Очистка продолжает работать и при
|
||||
выключенном сборщике. Дедупликация хранит SHA-256 отпечатки, а не копии сообщений.
|
||||
Удаление устройства не удаляет его историю; повторно открыть её можно по ссылке
|
||||
`/logs?server=<id>` или через общий журнал. Новые таблицы входят в полный `pg_dump`.
|
||||
Планировщик и фоновые задачи ожидаются, а SSE закрываются перед обслуживанием БД.
|
||||
Перед закрытием поток получает `reset`: интерфейс предлагает заново загрузить историю
|
||||
после обслуживания, чтобы не продолжать старый курсор поверх восстановленной БД.
|
||||
|
||||
## Интерфейс и ReUI PRO
|
||||
|
||||
Сохранены компоненты и стиль проекта base-nova. Исходники блоков получены из
|
||||
лицензионного реестра ReUI и адаптированы под RouterOS; демонстрационные данные,
|
||||
изменения инфраструктуры и workflow review из блоков не используются.
|
||||
|
||||
- Основа таблицы, toolbar и графика: [Infra Audit Log](https://reui.io/blocks/solutions/dev-ops/solution-dev-ops-2), [превью](https://reui.io/preview/base/solution-dev-ops-2).
|
||||
- Панель записи, исходные поля и контекст: [Audit Event Detail](https://reui.io/blocks/application/sheet/sheet-14), [превью](https://reui.io/preview/base/sheet-14).
|
||||
- [Data Grid API](https://reui.io/docs/components/base/data-grid), [превью](https://reui.io/components/data-grid).
|
||||
- [Filters API](https://reui.io/docs/components/base/filters), [превью](https://reui.io/components/filters).
|
||||
- [Frame API](https://reui.io/docs/components/base/frame), [превью](https://reui.io/components/frame).
|
||||
- [Badge API](https://reui.io/docs/components/base/badge), [превью](https://reui.io/components/badge).
|
||||
|
||||
Фильтры между полями соединяются AND, значения уровня/topics — OR. Поиск сообщения
|
||||
регистронезависимый, буквальный. «Ошибки входа» — явно обозначенный текстовый шаблон.
|
||||
Представления хранятся локально с привязкой к пользователю и backend. Экспорт CSV/JSON
|
||||
применяет те же фильтры; выборки свыше 50 000 записей отклоняются с предложением сузить
|
||||
период. Формулы spreadsheet в CSV нейтрализуются.
|
||||
|
||||
При прокрутке и открытии записи обновление видимой таблицы приостанавливается, но
|
||||
сбор продолжается. Буфер отображения ограничен 5 000 строками; более ранние записи
|
||||
доступны через период/экспорт. Смена сервера/источника/фильтров отменяет старые запросы.
|
||||
|
||||
## Проверки
|
||||
|
||||
- `npm --prefix backend run build` — contracts и backend.
|
||||
- `npm --prefix backend run test:logs` — дедупликация, нормализация, фильтры, CSV, JWT/RBAC и REST-совместимость терминала.
|
||||
- `npm --prefix backend run test:logs:pg` — интеграция с PostgreSQL и локальным HTTP-стендом RouterOS; используется отдельная случайная схема, которая удаляется после проверки.
|
||||
- Для нагрузочной SQL-проверки установить `LOGS_PERFORMANCE=1` перед `test:logs:pg`: миллион событий, курсорная история и агрегация.
|
||||
- `npm run test:logs` — Playwright: выбор серверов, детали, URL/поиск, экспорт, live-пауза, устаревшие ответы, 5 000 строк, mobile/desktop, светлая/тёмная темы.
|
||||
|
||||
Браузерный профиль использует Webpack и отдельный каталог `tmp/next-logs-test`, чтобы
|
||||
не конфликтовать с кэшем запущенного dev-сервера. SQL-профиль требует доступного
|
||||
`DATABASE_URL` и права создать временную схему; при недоступной БД завершится ошибкой,
|
||||
а не выдаст пропуск за успешную проверку.
|
||||
@@ -0,0 +1,178 @@
|
||||
# Автоматическое подключение NetFlow
|
||||
|
||||
`mmapp-netflow-agent` управляет только `wg-flow` на том же Debian/Ubuntu-хосте,
|
||||
где работает Docker Engine. Используются WireGuard ядра Linux и обычный Docker с
|
||||
root-правами. Rootless Docker и Docker Desktop не поддерживаются этим режимом.
|
||||
|
||||
## Production-состав
|
||||
|
||||
С Compose `deploy/docker-compose.cdn-mm.yml` и дополнением агента работают семь контейнеров:
|
||||
|
||||
| Контейнер | Назначение |
|
||||
| --- | --- |
|
||||
| cdn-mm-traefik | HTTPS и маршрутизация |
|
||||
| cdnmanager | CDN Manager |
|
||||
| mmapp-frontend | Интерфейс MM |
|
||||
| mmapp-backend | API, настройка MikroTik и приём IPFIX |
|
||||
| mmapp-postgres | Настройки и потоки |
|
||||
| mmapp-updater | Существующее обновление контейнеров MM |
|
||||
| mmapp-netflow-agent | Применение пиров WireGuard на хосте |
|
||||
|
||||
Собственный systemd-сервис не нужен. Стандартный `wg-quick@wg-flow` поднимает
|
||||
интерфейс до Docker: backend публикует IPFIX только на его адресе.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
User[Пользователь] -->|HTTPS| Proxy[Traefik]
|
||||
subgraph Host[Production Linux]
|
||||
subgraph Docker[Docker Compose]
|
||||
Proxy --> Frontend[frontend]
|
||||
Proxy --> CDN[CDN Manager]
|
||||
Frontend -->|API| Backend[backend + IPFIX collector]
|
||||
Backend --> PG[PostgreSQL]
|
||||
Backend <-->|HTTP через Unix socket bind mount| Agent[netflow-agent: host network + NET_ADMIN]
|
||||
Updater[updater] -.-> Backend
|
||||
Updater -.-> Frontend
|
||||
end
|
||||
Agent -->|atomic write| Conf[wg-flow.conf]
|
||||
Agent -->|wg syncconf| WG[wg-flow: интерфейс хоста]
|
||||
Conf --> Boot[wg-quick при загрузке]
|
||||
Boot --> WG
|
||||
WG -->|Docker UDP bind на WG-IP| Backend
|
||||
end
|
||||
Backend -->|RouterOS API| Router[MikroTik]
|
||||
Router <-->|WireGuard: внутри IPFIX| WG
|
||||
```
|
||||
|
||||
Агент не обрабатывает потоки: при остановке/пересоздании контейнера интерфейс
|
||||
и приём IPFIX продолжают работать. `NET_ADMIN` вместе с host network позволяет
|
||||
управлять сетью хоста; API ограничено фиксированным интерфейсом и структурированными
|
||||
настройками. Агент не получает Docker socket, `privileged`, корневую ФС хоста,
|
||||
право загрузки модулей или TCP API.
|
||||
|
||||
## Однократная установка
|
||||
|
||||
1. Обновить MM до версии с агентом. Образ агента должен быть опубликован CI
|
||||
в том же реестре; production-хост должен быть авторизован через `docker login`.
|
||||
2. В «Сбор данных → NetFlow» создать ключи хоста, открыть «Файлы хоста» и скачать
|
||||
`install-netflow-agent.sh` из вкладки «Агент Docker».
|
||||
3. Выполнить на Linux-хосте:
|
||||
|
||||
```bash
|
||||
sudo bash install-netflow-agent.sh /opt/cdn-mm
|
||||
```
|
||||
|
||||
Файл содержит приватный ключ. Хранить его как секрет, не коммитить.
|
||||
При необходимости образ можно задать явно:
|
||||
|
||||
```bash
|
||||
sudo MM_NETFLOW_AGENT_IMAGE=git.shx.one/denozord/mikrotikmanager-netflow-agent:VERSION \
|
||||
bash install-netflow-agent.sh /opt/cdn-mm
|
||||
```
|
||||
|
||||
4. В MM обновить состояние хоста и применить настройки. Затем подключать
|
||||
jump-host из раздела трафика: пиры применяются автоматически без перезапуска WG.
|
||||
|
||||
Альтернатива из checkout: скачать `wg-flow.conf` из MM и выполнить
|
||||
`sudo bash deploy/netflow-agent/install.sh /absolute/path/wg-flow.conf /opt/cdn-mm 4739`.
|
||||
Третий аргумент — фактический IPFIX-порт из настроек.
|
||||
|
||||
Установщик сначала проверяет конфигурацию и Compose. Он сохраняет существующие
|
||||
пиры и делает резервную копию конфигурации; при несовпадении ключа, адреса или порта
|
||||
останавливается. Hooks, SaveConfig и нестандартные параметры wg-quick требуют
|
||||
ручной проверки и не принимаются. Интерфейс должен иметь IPv4 /24;
|
||||
пиры MM получают собственные /32 в этой сети.
|
||||
|
||||
Создаются:
|
||||
|
||||
- `data/netflow-wireguard/wg-flow.conf` и `binding.json` с правами `0600`;
|
||||
- ссылка `/etc/wireguard/wg-flow.conf` на постоянную конфигурацию;
|
||||
- `docker-compose.netflow-agent.yml`, не заменяющий пользовательский override;
|
||||
- drop-in `/etc/systemd/system/docker.service.d/mm-netflow.conf` для порядка
|
||||
запуска `wg-quick → Docker`;
|
||||
- общий каталог `data/netflow-agent-socket` для Unix-сокета, подключённый в backend только для чтения. Bind mount сохраняет этот режим при пересоздании backend существующим updater.
|
||||
|
||||
Установщик однократно пересоздаёт backend и не перезапускает Docker или Traefik.
|
||||
Он не изменяет firewall хоста. Существующий публичный или несовместимый IPFIX bind
|
||||
в Compose нужно исправить перед повторным запуском. Не публиковать IPFIX на `0.0.0.0`.
|
||||
|
||||
## Эксплуатация
|
||||
|
||||
При следующих операциях Compose сохранять все файлы дополнений:
|
||||
|
||||
```bash
|
||||
cd /opt/cdn-mm
|
||||
docker compose -f docker-compose.yml -f docker-compose.override.yml \
|
||||
-f docker-compose.netflow-agent.yml up -d
|
||||
```
|
||||
|
||||
Если `docker-compose.override.yml` отсутствует, убрать соответствующий `-f`.
|
||||
Установщик печатает команду для фактического набора файлов.
|
||||
Образ агента обновляется явно через Compose; существующий updater не включает
|
||||
его в автоматические цели. При пересоздании backend updater сохраняет его mounts.
|
||||
|
||||
Просмотр: `GET /api/traffic/flow/host-status`, право `mm:traffic:read`.
|
||||
Повторное применение: `POST /api/traffic/flow/host-reconcile`, право `mm:traffic:write`.
|
||||
Статус не содержит приватных/preshared ключей. `lastHandshakeAt` — Unix seconds
|
||||
или `null`; факт применения настроек не означает handshake или получение IPFIX.
|
||||
Время последнего IPFIX-пакета в панели относится ко всему коллектору.
|
||||
|
||||
Подключения и изменения настроек сериализуются PostgreSQL advisory lock.
|
||||
После рестарта backend повторно применяет сохранённые пиры. При конфликте или
|
||||
недоступности агента приложение и текущий приём продолжают работать.
|
||||
Если MikroTik уже настроен, но хост не применён, результат подключения содержит
|
||||
`ok: false`, `stage: host-pending`, `hostError`: нажать «Применить настройки хоста».
|
||||
При ошибке во время настройки роутера повторить подключение; его изменения
|
||||
не откатываются автоматически.
|
||||
|
||||
Агент сохраняет сторонние persistent и runtime-only пиры, проверяет пересечения
|
||||
AllowedIPs, атомарно записывает конфигурацию и применяет её через `wg syncconf`.
|
||||
При сбое восстанавливает предыдущий файл и runtime; сбой восстановления сообщается
|
||||
отдельно. Добавление/обновление пиров не меняет адреса, маршруты и интерфейс.
|
||||
|
||||
Первая версия не удаляет туннели. Адрес коллектора, префикс и порты закреплены
|
||||
установкой: изменение требует согласования настроек MM, WG и Compose вручную и
|
||||
повторного запуска установщика. Автоматическая смена адреса или ротация ключа
|
||||
не выполняется. Другие установки могут продолжать пользоваться ручным экспортом
|
||||
без `FLOW_AGENT_SOCKET`.
|
||||
|
||||
## Проверки
|
||||
|
||||
```bash
|
||||
npm --prefix backend run test:netflow-settings
|
||||
npx playwright test -c playwright.netflow-agent.config.ts
|
||||
python3 -m unittest discover -s deploy/netflow-agent -p 'test_*.py' -v
|
||||
bash -n deploy/netflow-agent/install.sh
|
||||
docker build --target test -t mm-netflow-agent-test deploy/netflow-agent
|
||||
docker run --rm --cap-drop ALL --cap-add NET_ADMIN --read-only --tmpfs /tmp \
|
||||
-e FLOW_AGENT_KERNEL_TEST=1 --entrypoint python3 mm-netflow-agent-test \
|
||||
-m unittest discover -s /app -p test_agent.py -v
|
||||
```
|
||||
|
||||
Последняя проверка использует отдельное сетевое пространство контейнера, проверяет
|
||||
настоящий kernel WireGuard, сохранение стороннего пира и неизменность интерфейса.
|
||||
Она не заменяет приёмку на стенде с двумя MikroTik: handshake/IPFIX от каждого,
|
||||
сохранение первого соединения при добавлении второго, перезапуск агента/backend
|
||||
и холодная загрузка Linux-хоста с проверкой UDP bind.
|
||||
|
||||
### Приёмка на стенде — 2026-10-16
|
||||
|
||||
На `161.104.46.222` проверены временные контейнеры новой ветки с отдельной БД.
|
||||
15 тестов агента прошли с настоящим kernel WireGuard; 32 профильных скрипта
|
||||
и две отдельные SQL-проверки (monthly и IPv6 UDP/worker) завершились успешно.
|
||||
Оба MikroTik (`194.226.121.150`, `104.165.244.7`) подключены через API: подтверждены
|
||||
handshake, сохранение первого туннеля при добавлении второго и повторное подключение
|
||||
без дубликатов. В БД записаны IPFIX-потоки обоих MikroTik и синтетического Linux
|
||||
экспортёра через WireGuard. Реальные перезапуски контейнеров агента и backend
|
||||
сохранили соединения, приём пакетов продолжился.
|
||||
|
||||
При проверке исправлен API настроек: счётчики и время последнего пакета теперь
|
||||
читаются из работающего коллектора. После исправления полный живой сценарий повторён.
|
||||
Настройки обоих маршрутизаторов восстановлены; временные контейнеры, интерфейс,
|
||||
БД/роли и приватные файлы удалены. Основные сервисы остались на прежних образах.
|
||||
|
||||
Установщик с интеграцией `wg-quick`/systemd и холодная перезагрузка хоста на этом
|
||||
стенде не выполнялись. Образы собраны поверх существующего runtime backend;
|
||||
полная release-сборка frontend и публикация образов в эту проверку не входили.
|
||||
Результаты, исходные неудачные попытки и границы —
|
||||
[отчёт приёмки](ux-ui/acceptance/netflow-agent-2026-10-16.json).
|
||||
@@ -0,0 +1,39 @@
|
||||
# Refactor Baseline
|
||||
|
||||
## Проверки
|
||||
|
||||
- Frontend lint: `npm run lint` (root) — failed (`20 errors`, `10 warnings`).
|
||||
- Backend build: `npm run build` (`backend`) — passed.
|
||||
- Backend smoke: `npm run test:alert-engine` (`backend`) — passed.
|
||||
|
||||
## Критичные baseline-проблемы lint
|
||||
|
||||
- Массовые `react-hooks/set-state-in-effect` в крупных UI-экранах и `components`.
|
||||
- `prefer-const` ошибки в backend сервисах.
|
||||
- Накопленные предупреждения `exhaustive-deps` и `no-unused-vars`.
|
||||
|
||||
## Архитектурные hotspots (для приоритетной миграции)
|
||||
|
||||
- Frontend giant pages:
|
||||
- `app/(main)/alerts/page.tsx`
|
||||
- `app/(main)/uptime/page.tsx`
|
||||
- `app/(main)/network-map/page.tsx`
|
||||
- `app/(main)/filters/page.tsx`
|
||||
- `app/(main)/servers/page.tsx`
|
||||
- Backend mixed layers:
|
||||
- `backend/src/routes/servers.ts`
|
||||
- `backend/src/routes/uptime.ts`
|
||||
- `backend/src/routes/ospf.ts`
|
||||
- `backend/src/services/alerts-service.ts`
|
||||
|
||||
## Дубли контрактов/типов
|
||||
|
||||
- `backend/src/types/scheduler-run-snapshot.ts` и `lib/scheduler-run-snapshot.ts`
|
||||
- `backend/src/types/server.ts` и локальные `Backend*` типы страниц
|
||||
|
||||
## Инварианты рефакторинга
|
||||
|
||||
- Не менять API shape endpoint-ов.
|
||||
- Не менять бизнес-логику.
|
||||
- Не менять поведение UI.
|
||||
- Переход через параллельный новый слой и поэтапное переключение.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Версия 2.0.0
|
||||
|
||||
Релиз объединяет миграцию интерфейса на ReUI PRO / Frame / base-nova и TanStack Table v9, обработку реальных API и завершённую лабораторную приёмку. Публикация в main и выпуск второй основной версии разрешены владельцем проекта 2026-10-15.
|
||||
|
||||
## Изменения
|
||||
|
||||
- Общие таблицы и Filters, навигация, формы, URL-контекст и адаптация для телефона.
|
||||
- Достоверные loading/empty/unknown/partial состояния, сохранение последних данных и защита от поздних ответов и повторных операций.
|
||||
- Проверенные сценарии серверов, мониторинга, трафика, WireGuard, IPsec, GRE, VXLAN, Firewall, BGP, OSPF и диагностики.
|
||||
- Администрирование, Portal, Telegram, S3, контейнеры и сертификаты; подтверждение реальной ACME-ротации, TLS и очистки тестовых объектов.
|
||||
- Исправления клавиатурного фокуса, контраста и читаемости сетевых показателей на узком экране.
|
||||
|
||||
## Проверки
|
||||
|
||||
1396 уникальных основных E2E и221 отдельных context-сценарий приняты после исправления пяти устаревших тестовых контрактов. Первоначальные отказы и целевые повторы сохранены в протоколах. Дополнительно проверены120 состояний30 экранов на реальном стенде и252 REST-запроса за10 минут. Production builds и профильные backend-проверки описаны в [акте лабораторной приёмки](../ux-ui-acceptance-candidate.md).
|
||||
|
||||
Расчёт major/minor/patch, приоритет breaking-коммитов и отсутствие повторного выпуска существующего тега проверяются10 интеграционными тестами временных Git-репозиториев. CI запускает их перед расчётом версии. Для Gitea28 условие optional deploy webhook перенесено с job-level secrets на step-level env; пустой URL не вызывает запрос.
|
||||
|
||||
## Публикация и обновление
|
||||
|
||||
Версию2.0.0 вычисляет CI по breaking-коммиту выпуска. Он собирает образы backend/frontend/updater с semver/SHA/latest, создаёт тег и Gitea Release. Версии workspace package.json не являются версией поставляемого приложения и вручную не изменяются.
|
||||
|
||||
Перед обновлением существующей установки сохраните резервную копию БД и данных приложения, текущие настройки и теги образов. Используйте единый набор образов одной версии. Инструкции развёртывания и миграций — в [README](../../README.md).
|
||||
|
||||
Публикация запускает существующий workflow, включая deploy webhook, если DEPLOY_WEBHOOK_URL настроен. Результат публикации и сборок проверяется в Gitea Actions; подготовка исходников не считается успешной сборкой образов.
|
||||
|
||||
## Границы приёмки
|
||||
|
||||
Проверенный контур: Debian13, PostgreSQL18.6, Portal1.3.1, один backend, два CHR RouterOS7.24.5; Android StrongSwan full-tunnel/reconnect подтверждены пользователем. Лабораторная приёмка не подтверждает все production-конфигурации.
|
||||
|
||||
Непроверенные Windows/macOS/iOS VPN, ручной screen reader, публичный IPv6, независимые WAN, несколько backend, расширенные PKI/S3 и отдельные внешние интеграции перечислены в [акте](../ux-ui-acceptance-candidate.md) и [матрице](../ux-ui-remaining-acceptance.md). Тестовые образы не объявляются автоматически production-установкой.
|
||||
@@ -0,0 +1,9 @@
|
||||
# ReUI: итог lint этапа 2
|
||||
|
||||
2026-09-13. Проверены изменённые файлы серверов/Filters и вся новая группа Data Grid, Filters, Cascader. **0 ошибок, 1 предупреждение** (исходно 23 ошибки и 27 предупреждений). Правила не отключены.
|
||||
|
||||
Оставшийся виртуализатор исключается React Compiler из автоматической мемоизации. Его браузерную регрессию и производительность проверять при переносе использующих его экранов. Исходные общепроектные ошибки вне этого этапа перечислены в основном журнале.
|
||||
|
||||
| Файл | Позиция | Правило | Замечание |
|
||||
| --- | --- | --- | --- |
|
||||
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 764:23 | `react-hooks/incompatible-library` | Compilation Skipped: Use of incompatible library |
|
||||
@@ -0,0 +1,83 @@
|
||||
# UI Design Contract (MikrotikManager)
|
||||
|
||||
Surface: **ReUI Frame**. Kit: `components/reui-kit/`.
|
||||
Иерархия: **ReUI PRO > shadcn primitives**.
|
||||
Стек: Next.js 16 App Router + Turbopack + shadcn **base-nova** + ReUI `@reui`.
|
||||
|
||||
Карта: [docs](https://reui.io/docs) · [llms.txt](https://reui.io/llms.txt) · [Get Started](https://reui.io/docs/get-started) · [Styling](https://reui.io/docs/styling) · [Blocks](https://reui.io/blocks) · [MCP](https://reui.io/docs/mcp)
|
||||
|
||||
## Surface
|
||||
|
||||
Project lock: **`surface: frame`**. Ops / list / dashboard / detail / settings — только **Frame**, не shadcn Card как page shell. Не смешивать Card и Frame на одном ops-экране.
|
||||
|
||||
Эталон CRUD: [`app/(main)/servers`](../app/(main)/servers).
|
||||
Оболочка списков: `DataPageCard` → Frame. Панели: `OpsPanel` → Frame.
|
||||
|
||||
## Canonical PRO references
|
||||
|
||||
| Зона | Preview |
|
||||
|------|---------|
|
||||
| Shell | https://reui.io/preview/base/app-shell-12 |
|
||||
| KPI | https://reui.io/preview/base/stats-12 · https://reui.io/docs/components/base/icon-tile |
|
||||
| Lists | https://reui.io/preview/base/data-grid-filtering-2 |
|
||||
| Server rail | https://reui.io/preview/base/list-9 · https://reui.io/docs/components/base/frame · https://reui.io/docs/components/base/icon-tile |
|
||||
| Settings | https://reui.io/preview/base/settings-16 · https://reui.io/preview/base/settings-3 |
|
||||
| Forms / Sheet | https://reui.io/preview/base/form-7 · https://reui.io/preview/base/sheet-8 |
|
||||
| Alert / Badge | https://reui.io/docs/components/base/alert · https://reui.io/docs/components/base/badge |
|
||||
| Empty | https://reui.io/preview/base/empty-state-12 |
|
||||
|
||||
## Kit (`components/reui-kit/`)
|
||||
|
||||
| Component | Role |
|
||||
|-----------|------|
|
||||
KPI: только `KpiStatGrid` (hybrid IconTile elevated `size-10.5`, эталон `/wireguard`). Не hand-roll Frame KPI.
|
||||
| `CodeExportSheet` | Экспорт кода (.rsc / .conf) — Sheet + Frame + ScrollArea |
|
||||
|
||||
Переключение сервера (ops-контекст): **`ServerTileRail` + `ServerRailLayout`** (`w-60` = `--sidebar-width`). Desktop rail сворачивается (persist `mm:server-rail-collapsed`); mobile — Sheet. Не Combobox. Страницы: OSPF, Filters, GRE, Recursive Routes, WireGuard, Terminal, Certificates, Probes, **Firewall** (live `/api/firewall`). Combobox — generic primitive, не доменный селектор хостов.
|
||||
|
||||
Слои:
|
||||
|
||||
| Слой | Путь |
|
||||
|------|------|
|
||||
| shadcn | `components/ui/` |
|
||||
| ReUI CLI | `components/reui/` |
|
||||
| Kit | `components/reui-kit/` |
|
||||
| Domain grids | `components/data-grids/` |
|
||||
|
||||
## Shared App Shell chrome
|
||||
|
||||
| Токен / зона | Значение |
|
||||
|--------------|----------|
|
||||
| `--sidebar-width` | `240px` |
|
||||
| Header right | AppsMenu → SystemMonitorPopover (тема — в NavUser) |
|
||||
| Search | ⌘K / Ctrl+K only |
|
||||
| `main` | `gap-4 md:gap-6`, `px-4 py-4 md:px-6 md:py-5` |
|
||||
|
||||
## Spacing & tokens
|
||||
|
||||
- `flex` + `gap-*` — не `space-y-*` / `space-x-*`
|
||||
- Semantic tokens / ReUI Badge variants — не raw `bg-emerald-*` / hex
|
||||
- Max 1 primary CTA на экран
|
||||
|
||||
## Exceptions (не Frame ops shell)
|
||||
|
||||
- `network-map` — canvas / topology UX
|
||||
- `terminal` — terminal chrome
|
||||
|
||||
## Forbidden
|
||||
|
||||
- Card как ops list/dashboard shell
|
||||
- Hand-roll data-grid / KPI / code-export при наличии kit
|
||||
- Дубль Copy в header + footer export sheet
|
||||
- Mixing Card и Frame на одном ops-экране
|
||||
- Radix-варианты docs — только Base UI (`base-nova`)
|
||||
- Combobox / toolbar-фильтр как переключатель сервера (SoT — `ServerTileRail`)
|
||||
|
||||
## License
|
||||
|
||||
```env
|
||||
# .env.local (gitignored)
|
||||
REUI_LICENSE_KEY=
|
||||
```
|
||||
|
||||
`components.json` → `@reui` с `Authorization: Bearer ${REUI_LICENSE_KEY}`.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Итоговая лабораторная приёмка UX/UI — 2026-10-15
|
||||
|
||||
Статус: **основной UX/UI-план, включая этап12.5, завершён в границах предоставленного тестового стенда**. Перечисленные ниже внешние ограничения сохраняются. Документ фиксирует состояние до публикации. Владелец отдельно разрешил публикацию main/2.0.0; [описание релиза](releases/2.0.0.md). Это не изменяет границы лабораторных доказательств.
|
||||
|
||||
## Проверенный контур
|
||||
|
||||
- Debian13/Docker Compose, PostgreSQL18.6, Portal1.3.1; один backend.
|
||||
- Два тестовых CHR RouterOS7.24.5:194.226.121.150 и104.165.244.7. HTTP REST используется по разрешению владельца стенда.
|
||||
- Backend `ux-certificates258`: `sha256:984684709e619972bae8657208e3150d12f1c4f2b5642fecf5286a5d87e9fe71`.
|
||||
- Frontend `ux-accessibility261`: `sha256:eec4410f1109a46e864d695cfb4311fdb9a224247549c8a9e78e44c6c0e455cb`.
|
||||
- Основной ПК и узкий экран320px, обе темы. Android StrongSwan full-tunnel/reconnect подтверждены пользователем227; прочие ОС этим не принимаются.
|
||||
|
||||
Точные версии активных образов: [deployment261](ux-ui/acceptance/ui261-deployment.json). История решений: [план](ux-ui-plan.md), [журнал](ux-ui-progress.md), [внешняя матрица](ux-ui-remaining-acceptance.md).
|
||||
|
||||
## Критерии этапа12
|
||||
|
||||
| Критерий | Фактический результат | Граница доказательства |
|
||||
| --- | --- | --- |
|
||||
| Общая оболочка, доступность и адаптивность |260/261:120 уникальных default states30 экранов, обе темы/1440 и320px; профильные клавиатурные проверки и исправленный фокус при смене URL | Результаты разных фаз сохранены; это не полный ручной screen-reader аудит и не все состояния каждой формы |
|
||||
| Достоверность данных и операций | Unknown/partial состояния и подтверждение операций проверены профильными наборами и реальными сценариями журнала; в259 проверены native ID/key/fingerprint, TLS и canonical dates | Успех HTTP сам по себе не принят за применение; произвольные внешние конфигурации не охвачены |
|
||||
| Производительность | Большие списки — локальная12.3.83;260 — synthetic timings с отдельным ожиданием ответов API;262 —10min REST soak/252 запросов | Это измерения конкретного стенда, без заявления field CWV, maximum throughput или бесконечной устойчивости |
|
||||
| Сборки и регрессия | Backend257:25 profiles; certificates258:9 scripts/build/lint; frontend261:production build, source528 matched; профильные E2E260/261 пройдены | UI263:1393 initial +3 targeted =1396 unique passed; отдельный context264:219 initial +2 targeted =221 unique passed;0 skipped/flaky в обоих наборах. Это разные прогоны, без суммирования повторов |
|
||||
| Реальные интеграции | Portal/Telegram195–201, Android227, S3/limited bridge restore/retention228–240, GeoIP mirror242, контейнеры248, ACME250/renewal259 | Успех этих сценариев не подтверждает все сторонние клиенты/провайдеры и многопроцессную установку |
|
||||
| ReUI | Frame/base-nova/установленные компоненты; semantic Badge variants; vendor/theme/motion не изменены; checklist и scoped проверки зафиксированы260/261 | Вне проверенных состояний могут оставаться проблемы; автоматический axe не является полной сертификацией WCAG |
|
||||
|
||||
Краткие протоколы: [UI260](ux-ui/acceptance/ui260-summary.json), [UI261](ux-ui/acceptance/ui261-summary.json), [REST262](ux-ui/acceptance/rest262-summary.json), [UI263](ux-ui/acceptance/ui263-summary.json), [context264](ux-ui/acceptance/context264-summary.json), [ACME259](ux-ui/acceptance/acme259-native-rotation.json).
|
||||
|
||||
## Что остаётся за пределами подтверждённого контура
|
||||
|
||||
| Группа | Что не подтверждено / чего не хватает |
|
||||
| --- | --- |
|
||||
| Клиентские ОС и доступность | Windows/macOS/iOS VPN; другие Android-конфигурации; ручная проверка screen reader/assistive technology |
|
||||
| Внешняя сеть | Публичного IPv6 на стенде нет; независимые WAN, физическая потеря пути, outer IPv6 и maximum throughput не приняты |
|
||||
| Масштаб и устойчивость | Несколько полноценных backend/worker со всеми writers, длительные rekey/failover/DB disconnect; контролируемые multi-process тесты не заменяют весь этот контур |
|
||||
| PKI и маршрутизация | Произвольные PKI/OID/path-length/политики, все конфигурации IPv6/address pool; CA revocation ACME отдельно не принят |
|
||||
| Внешние сервисы | Публикация Gitea CI не запускалась по правилу no push; прямой licensed MaxMind отсутствует в текущей реализации; EvoBGP на стенде выключен и не настроен |
|
||||
| S3 | Большой native export, произвольная миграция бакетов и работа нескольких экземпляров требуют отдельной приёмки; полный restore конфигурации CHR не выполнялся |
|
||||
|
||||
Эти строки — ограничения доказательств и возможностей текущей реализации. Они не превращаются автоматически в поручение реализовать новые функции или получить отсутствующее оборудование.
|
||||
|
||||
## Состояние стенда и сохранность
|
||||
|
||||
После ACME259 восстановлены исходные SSL/native certificates/files/export и приватные SQL-настройки; собственные DNS/issue jobs и приватные ACME fixtures удалены. Контрольные проверки обоих CHR успешны; пароли не менялись. Последующие260–264 не изменяли конфигурацию устройств. ECMP261 проверялся как локальный черновик, затем возвращён off.
|
||||
|
||||
Коммиты только локальные, без push. В полном UI-наборе263 фактический Next dev manifest направляет unmocked proxy на недоступный `127.0.0.1:9`; исходные371 screenshot-файл сохранены перед запуском и сверены:124 перезаписанных восстановлены, SHA-256 всех371 совпал; два исторических JSON также восстановлены.
|
||||
|
||||
## Завершение и дальнейшая работа
|
||||
|
||||
Критерии согласованного этапа12 — production build, тесты, ReUI checklist и перечень оставшихся ограничений — выполнены в указанном контуре. На предоставленном стенде обязательных незавершённых блоков основного плана нет. Для расширения покрытия следует выбрать конкретную группу из таблицы и обеспечить её условия; повторять принятые наборы без изменений не требуется. Публикация и production-развёртывание в текущий объём не входят.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,201 @@
|
||||
# Локальная проверка производительности UX/UI
|
||||
|
||||
Состояние на2026-10-04; этап12.3 продолжается. Эти измерения относятся к Playwright/Edge/Next dev без CPU throttling и реальной сети. readyMs — wall clock от page.goto до готовой строки, включая компиляцию/подставной API; разные прогоны имеют разную прогретость. Это не production SLA и не p95. Fixtures проверяют UI на реальном формате DTO, но не ёмкость PostgreSQL/RouterOS.
|
||||
|
||||
| Сценарий | Размер fixture | Строк в DOM до → после | DOM nodes до → после | Наблюдаемый dev ready до → после |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Серверы |1000 ServerRead,501462 JSON bytes |1000 →50 |41569 →2644 |3345 →1058/1543ms |
|
||||
| Статистика/CompactDataGrid |1000 users,88894 JSON bytes массива |1000 →50 |12585 →1210 |5195 →2928/1195ms |
|
||||
| BGP |1000 полных сессий |1000 →50 |25657 →1932 |2990 →898ms |
|
||||
| Speed-пробы |1000 probes/1001 devices |1000 →50 |23590 →11265 (секция739) |3741 →2310ms |
|
||||
| Ресурсы uptime |1000 resources/CPU10% |1000 →50 |38655 →2580 |4328 →1578ms |
|
||||
| Очередь проблем |1000 offline servers |5 начальных,55 после раскрытия,105 после кнопки |831 начальный dashboard |1081ms; baseline до не замерялся |
|
||||
|
||||
Профили: large-servers.spec.ts, large-statistics.spec.ts, large-bgp.spec.ts, dashboard-data.spec.ts. Измерения приложены к Playwright test results как JSON. Полные массивы всё ещё загружаются/валидируются/фильтруются на клиенте. Pagination ограничивает строки DOM, но не число pivot колонок; широкая pivot требует отдельной проверки. Порционное раскрытие очереди допускает постепенный полный список по запросу пользователя.
|
||||
|
||||
## Оставшиеся специализированные grids
|
||||
|
||||
Актуальная карта после12.3.63 от2026-10-04: точный поиск manualPagination:true в components/data-grids —5 файлов. Это не5 доказанных дефектов: есть фиксированный источник, demo, неподключённый компонент и ограниченный серверный срез. Источники сопоставлены с JSX-потребителями; ограничения установлены чтением кода, не нагрузочной приёмкой API.
|
||||
|
||||
| Файл | Источник и необходимая проверка |
|
||||
| --- | --- |
|
||||
| [data-collection-scheduler-data-grid.tsx](../components/data-grids/data-collection-scheduler-data-grid.tsx) | 11 фиксированных SCHEDULER_JOB_KEYS (lib/scheduler-settings.ts); UI map этих ключей. Fixture1000 не соответствует источнику. |
|
||||
| [gre-pools-data-grid.tsx](../components/data-grids/gre-pools-data-grid.tsx) | В live displayPools=[]; только mockGrePools в demo. Приоритета live1000 нет. |
|
||||
| [probes-schedule-data-grid.tsx](../components/data-grids/probes-schedule-data-grid.tsx) | Только demo ScheduleTab/INIT_RULES3; live использует ProbesSpeedSchedule. Demo список расширяется пользователем; не доказательство live API. |
|
||||
| [subusers-data-grid.tsx](../components/data-grids/subusers-data-grid.tsx) | Поиск импортов/JSX в app/components не нашёл потребителя: компонент экспортируется, но не подключён. Не доказывает дефект экрана /users. |
|
||||
| [traffic-flows-data-grid.tsx](../components/data-grids/traffic-flows-data-grid.tsx) | FlowAnalyticsPanel/conversationsList: backend traffic-flow-analytics.ts top=min(50,max(10,settings.topN)), slice(0,top). Это top slice, не полный каталог/серверная pagination. Проверить сообщение об ограничении50 и связывание с графиками. |
|
||||
|
||||
HomeRouterCard/pages, WAN matrix и полный Community-каталог приняты локально в12.3.55/60/63; скрытый срез24 устранён. CPU7WAN×20 проверен в12.3.61, произвольный большой mixed pool не принят. OSPF topology/details/preview приняты в12.3.50–53. Остаются полные текстовые сводки WAN/JH/Exit, общая context регрессия и внешняя12.5. Demo и Subusers отделены от live приёмки.
|
||||
|
||||
Принятые после ранней карты: OSPF routes/BFD, WireGuard interfaces/peers/detail, VXLAN/GRE tunnels. Pagination сохраняет полный DTO в памяти и не доказывает серверную производительность. Текущий журнал: [ux-ui-progress.md](ux-ui-progress.md).
|
||||
|
||||
12.3.6:1000 speed probes baseline —1000 rendered rows/23590 DOM nodes/3741ms dev ready; профиль collector-probes4 cases и ESLint прошли. Далее12.3.7 ограничение DOM speed grid; этот baseline не означает принятую производительность.
|
||||
|
||||
12.3.7: speed grid принят на1000 строках в описанных локальных границах.50 строк/739 nodes секции; вся страница11265 nodes из-за полного каталога устройств. ServerTileRail требует отдельного ограничения DOM с проверкой поиска, выбора и клавиатуры. Следующий блок12.3.8 — uptime resources.
|
||||
|
||||
12.3.8: ресурсы приняты на1000 CPU10% строках; глобальный поиск/URL/сортировка/страница20/refresh/1000→1/320px. Большой список1000 предупреждений ресурсов требует отдельной проверки12.3.9.
|
||||
|
||||
12.3.9:1000 предупреждений CPU90% — warning nodes2009→21, страница4739→2751 при закрытом списке.5→55→105→5→55 карточек по явному раскрытию; полный счётчик сохранён.9 browser и tagged axe прошли. Полное постепенное раскрытие допускает весь список, это не виртуализация.
|
||||
|
||||
12.3.11: ServerTileRail1001 устройств —50 options на странице (All отдельный aggregate), mobile Sheet тоже50. Speed probes + каталог:11265→1778 DOM nodes,739 nodes speed секции/50 строк. Поиск/URL/граница площадок/клавиатура/refresh/320px/axe обе темы проверены;47 browser и production build прошли. Полные DTO остаются в памяти.
|
||||
|
||||
## Уточнение ограниченных источников перед общей регрессией
|
||||
|
||||
Статический аудит исходников на c4110fa: schedulerGridRows строится из SCHEDULER_JOB_KEYS (11), поэтому отсутствие client pagination не означает1000 строк. TrafficFlowsDataGrid получает analytics.conversationsList, а buildFlowAnalyticsUncached задаёт top=min(50,max(10,settings.topN)) и slice(0,top); page/limit в этом пути нет. Старый /traffic/flows listFlowTalkers — другой источник с settings.topN, его нельзя смешивать с текущей таблицей analytics. Uptime speed history GET /uptime/speed-test/runs использует DB limit200; frontend локальный run список ограничен20. Эти ограничения установлены чтением кода, не нагрузочным испытанием PG. Остальные строки карты требуют проверки по своим потребителям;После history-профиля осталось24 manualPagination:true файла; они не означают24 одинаковых дефекта.
|
||||
|
||||
Statistics pivot в backend/src/services/statistics-aggregate.ts ограничен PIVOT_ROW_CAP=50 и PIVOT_COL_CAP=15; при превышении добавляются агрегаты __other__. Проверять фактическую границу51×16, прокрутку и переходы к срезам, а не произвольную матрицу1000×1000. Это статический аудит источника; browser evidence широкой pivot ещё требуется.
|
||||
|
||||
12.3.13: pivot51×16/17311 JSON bytes принята в описанных локальных границах.50 rows/2574 nodes desktop и2313 mobile; крайние колонки доступны через штатный DataGridScrollArea, агрегаты Other без ложных действий. Sort/page2/два измерения/Back/reload/320px/axe проверены. Фактический cap backend исключает потребность в произвольной матрице1000×1000; реальная скорость PG не измерялась.
|
||||
|
||||
12.3.14: history200/73075 JSON bytes —200→50 rows,7583→2361 DOM nodes; final dev ready1271ms. Global TX sort/page4/refresh page2/200→1/320px/ScrollArea/axe проверены. Это DOM приёмка, не принятие legacy null→0 rates и общей очистки двух GET при ошибке reloadSpeedData.
|
||||
|
||||
12.3.15: live расписание на1000 rows дополнительно проверено при503 на page20, freshness/cache/recovery1/no POST;50 rows/739 section nodes/1778 page nodes. Demo ProbesScheduleDataGrid не использует API и начинается с3 INIT_RULES; исключать его из live migration, но не считать произвольный большой demo-list проверенным.
|
||||
|
||||
12.3.16:certificates1000/329034 JSON bytes —1000→50 rows/29666→2145 DOM nodes,1098ms final dev ready. Whole-catalog search/URL/reload/sort/page20/SAN/refresh/1000→1/320px/axe проверены. Осталось23 manualPagination:true файла; закрепление идентификатора строки при горизонтальной прокрутке — следующий UX блок.
|
||||
|
||||
12.3.17: закреплённое имя и значения полностью видимы на320px после корректировки размеров; pivot action при focus не перекрывается.29 browser/axe/typecheck/build прошли. Certificate final50 rows/2145 nodes; pinning ограничивает положение колонок, не число загружаемых DTO.
|
||||
|
||||
12.3.18:users1000/263680 JSON bytes —1000→50 rows/37505→2393 DOM nodes/921ms dev ready. Whole-catalog name/login/email search, global sort/page20/refresh/details/error recovery/1000→1/правильный пользователь в форме/320px/axe проверены;32 browser/type/lint/build. Поиск не сохраняется в URL; полные DTO остаются в памяти.
|
||||
|
||||
12.3.19:backups1000/171812 JSON bytes —1000→50 rows/43580→2462 DOM nodes/898ms dev ready. Whole-catalog search/Filters/URL/reload/page20/refresh/503 cache/1000→1/правильный filename/возврат focus/320px/axe приняты;39+4 browser/type/lint/build. Полный DB список ещё загружается, производительность PG не измерялась.
|
||||
|
||||
12.3.21: history200 остаётся50 DOM rows/2367 nodes/1150ms dev ready. Strict DTO и null rates приняты от pure DB mapper до grid/KPI/card;60+5 browser и unit4/builds. Это не проверка реального PostgreSQL/RouterOS.
|
||||
|
||||
12.3.24:OSPF routes1000/200347 JSON bytes —50 DOM rows/1356 page nodes/930ms dev ready. Источник /ospf/catalog объединяет полный RouterOS ipRoutes без page/limit. Whole-catalog search/URL/reload/global Cost sort/page20/refresh/503 cache/1000→1/320px/видимость области/axe приняты;22+1 browser/type/lint/build. Полный DTO остаётся в памяти; скорость RouterOS не измерена. Осталось20 manualPagination:true specialized grids, включая demo/bounded источники; это не20 доказанных дефектов.
|
||||
|
||||
12.3.25:BFD1000/323133 JSON bytes —50 DOM rows/1956 page nodes/983ms dev ready. Источник /ospf/catalog объединяет полный RouterOS bfdSessions без page/limit. Whole-catalog search/URL/reload/global Rx sort/page20/refresh/503 cache/1000→1/320px/pinning/axe приняты;12 browser/type/lint/build. Полный DTO остаётся в памяти; скорость RouterOS не измерялась. Осталось19 manualPagination:true specialized grids, включая demo/bounded источники.
|
||||
|
||||
Аудит источников12.4.5:RouteOptimizerCommRecsDataGrid получает flatRules.filter(sourceServerId===home.id).slice(0,24), максимум24 на один HomeCard; это не cap всей страницы с несколькими HomeCard. WireGuard /wireguard агрегирует полный interfaces/peers устройств без page/limit;1000-профиль применим к реальному пути, а WireGuardPeersDetail дополнительно рендерит полный peers массив раскрытого интерфейса. Эти границы установлены чтением кода, не внешней нагрузочной приёмкой.
|
||||
|
||||
12.3.28–12.3.35: WireGuard interfaces1000→50/2136 nodes/1573ms, peers1000→50/2596 nodes/1369ms, раскрытые peers1000→50/2388 nodes; VXLAN1000→50/2137 nodes/1249ms; GRE1000→50/2748 nodes/1609ms. Baseline до по этим экранам не замерялся; сравнение latency между разными dev прогонами не является ускорением production. Evidence и проверки по каждому блоку в ux-ui-stage-12.md.
|
||||
|
||||
12.3.38: Communities1000/190573 JSON bytes →50 DOM rows/2216 page nodes/1206ms dev ready.19 browser/type/lint/build прошли.14 manualPagination:true остаются; обновления/selection по ID подтверждены локально.
|
||||
|
||||
12.3.40: recursive1000 групп→50 rows/2118 nodes/1457ms; одна группа1000 endpoints→50 cards/1126 nodes.35 browser/type/lint/build прошли; большой RouteSheet пока вне принятого performance scope.13 manualPagination:true остаются.
|
||||
|
||||
12.3.41: recursive RouteSheet1000 endpoints ×1000 gateways →10 cards/1569 modal nodes, максимум5 gateway choices на карточку; полный PUT1001 сохранён.22+1 browser/type/lint/build. Расчёт/валидация полного draft остаётся на клиенте.
|
||||
|
||||
12.3.42: Filters1000/120894 JSON bytes →50 rows/2266 nodes/1880ms dev ready. Global order/граница страниц/полный PUT/403/поиск/сортировка/refresh/cache/clamp/320px/axe проверены;10+1 browser/type/lint/build прошли.12 manualPagination:true остаются.
|
||||
|
||||
12.3.43: Firewall1000/253248 JSON bytes →50 rows/3054 nodes/2082ms dev ready. Cross-page кнопки/точный RouterOS destination/DnD page2/403/search/cache/clamp/320px/axe проверены;35+1 main/context4/type/lint/build прошли. Stale operations после полного GET failure требуют12.3.44; большой multi-server sort отдельно не проверен.11 manualPagination:true остаются.
|
||||
|
||||
12.3.44: stale операции Firewall заблокированы до успешного read/после retry, ограничения12.3.43 по полному GET failure исправлены.29+2 main/context4/type/build прошли;4 исходных ESLint errors страницы подтверждены сравнением с HEAD.11 manualPagination:true остаются.
|
||||
|
||||
12.3.45: локальный сценарий1000→50 rows/1847 modal nodes; pagination/full draft999/скрытый verdict#999/320px/axe проверены,6 browser/type/grid lint/build прошли. Трассировка999 остаётся15529 page nodes, требует12.3.46; ошибки записи localStorage не проверены.10 manualPagination:true остаются.
|
||||
|
||||
12.3.46: trace999/15529→1293 page nodes,50 steps/whole verdict#999/страницы/jump/stop→restart epoch/reset/320px/axe проверены;6+1 browser/type/test lint/build прошли. Полный steps в памяти и O(N²) обновления instant не менялись; общий CPU performance не принят.10 manualPagination:true остаются.
|
||||
|
||||
12.3.47: Firewall draft/URL/list filter/focus/lint cleanup завершены,26 main/context4/type/полный ESLint страницы/build прошли.10 manualPagination:true остаются; далее полный OSPF1000 baseline, включая SVG topology.
|
||||
|
||||
12.3.48: OSPF1000 neighbors/1000 interfaces/1001 nodes,583875 JSON bytes →1000 rows/14012 SVG descendants/32635 page nodes/6760ms dev ready.1 browser/test lint прошли, исходные профиль и desktop/mobile snapshots сохранены. Граф перекрывается и не принят. Далее12.3.49 таблица,12.3.50 topology;10 manualPagination:true остаются.
|
||||
|
||||
12.3.49: OSPF1000 neighbors→50 rows,1001 SVG nodes/12015 descendants/13597 page nodes/2827ms dev ready. URL page20/search/global Cost sort/refresh/cache/clamp/320px/axe приняты;22 browser/type/lint/build. Весь граф не принят, KPI1000 переносится на320px, большой node detail вне scope; далее12.3.50–51.9 manualPagination:true остаются.
|
||||
|
||||
12.3.50: OSPF1000 neighbors → scope8 связей/9 узлов, выбранный remote1000:2 SVG nodes/27 descendants/1630 page DOM.26+3 main/8 context/type/lint/build. Полный источник и статус/поиск/URL сохранены; большие node details и читаемость parallel edges не приняты. Далее12.3.51.
|
||||
|
||||
12.3.51: OSPF node=1/1000 neighbors+1000 interfaces →50+50 rows/635 panel nodes/2335 page DOM.4+15+1 browser/type/lint/build. Search/full counts/refresh/clamp/320px/axe приняты; parallel link labels далее12.3.52.
|
||||
|
||||
12.3.52: OSPF parallel1000 between2 nodes →8 raw edges per page/1 visual line, полный источник/state/cost сохранён.9+1 browser/type/lint/build; screenshot1440 принят. Далее optimizer preview.
|
||||
|
||||
12.3.53: OSPF preview1000 interfaces/245293 bytes →50 rows/924 region nodes/1610 page DOM.47+16 main/8 context/type/lint/build. Полный POST/receipt1000 при search1, sort/cache/clamp/320px приняты.8 manualPagination:true; далее many HomeRouterCard/матрицы.
|
||||
|
||||
12.3.54:1000 HomeRouterCard/179347 bytes →40668 page DOM/11496ms dev ready.1 browser/test lint, baseline без WAN не означает принятую производительность. Далее bounded cards12.3.55.
|
||||
|
||||
12.3.55:1000 HomeRouterCard →5/1870 page DOM/1606ms dev ready, full search/URL/refresh/cache/clamp/320px/axe/pin preserved.23+8 main/8 context/type/lint/build. Полный CPU расчёт и1000 native device options остаются; далее1000 full routes.
|
||||
|
||||
12.3.56:WAN10×JH10×Exit10/21 servers/4261 bytes →1000 expanded full-route rows/33049 table DOM/33780 page DOM/3738ms dev ready.1 browser/test lint; baseline, далее12.3.57.
|
||||
|
||||
12.3.57:1000 full routes→50 rows/1699 table nodes/2461 page DOM/1853ms dev ready.6+1 browser/type/lint/build, global sort/index/page20/refresh/clamp/320px/axe.7 manualPagination:true, далее WAN matrix/CPU/24 commRecs.
|
||||
|
||||
|
||||
## 12.3.58 — карта оставшихся рисков оптимизатора (2026-10-04)
|
||||
|
||||
Статический аудит после a16bfae, без продуктовых изменений/сетевых операций. Осталось7 manualPagination:true. WAN matrix рендерит все home.wans и все jumpHosts как columns, legs.find на каждую ячейку; Math.max(...legs.map(score)) тоже не имеет явной границы числа аргументов. DOM ограничение карточек и full routes не ограничивает эту матрицу. Следующие независимые fixtures:1000 WAN×1JH без Exit и10WAN×100JH без Exit — отделить rows/columns от full-route product. После baseline нужны page50 WAN/ограниченный набор JH columns/точные counts/поиск всех JH, map lookup по wan/jh без изменения состояния/best по полным legs.
|
||||
|
||||
buildLiveOptimizerData/assignProbesForWanJh делает DFS, когда WAN<=7 и WAN<=pool.length. Лимита pool нет. scoreProbeForWanIface допускает srcInterface="" для любого WAN; при7WAN/20 подходящих разных probes полное дерево содержит20P7=390700800 полных назначений (вывод из кода, не измеренный benchmark). Не запускать этот случай через Next/UI: сначала отдельный чистый CPU-профиль в дочернем процессе с жёстким timeout, без DB/RouterOS. Стратегию назначения/оптимальность нельзя менять без доказательства эквивалентности на малых наборах; простое обрезание pool может скрыть лучшее назначение.
|
||||
|
||||
commRecs строятся через filter(sourceServerId).slice(0,24), а HomeCard подписывает BGP community только длиной среза. Нужны полный source count/явное сообщение24 изN; нельзя выдавать24 за весь каталог или менять правила применения. Локальная вкладка карточки сбрасывается при pagination, native OSPF select1000 options остаётся. Общая main/context после delta и реальная внешняя12.5 ещё не закрыты. Этот блок — карта приёмки, не доказательство нагрузочной готовности. Product build a16bfae уже passed; для документации повтор не нужен. Следующий12.3.59 — указанные bounded profiles/CPU timeout. Локальный коммит без push.
|
||||
|
||||
|
||||
## 12.3.59 — отдельные профили матрицы и CPU
|
||||
|
||||
2026-10-04. Live API подменён строгими DTO, без Exit и API mutations. Два браузерных профиля прошли: WAN1000×JH1 — 1000 строк,4 столбца,28019 DOM таблицы,28712 DOM страницы,4977мс dev-ready,108917байт; WAN10×JH100 — 10 строк,103 столбца,9803 DOM таблицы,10595 DOM страницы,2258мс dev-ready,16593байт. Время dev измеряет также загрузку/компиляцию и не является production benchmark.
|
||||
|
||||
Чистый расчёт7WAN×20 wildcard probes воспроизводится scripts/performance/optimizer-probes-profile.mjs, в отдельном child process с жёстким timeout10000мс. Расчёт не завершился за timeout; тяжёлый DFS нельзя воспроизводить в UI. Нет DB/API/сетевых операций. Следующий12.3.60 — страницы50WAN и ограниченное окно JH, поиск по полному каталогу, проверка обновления/сжатия и320px. Семантику назначения probes этим блоком не меняем.
|
||||
|
||||
|
||||
## 12.3.60 — ограниченное отображение WAN matrix
|
||||
|
||||
2026-10-04. ReUI DataGrid/TanStack v9: клиентские страницы50WAN, окно5JH, поиск по полному WAN/JH каталогу, точные filtered/total counts. Fixed widths/горизонтальный DataGridScrollArea/закреплённый WAN; страницы сохраняются при refresh и нормализуются при сжатии каталога. Best score берётся из всех legs циклом без spread; Map WAN→JH сохраняет первый matching leg, как прежний find. Raw unknown/zero/даты и модель остаются раздельными. API writes отсутствуют.
|
||||
|
||||
WAN1000×JH1:1000→50rows,28019→1419tableDOM,28712→2149pageDOM,2264ms dev-ready. WAN10×JH100:103→8columns,9803→683tableDOM,10595→1492pageDOM,1785ms dev-ready. Полные исходные массивы остаются в памяти.
|
||||
|
||||
Проверены12browser + повтор2 после lint-правки, TypeScript без incremental, targeted ESLint, production build, ReUI validate_usage/checklist. Мобильные снимки docs/ux-ui/screens/optimizer-wan-matrix-{1000,100jh}-320.png просмотрены. Поиск последних объектов, последний диапазон, cache/refresh/clamp,320px/pinnedWAN и WCAG axe приняты. Общая регрессия после delta ещё требуется.6 manualPagination:true остаются; CPU DFS и срез24 commRecs не исправлены этим блоком.
|
||||
|
||||
|
||||
## 12.3.61 — точное отсечение перебора проб
|
||||
|
||||
2026-10-04. DFS сохранил порядок WAN/pool, обязательный выбор совместимой пробы и первое назначение при равных totals. Отсекаются только ветви, чья верхняя граница не превосходит найденного bestSum. Две релаксации: сумма независимых максимумов remainingWAN и сумма наибольших remainingCount максимумов уникальных probe IDs. Каждое допустимое завершение ограничено обеими оценками; минимум также верхняя граница. Никакого изменения правил scores, fallback greedy для >7WAN/недостаточного pool, выбора интерфейсов, API или сетевых операций.
|
||||
|
||||
Независимый старый полный DFS в тесте совпал по exact probe IDs на1200 seeded fixtures с ties/incompatible/partial matching. Дополнительно equal20 сохраняет первые7 и проверен forced early choice.7 pure tests/type/lint,6 main browser и8 context прошли. Скрипт с child timeout10с теперь проверяет probe IDs: equal17.3ms(p0..6), varied16.6ms(p13..19), freshness60.9ms(p13..19). До правки equal превышал10с; первая слабая граница оставляла freshness2269ms, усиленная граница сократила его. Время child startup отдельно335–443ms, в расчёт не входит. Production build проходит.
|
||||
|
||||
Это профили7WAN×20, а не гарантия для любого размера/набора: DFS всё ещё экспоненциальный в худшем случае, исходный pool не ограничен; large mixed-interface/live нагрузка остаётся предметом production измерения. Следующий12.3.62 — скрытый срез24commRecs.
|
||||
|
||||
|
||||
## 12.3.62 — исходный скрытый срез Community
|
||||
|
||||
2026-10-04. Live API fixture1000 правил Home1/1WAN/1JH/безExit, strict servers/rules DTO. UI показывает BGP community(24),24rows/504tableDOM/1197pageDOM/1916ms dev-ready. Это не performance-успех:976 правил вообще исключены до grid, counts не показывают реальный источник.1 browser/test lint passed, API writes отсутствуют. Следующий12.3.63 удаляет срез и ограничивает отображение pages50, сохраняя unknown indices безExit.
|
||||
|
||||
|
||||
## 12.3.63 — весь Community-каталог с ограниченным отображением
|
||||
|
||||
2026-10-04. Удалён скрытый slice24 после фильтра sourceServerId; ownership и расчётная семантика сохранены. ReUI DataGrid pages50/full search/communityName/gateway/path, exact counts, full-model sort, fixed widths/horizontalScroll/pinnedCommunity. Row key формируется до фильтрации из прежнего home/community/index; pins сохраняются при search/sort/страницах/refresh. Global рекомендаций count теперь относится ко всем правилам. Live режим по-прежнему не применяет BGP-рекомендации; симуляция доступна только demo.
|
||||
|
||||
1000source→50 rendered/1024tableDOM/1751pageDOM/1851ms dev-ready; раньше24 rendered соответствовали24 в модели,976 правил терялись. Проверены page20 и правило1000/search/unknown indices безExit/no simulation buttons/refresh/clamp1/320px/pinned column/axe.7 main browser,8 pure tests (1200 assignment fixtures и новый1000 ownership/unknown), TypeScript, targeted lint и production build прошли. Снимок docs/ux-ui/screens/optimizer-community-320.png просмотрен.
|
||||
|
||||
Осталось5manualPagination:true: scheduler11 fixedkeys, live GRE pools пусты/demo ограничен fixtures, probes schedule толькоdemo, subusers не подключён, trafficflows серверныйtop50 принят с честным указанием среза. Не мигрировать искусственно недостижимые live каталоги. Дальше12.4.6/12.4.7 — повтор общей main/context матрицы после delta. Внешняя12.5 не выполнена.
|
||||
|
||||
|
||||
## 12.3.64 — компактная текстовая сводка WAN
|
||||
|
||||
2026-10-04. Baseline1000WAN:31783chars/13695px высоты summary на320px, хотя grid уже50rows/1419DOM. В HomeCard теперь preview первых3 WAN с прежними ISP/IP, точный remaining/total и понятная ссылка в copy на существующую вкладку WAN×JH. Для ≤3WAN описание не сокращено. Исходный массив/расчёт/поиск/таблица не срезаются.
|
||||
|
||||
Final1000WAN:134chars/86.5px высоты summary; WAN10:130chars/86.5px. В тест добавлены реальные размеры/длина preview, точные counts и мобильный snapshot.12 profile browser +1 screenshot repeat, full ESLint страницы/test и production build прошли. Полный search WAN1000, последняя страница, refresh/clamp/pinnedWAN/320px/axe сохранены. Снимок docs/ux-ui/screens/optimizer-wan-summary-320.png просмотрен;9 historical optimizer PNG восстановлены по явному списку.
|
||||
|
||||
Общие main/context доказательства относятся к прежним HEAD; этот небольшой текстовый delta проверен профильными сценариями. Исторический context-delta(a558412/36) сохранён отдельно от нового context-final-delta(b1f8326/221), чтобы ссылки12.4.3 не изменили смысл. Следующий12.3.65 — pure CPU7WAN×1000pool с hard timeout; не запускать в UI. KPI captions/native selector и худшая DFS/full-route комбинация не приняты этим блоком. Внешняя12.5 остаётся.
|
||||
|
||||
|
||||
## 12.3.65 — CPU-профили pool1000
|
||||
|
||||
2026-10-04, UI/source расчёта не менялись. Child script принимает integer count20–1000, hard timeout10с, без API/DB/браузера/сети.7WAN×1000: equal1217.5ms (IDs p0..6), varied7967.5ms (p13..19), freshness не завершился за10с, процесс остановлен. Startup отдельно ~0.4s. Freshness создаёт1000 разных возрастов, будущие timestamps не используются. ESLint скрипта прошёл; корректность ID проверяется после успешного завершения.
|
||||
|
||||
Это оставшийся CPU риск, а не performance приёмка. В current DFS повторяются Date.parse/trim/score и оценка upper для ветвей, уже достигших максимум. Следующий12.3.66: score cache только для bounded WAN≤7 DFS с одним snapshot time и early stop при достижении node upper, preserving first tie/order/forced picks/greedy fallback. Проверить1200 legacy oracle fixtures, raw observations, profiles20/1000. Худшая комбинаторика и весь full-route product по-прежнему не ограничены.
|
||||
|
||||
|
||||
## 12.3.66 — точный выбор проб из большого pool
|
||||
|
||||
2026-10-07. Score matrix вычисляется только при exact DFS≤7WAN/pool≥WAN, с единым временем ранжирования на назначение JH. Сырые наблюдения/даты не меняются, greedy fallback сохранён. Допустимый score-first greedy путь даёт только lower total, не готовое назначение. Пока DFS не нашёл реальный witness, равные верхние границы НЕ отсекаются; первое равное назначение остаётся в исходном pool order. Node stop требует реального bestAssign. Для каждого кандидата child upper выводится из topK максимумов текущего узла с исключением занятой пробы; уже проигрышные siblings не пересканируют весь pool. Forced pick сохраняется, даже если ветвь отсечена.
|
||||
|
||||
1230 seeded сравнений с независимым прежним DFS совпали по точным probe IDs, включая30 смешанных наборов7WAN.10 pure tests прошли: ties/partial matching, single snapshot при переходе часа, прежний greedy для8WAN, unknown/zero/disabled/raw snapshots.51 main browser и8 context прошли; TypeScript без incremental, targeted lint и production build успешны. Historical9 optimizer PNG восстановлены по точному списку.
|
||||
|
||||
Pure child CPU1000: equal1217.5→15.6ms,varied7967.5→14.5ms,freshness10с timeout→16.7ms; CPU20:11.5–11.7ms. Child startup отдельно~0.25s. Exact IDs проверены во всех6 профилях. Evidence docs/ux-ui/acceptance/optimizer-probes-cpu-2026-10-07.json содержит source SHA256, baseline HEAD и результаты. Браузерная live ветка7WAN/1000probes:219902bytes/7rows/222tableDOM/1018ms dev-ready; timestamps соответствуют p993..999, после refresh сохраняются,320px без overflow, API mutations отсутствуют. Это не production SLA/нагрузка PostgreSQL/RouterOS и не гарантия произвольного mixed pool: худшая экспоненциальная сложность DFS и full-route product остаются.
|
||||
|
||||
Следующий12.3.67: KPI captions JH/Exit (повторы/пустая площадка/unknown), затем separate full-route CPU profile. Общая main/context регрессия12.4.6/7 относится к прежним HEAD; этот delta принят профильными51+8. Внешняя12.5 не выполнена.
|
||||
|
||||
|
||||
## 12.3.67 — краткие и достоверные KPI-подписи площадок
|
||||
|
||||
2026-10-07. В существующем ReUI Stats12/KpiStatGrid footer переиспользован ReUI Badge outline/sm. Короткие уникальные названия (≤3 и≤24символов) показываются без повторов; большой/длинный список заменяется точным количеством площадок. Отдельно виден count узлов без площадки: пустые/whitespace/нормализованный — не считаются реальной площадкой. Нет полного join большого каталога. Неизвестный каталог сообщает «Площадки неизвестны»; нулевой topology pool — «Нет узлов в расчёте», потому что live topology исключает offline/disabled, а устройства могут существовать в inventory. Права/выбор узлов/расчёт/источники не менялись.
|
||||
|
||||
16 main browser +2 повторных новых профиля после copy-уточнения прошли:1000JH и1000Exit отдельно (без опасного cross product), repetitions/two sites/1000sites/long80chars/unknown/empty/offline/disabled/503 cache/recovery.320px без overflow, caption≤80px, scoped WCAG axe passed. Non-incremental TypeScript до dev, full page/helper/test lint и окончательный production build прошли. ReUI API/validate_usage проверены; primitive/theme не изменены. Historical9 optimizer PNG восстановлены, новые docs/ux-ui/screens/optimizer-sites-{jump-host,exit-node}-320.png просмотрены.
|
||||
|
||||
Далее12.3.68 pure child CPU profile full-route product≤100000/timeout10s/memory cap; не грузить тяжёлый baseline в UI. Остаточные DFS worst-case/full-route memory/native selector и внешняя12.5 не объявляются принятыми. Общая main/context регрессия относится к ранее записанным HEAD; текущий footer delta проверен профильными16+2.
|
||||
|
||||
|
||||
## 12.3.69 — lookup leg и исключение ненужных расчётов без WAN
|
||||
|
||||
2026-10-07. WAN/JH map сохраняет первый matching leg, lookup вынесен из Exit loop. JH/Exit legs не строятся, если нет настроенного WAN: их не может использовать ни один full route. Порядок WAN/JH/Exit, сортировка/ties, raw source identity, all routes и unknown community indices сохранены.13pure tests прошли, включая1230 assignment oracle fixtures и новые проверки8route probe ownership/ties/zeroWAN.12browser (large homes/routes/observed/tables) passed; non-incremental typecheck до dev, targeted lint и production build успешны.
|
||||
|
||||
CPU final:1000routes13.3ms;100000(10×100×100)49.7ms;100000(100×10×100)44.0ms. До lookup ~284–329ms и267–287ms. Дополнительный zeroWAN baseline0×100×1000 строил100000unused JH/Exit legs:45.6ms/heapDelta24.6MB; после skip11.5ms/0.17MB. Новый profiler допускаетWAN0 и ограничивает также JH×Exit≤100000. HeapDelta не peak/retained memory; полный nonzero product по-прежнему хранится и сортируется в памяти. Evidence docs/ux-ui/acceptance/optimizer-routes-final-2026-10-07.json содержит source SHA256 и точные результаты.
|
||||
|
||||
После чтения реального producer обнаружены следующие вопросы достоверности:source btest выполняется на srcClient,TX/RX экспортируются без переименования,optimizer пока читаетTX какDL. srcInterface передаётся только after-ping, не bandwidthTest; поле не доказывает WAN скоростного теста. Producer parser/fallback отсутствующую скорость превращает в0, а explicit avg0 может заменяться mean series. Следующий12.3.70 фиксирует аудит с первичными RouterOS источниками и планирует точечные исправления данных/подписей. Команды/права/правила сетевых операций не менялись; real PG/RouterOS/integrations12.5 не выполнялись.
|
||||
@@ -0,0 +1,766 @@
|
||||
# План реализации UX/UI по пятичасовым окнам
|
||||
|
||||
Актуальное состояние 2026-10-15: 264 — лабораторная приёмка основного UX/UI-плана завершена в документированных границах стенда. Приняты1396 основных UI и221 отдельных context-сценарий;120 live default states30 экранов. Runtime backend258/frontend261. Непроверенные внешние группы сохранены в итоговом акте. Публикация main/2.0.0 отдельно разрешена владельцем; [описание релиза](releases/2.0.0.md).
|
||||
|
||||
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-15. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
|
||||
|
||||
## 12.5.264 — context-регрессия и завершение лабораторной приёмки (2026-10-15)
|
||||
|
||||
Отдельный playwright.ux-context.config.ts: initial219 passed/2 failed, skipped0/flaky0/global errors0. Два remove-кейса использовали running fixture и упирались в корректный запрет удаления после248. Для remove задан stopped, для stop сохранён running; проверка позднего результата после смены backend сохранена. Повторены ровно два отказавших remove-кейса:2 passed. Итого221 уникальный принятый сценарий, а не один зелёный исходный прогон. Проверены смена backend/режима данных, поздние чтения и результаты операций, ABA и сохранение нового контекста; набор включает backend-switch.e2e.ts и исключённые из основной конфигурации context-файлы. Это локальные HTTP mocks, без native операций. С основным263 приняты1396 основных и221 отдельных context-сценарий; повторные три263 не добавляются к уникальному числу. [Протокол по файлам](ux-ui/acceptance/context264-summary.json).
|
||||
|
||||
TypeScript и scoped ESLint тестовых изменений263/264 прошли. После тестов SHA-256371 исходных screenshots проверен, исторические JSON сохранены. Нового production кода после build261/backend258 нет, повторная сборка не требовалась. Runtime images повторно сверены через docker inspect, все четыре сервиса running, backend/Portal/PG healthy. Пароли и конфигурации CHR в263–264 не менялись.
|
||||
|
||||
Основной UX/UI-план и этап12 завершены **в границах предоставленного тестового стенда**: production builds, профильные backend-проверки,1396 UI/221 context,120 live default states30 экранов, реальные интеграционные сценарии и список ограничений сохранены. [Итоговый акт](ux-ui-acceptance-candidate.md) отделяет эти результаты от непроверенных ОС/ручного screen reader/публичного IPv6/независимых WAN/multi-instance/расширенной PKI/S3/внешней публикации. Это не приёмка всех конфигураций и не выпуск в production.
|
||||
|
||||
Устаревшая текущая точка плана, ошибочно называвшая этапы10–12 не начатыми, заменена актуальным индексом. Исторические датированные записи сохранены. Следующий шаг при расширении работ — выбрать конкретную дополнительную группу из матрицы и предоставить её стенд; бесконечный повтор принятых тестов не требуется. Коммиты локальные, push0.
|
||||
|
||||
## 12.5.263 — полная UI-регрессия и согласованный фокус выбранной строки (2026-10-15)
|
||||
|
||||
Основной Playwright-набор:1396 сценариев в235 файлах,39min39s. Первый прогон:1393 passed/3 failed, skipped0/flaky0/global errors0. Все три отказа — прежний тестовый контракт ServerTileRail в collector-probes-tables: после260 фокус находится на выбранном option, контейнер listbox больше не Tab stop. Исправлены только тестовые обращения к фокусу; URL, End/Home/стрелки, границы площадок, поиск, pagination, mobile Escape и axe сохранены. Повторены ровно три отказавших сценария:3 passed/12.6s. Итого1396 уникальных принятых сценариев; это не1399 и не один полностью зелёный исходный прогон. [Протокол и результаты по файлам](ux-ui/acceptance/ui263-summary.json).
|
||||
|
||||
BACKEND_INTERNAL_URL направлен на недоступный127.0.0.1:9; effective Next dev manifest проверен, диагностический GET вернул500. Перед запуском сохранены371 исходных screenshot-файл;124 перезаписанных восстановлены, SHA-256 всех371 совпал, новых файлов0. Два исторических backups241 JSON, перезаписанных тестами, восстановлены из предварительно чистого HEAD. Чужие исходные изменения сохранены. Production/native конфигурации не менялись, runtime backend258/frontend261. Context-набор исключён существующей конфигурацией и не выдан за новый прогон.
|
||||
|
||||
Следующий264 — актуальная отдельная context-регрессия и итоговый акт в границах предоставленного стенда. Ограничения внешних ОС/IPv6/WAN/multi-instance и ручного screen reader перечисляются отдельно; no push сохраняется.
|
||||
|
||||
## 12.5.262 — десятиминутная устойчивость REST после ограничения соединений (2026-10-15)
|
||||
|
||||
Реальный Portal UI login; JWT только в памяти процесса, не в отчёте/файле. Затем прямой localhost8000 SSH tunnel к backend258, endpoint GET /api/certificates/state:21 волна через30s,12 одновременно инициированных Node fetch запросов в каждой. Первый и последний запросы разделены полноценным окном600916ms. Frontend развёртывался/проверялся в части окна, обычные фоновые коллекторы работали; тест не зависел от frontend restart. [Полный протокол](ux-ui/acceptance/rest262-soak.json).
|
||||
|
||||
Все252 HTTP responses200;504 server observations по exact IDs1/2, errornull везде. Server collectedAt валидны и строго новее предыдущей волны: кэш старого receipt не засчитан. Median/p95/max request duration=821/1687/1933ms. Ошибок API/timeout/RouterOS login не обнаружено; автоматических повторов после неопределённого результата нет. Configuration/native writes0; только авторизация Portal и чтение. [Сводка](ux-ui/acceptance/rest262-summary.json).
|
||||
|
||||
Проверен один backend, два предоставленных CHR и конкретный HTTP REST путь. Live peak native sockets не измерялся: cap2 подтверждён профильным transport тестом257, здесь проверяется наблюдаемая стабильность под повторяющимися burst. Не заявляются global cap для hostname aliases/внешних WinBox/SSH/других backend, все прочие REST endpoints, максимальная пропускная способность или бессрочная устойчивость. Историческая причинность всех401/500/vendor version hypothesis этим окном не доказана.
|
||||
|
||||
Helper syntax/scoped ESLint passed; production код не менялся, Docker build/25 backend profiles не повторялись. Native объектов/настроек/DNS/файлов не создавали; rollback не нужен, пароли не менялись. Датированные документы и текущая матрица обновлены. Следующий263 — один полный локальный UI-набор после shared keyboard260 и responsive261, с недоступным proxy backend и восстановлением исходных screenshots; build/runtime остаются backend258/frontend261.
|
||||
|
||||
## 12.5.261 — оставшиеся экраны и читаемые сетевые KPI (2026-10-15)
|
||||
|
||||
Baseline12 разделов×2 темы×1440/320px:48 live states, API/JS errors0, overflow0, blocked configuration writes0. Четыре проверенных read-only POST OSPF preview разрешены явно после чтения backend handler; они рассчитывают план, не применяют его. DNS resolution/catalog read POST также имеют точный opt-in allowlist в helper, остальные non-GET блокируются. EvoBGP на стенде disabled, URL/key не настроены: каталоги здесь проверены в состоянии недоступной интеграции, не с реальными внешними данными. [Baseline](ux-ui/acceptance/ui261-baseline.json).
|
||||
|
||||
Найдены4 contrast failures: TypeChip в recursive-routes/light и opacity40 всего ECMP disabled section в двух темах на ПК. TypeChip теперь использует установленный ReUI Badge light variants/text-foreground; ECMP — native disabled fieldset с legend вместо затемнения всех подписей. Профильная проверка включённого ECMP дополнительно выявила неконтрастный выбранный алгоритм; применены bg-muted/text-foreground. Это локальный черновик, серверная логика/применение маршрутов не менялись.
|
||||
|
||||
В BGP summary/analytics, GRE, VXLAN, OSPF summary/BFD убраны принудительные grid-cols2 overrides. Используются существующие kpiCols и неизменённые Frame/IconTile/KpiStatGrid: одна колонка в узком контейнере, прежние container breakpoints для плотного ПК. Шрифты, vendor компоненты, theme tokens и motion не менялись. В8 локальных geometry cases320/390 и16 live theme/width cases подписи KPI не обрезаются; explicit краткая подпись Интерф. в OSPF сохранена. [Снимок BGP320 после загрузки](ux-ui/screens/ui261-bgp320.png).
|
||||
|
||||
Локальные40 E2E: initial38 passed/2 ECMP contrast failed; после исправления повторены только2 affected cases, passed. Geometry8, ECMP2, recursive route contracts15 и OSPF preview15; разные прогоны не суммируются в42 сценария. ECMP false/true проверены также в настоящем Portal/UI, scoped axe0, configuration writes0, draft возвращён off. [Live ECMP](ux-ui/acceptance/ui261-live-ecmp.json). TypeScript/scoped ESLint и production build passed, source528 matched. Runtime frontend ux-accessibility261, backend ux-certificates258 healthy; DB/Portal сохранены. [Deployment](ux-ui/acceptance/ui261-deployment.json).
|
||||
|
||||
Повторены только6 изменённых страниц:24 live states, WCAG-tagged axe violations0/API/JS errors0/overflow0/clipped KPI labels0. С48 baseline это64 уникальных состояния16 страниц: восемь состояний двух изменённых baseline страниц заменены повторными, четыре сетевых KPI страницы добавлены. Вместе с260 —120 уникальных default states30 экранов. Report сохраняет фазу/образ каждого результата: остальные страницы не выданы за повторный прогон на261. [Changed24](ux-ui/acceptance/ui261-changed-final.json), [итог64](ux-ui/acceptance/ui261-final.json), [сводка](ux-ui/acceptance/ui261-summary.json). Во время части замеров шла контролируемая REST-нагрузка262, timings не field CWV и не сравнение независимых бенчмарков.
|
||||
|
||||
| Референс | Схема доработки |
|
||||
| --- | --- |
|
||||
| [ReUI Stats12](https://reui.io/preview/base/stats-12?ref=mcp) | Узкий контейнер → штатная одна колонка → полная подпись KPI; [BGP320](ux-ui/screens/ui261-bgp320.png) |
|
||||
| [ReUI Badge](https://reui.io/components/badge?ref=mcp) | Тип устройства → light variant → semantic foreground |
|
||||
|
||||
Настройки CHR, DNS, сертификаты и пароли не менялись. Native/background telemetry reads не объявляются отсутствием всех DB metadata updates. Manual screen-reader, новые клиентские ОС/WAN/public IPv6/multi-instance, CA revoke и внешняя публикация остаются отдельными границами. Следующий262 — оформить завершённый ten-minute REST soak, затем263 — актуальная полная локальная UI-регрессия после общего keyboard adapter260 и responsive delta261. Автоматическая120-state проверка не заменяет сквозные сценарии и не является полной WCAG сертификацией.
|
||||
|
||||
## 12.5.260 — общая доступность, клавиатура и профильная скорость UI (2026-10-15)
|
||||
|
||||
Проведён read-only аудит18 разделов×2 темы×1440/320px:72 состояния текущего стенда/настоящий Portal UI, без response mocks. Baseline выявил23 состояния с axe нарушениями: недостаточная независимая pointer-area у focusable listbox-контейнера, контраст счётчиков SegmentedControl, raw type badges серверов и заголовка VXLAN. Document overflow0/JS errors0/API errors0; BGP320 имел2 внутренних переполнения main. Dashboard в baseline ещё содержал skeleton: его ранние timings не считаются готовностью данных. [Baseline](ux-ui/acceptance/ui260-baseline.json).
|
||||
|
||||
ServerTileRail сохраняет существующие Item/ScrollArea/DataGrid/44px варианты: один Tab stop на option, стрелки/Home/End перемещают selection и DOM focus, включая переход через страницу50. Root больше не конкурирует с вложенными option за фокус/target. Первые2 новые keyboard tests обнаружили remount GrePageContent при смене server URL; короткий10s keyboard intent восстанавливает фокус на новом выбранном элементе, только если пользователь не сфокусировал другой control, и игнорирует скрытый rail. Настройки устройств/URL selection/API не изменены.
|
||||
|
||||
TypeBadge переиспользует установленный ReUI Badge primary/info/success-light и text-foreground (как существующий rail), поскольку текущий dark success-foreground не прошёл4.5:1; vendor/style/theme не менялись, декоративные иконки скрыты от AT. У счётчиков снята opacity, заголовок VXLAN использует text-foreground. Вкладки BGP на узком экране имеют собственную горизонтальную прокрутку и не сжимаются. [Badge API](https://reui.io/docs/components/base/badge?ref=mcp), [preview](https://reui.io/components/badge?ref=mcp); audit checklist получен через MCP, выполнен в изменённых границах.
|
||||
|
||||
Локально initial57 E2E:55 passed/2 keyboard failed; после исправления remount rerun6 (2 keyboard+4 GRE/VXLAN) passed. Затем добавлены2 contrast tests всех3 типов серверов; final shared4 (2 contrast+2 keyboard) passed. Это59 уникальных принятых случаев; повторные прогоны не прибавляются к числу сценариев; initial отказ сохранён в сводке. Проверены серверные операции/отказы/RBAC/формы, BGP data states, GRE/VXLAN layout и backup layout. TypeScript/scoped ESLint passed. Production frontend build passed,528 source files matched; финальный образ ux-accessibility260-final развёрнут, backend258/DB/Portal сохранены.
|
||||
|
||||
Первый live recheck72 оставил2 color-contrast failures только на servers/dark; прочие70 прошли. После text-foreground final server recheck4 прошёл. Итоговое покрытие72 уникальных состояний объединено с явным происхождением результатов, а не выдано за76 разных случаев: axe WCAG2/2.1/2.2 tagged violations0, document/main overflow0, JS/API errors0, blocked writes0. Для data pages сначала ожидаются200 required endpoint responses; dashboard после этого skeleton0. Synthetic main-visible p50/p95=548/1052ms; required API response p50/p95=1033/2494ms. Это один Edge/headless lab run через SSH, без throttling, стандартный viewport snapshot; не field CWV/maximum load/полная ручная AT сертификация. [Полный протокол](ux-ui/acceptance/ui260-final.json), [сводка](ux-ui/acceptance/ui260-summary.json).
|
||||
|
||||
Визуально просмотрены screenshots servers1440 и BGP320. На BGP320 подписи KPI ещё сокращаются; эту отдельную проблему читаемости включить в261 вместе с оставшимися экранами, не считать её проверенной axe.
|
||||
|
||||
| Референс | Схема и экран |
|
||||
| --- | --- |
|
||||
| [ReUI Badge](https://reui.io/components/badge?ref=mcp) | Тип устройства → semantic variant → читаемая подпись; [servers1440](ux-ui/screens/ui260-servers.png) |
|
||||
| [ReUI Frame](https://reui.io/components/frame?ref=mcp) | Узкий экран → прокрутка вкладок → выбранный раздел; [BGP320](ux-ui/screens/ui260-bgp.png) |
|
||||
|
||||
Устройства не перенастраивались; новых native объектов/DNS/ACME не создавали. Текущая матрица исправлена: containers248 и ACME issue250/renewal259 приняты, старое отсутствие пакета/токена больше не записано как blocker. Семь групп описывают охват, не обязательные семь новых этапов. Следующий261 —12 оставшихся default screens: users/firewall/probes/terminal/data-collection/recursive-routes/route-optimizer/network-map/ip-ranges/asns/communities/domains; затем актуальные границы выпуска. Новая реализация CA revoke/MaxMind или внешняя публикация не объявляются выполненными.
|
||||
|
||||
## 12.5.259 — реальная ротация сертификата и подтверждённый откат (2026-10-15)
|
||||
|
||||
По сохранённому разрешению254 выполнен тот же exact mmt253-8e62a941.pngs.top на104.165.244.7. Перед началом снят свежий приватный native/export/SSL/files/SQL baseline; own certificate/files/jobs/DNS0, Cloudflare token/zone/account проверены. Renewal временно выключен. Подготовленный backend258 активирован; frontend251/Portal/DB сохранены, backend healthy. [Развёртывание](ux-ui/acceptance/acme259-deployment.json).
|
||||
|
||||
Настоящий Portal/UI без mocks: один manual issue POST, terminal done, JS errors0. Native logical leaf единственный, private-key=true, обе SSL службы enabled с logical name. Независимый trusted TLS/SNI/hostname совпал с native SHA-256. [UI](ux-ui/acceptance/acme259-live-ui.json), [первый TLS](ux-ui/acceptance/acme259-tls-before.json).
|
||||
|
||||
Один PUT enabled=true запустил штатный certificates_renew; отдельный run-now0. Canonical validity распознан, daysLeft90; revocationStatusunknown не подменяется valid. Единственная цель, scheduler ok/renewed1/errors0, затем renewal сразу disabled. Реальный цикл31.488s — не гарантия длительности следующих выдач. [Планировщик](ux-ui/acceptance/acme259-renewal.json).
|
||||
|
||||
После продления native logical name ровно1, unfinished _new_0; прежний leaf сохранён в одном _old_<12hex> с теми же ID/SHA-256/private-key. Новый ID и SHA-256 отличаются. Trusted TLS обслуживает новый leaf, canonical validFrom/validUntil совпадают с X509; обычный HTTPS REST200 после продления. [Ротация](ux-ui/acceptance/acme259-native-rotation.json), [новый TLS](ux-ui/acceptance/acme259-tls-after.json), [сравнение](ux-ui/acceptance/acme259-tls-comparison.json). Это успешная конкретная последовательная ротация двух SSL служб; zero-downtime, другие потребители старого ключа и несколько issuers не заявляются.
|
||||
|
||||
Очистка: SSL baseline → только собственные поколения/CA/files → два own terminal jobs → исходные ACME/renew settings целиком. Приложение удалило TXT; собственная A удалена по exact ID/name/type/content, оба DNS имени0. После scheduler refresh повторно восстановлены исходные SQL timestamps/meta. Native certificates/files/SSL, normalized export и приватные SQL строки совпали; при сравнении files исключён last-modified, export — комментарии/пустые строки. Private baseline/key fixtures удалены на Debian и локально. Оба CHR доступны, пароли не менялись. [Откат](ux-ui/acceptance/acme259-cleanup.json), [DNS](ux-ui/acceptance/acme259-cloudflare.json).
|
||||
|
||||
В ручном helper SQL count оказался number0, не string0: первая проверка restore остановилась до device writes, тип ожидания исправлен. Диагностический SELECT с несуществующим created_at отклонён без записей. Эти ошибки приёмочного кода не скрыты и не считаются дефектами продукта. Для неизменённого production кода build/profile не повторялись:258 уже проверен9 scripts/build/lint, общая transport regression257 —25 profiles. CA revocation не выполнен; удаление native сертификата не означает отзыв CA. Следующий260 — актуальный остаток и профильный UX/a11y/performance контроль.
|
||||
|
||||
## 12.5.258 — уникальное новое поколение и сохранение старого сертификата (2026-10-15)
|
||||
|
||||
После256/257 issuer проверяет duplicate logical name ещё до CA order. Leaf/key получают случайное уникальное имя <base>_new_<12hex>, signed X509 fingerprint вычисляется до native upload. rotateCertificateGeneration требует подтверждённые разные native IDs и свободное archive name; сначала проверяет новый leaf/private-key и назначения обоих SSL сервисов на него. Только после этого прежний logical объект переносится в <base>_old_<12hex>, новый получает прежнее logical name и повторно проверяются fingerprint/private-key/services. Старый объект/ключ не удаляется, данные jobs/requestId остаются совместимыми.
|
||||
|
||||
Перед архивацией re-read обнаруживает изменение old ID/fingerprint; после ACK проверяется освобождение logical name, сохранение old ID/fingerprint в archive и неизменность new native ID. Shared IDs, occupied archive, missing ID, external modification или false rename ACK не дают successful receipt. При поздней ошибке возможен частично применённый state с services на проверенном generation; auto-delete/слепого rollback/повторного PATCH нет. Old key сохраняется для reconciliation, остальные его потребители не объявляются автоматически проверенными. Нет обещания нулевого TLS reload или защиты нескольких issuers.
|
||||
|
||||
Сценарии first issue/no previous и renewal/previous оставляют ровно один logical name и old key; четыре apply/rename failure checkpoints сохраняют старый материал; initial3 conflicts не вызывают apply. Дополнительно shared native ID, external fingerprint change и false archive ACK отвергаются. Все9 certificate scripts прошли, contracts/backend build и scoped ESLint passed; общая25-profile regression257 не повторялась, транспорт не менялся. Новых CA/DNS/native операций258 не было.
|
||||
|
||||
Production image ux-certificates258 собран; source530/compiled1084 matched, missing/different0. Образ подготовлен, НЕ активирован: тестовый runtime остаётся backend ux-certificates257/frontend ux-certificates251 healthy. [Prepared image](ux-ui/acceptance/certificates258-preparation.json). Реальная rename/binding семантика ещё не принята по mocks. Signed certificate name изменяем по [официальной документации](https://help.mikrotik.com/docs/spaces/ROS/pages/2555969/Certificates), но фактические native/TLS postconditions проверяются отдельно.
|
||||
|
||||
[TEST-ACME](../deploy/TEST-ACME.md) дополнен поколениями и cleanup правилами. Следующий259 — активировать258 только для согласованного exact mmt253-8e62a941.pngs.top/server2, свежий baseline, real first issue + one scheduler renewal. Требовать new trusted TLS fingerprint, один logical leaf, архив с исходными native ID/fingerprint/private-key и0 unfinished new names; затем убрать все только собственные поколения/root/files/jobs/DNS и восстановить settings/services/export. Старый cleanup256 нужно адаптировать к generated names, не применять вслепую. Разрешение того же сценария уже получено254, новый вопрос не нужен. Этот внешний цикл не начат на малом остатке недельного лимита, чтобы оставить запас на обязательный откат/коммит. Real renewal остаётся открытым.
|
||||
|
||||
## 12.5.257 — достоверный импорт сертификата и ограничение REST-сессий (2026-10-15)
|
||||
|
||||
После реального256 ACME issuer больше не считает HTTP ACK достаточным. applyVerifiedCertificateToServices перед назначением читает raw /certificate, требует unique logical name, SHA-256 ожидаемого выданного X509 leaf и private-key; после применения повторяет проверку leaf и читает configured /ip/service, подтверждая www-ssl/api-ssl enabled с нужным сертификатом. Missing/ambiguous/wrong fingerprint/private-key и неизвестное/ошибочное назначение приводят к failed через existing runner, не к done. Auto-delete импортированных объектов или rollback неизвестной частичной операции не добавлялся; operator видит ошибку и должен учитывать фактические изменения.
|
||||
|
||||
Новый certificate-installation.test:6 invalid imports never apply,4 service mismatches и post-apply ambiguity не дают успеха, positive подтверждённого apply проходит. Certificate profile теперь9 scripts. Production compiled helper проверен на точном captured REST JSON256 с2 одинаковыми именами: rejected/applyCalls0/networkCalls0. Это проверка настоящего payload, не новый RouterOS import/CA order. [Captured guard](ux-ui/acceptance/certificates257-captured-duplicate.json).
|
||||
|
||||
Initial intermediate postguard deployment ещё давал ошибки устройств в live assertion из-за известного login cap6. Общий transport теперь использует отдельные shared HTTP/HTTPS agents с keepAlivefalse/maxSockets2: ограничение на pool/origin в каждом протоколе, idle connections не занимают login slots. GET/POST/PUT/PATCH/DELETE/file HTTP пути используют эти pools; TLS rejectUnauthorized остаётся исходным verifySsl, credentials/HTTP ошибки/abort/deadlines/replay rules не менялись. Не заявляем глобальный cap между backend instances, hostname aliases или другими SSH/WinBox клиентами. HTTP/HTTPS pools отдельные; нагрузочная live проверка относится к HTTP REST на двух CHR.
|
||||
|
||||
Transport тесты:12 запросов из3 разных client instances peak2, idle sockets0; queued PUT deadline истёк до отправки и позже не дошёл до устройства. Старые interrupted/malformed/explicit rejection/no write replay случаи сохранены. test:ros-file (2scripts, response suite10 cases),9 certificate scripts, contracts/backend build и scoped ESLint passed. Initial TCP tests внутри sandbox были отвергнуты окружением, тот же suite с разрешённым локальным TCP passed. Ошибка ignored packaging replace256→257 затронула слово sha256 и остановилась до upload/build; corrected script сохранил алгоритм SHA-256, final manifest подтверждён.
|
||||
|
||||
Из-за изменения общей транспортной основы выполнена полная backend profile regression на собственной SQL БД/ограниченной роли, не production DSN. Все25 profiles passed; private logs остаются вне Git. Пропущенные специальные SQL/UDP ветки перечислены в report, не объявляются выполненными: их наличие не скрывается общим passed. Own test DB/role/container удалены и отсутствие подтверждено. [Full regression](ux-ui/acceptance/certificates257-full-regression.json).
|
||||
|
||||
Финальные production/acceptance images собраны; source530/compiled1084 matched и backend ux-certificates257 healthy. Frontend ux-certificates251/DB/Portal сохранены. После полной регрессии backend перезапущен на final image; [deployment](ux-ui/acceptance/certificates257-deployment.json). Настоящий Portal/read1440/390: оба CHR без ошибок, overflow/JS errors/writes0. [Live UI](ux-ui/acceptance/certificates257-live-ui.json). Дополнительно12 параллельных state reads через реальный API,2CHR в каждом ответе, все200/errornull, без RouterOS login ошибок [live load](ux-ui/acceptance/certificates257-live-load.json). Это конкретный controlled burst, не длительная нагрузочная/многопроцессная приёмка.
|
||||
|
||||
Новых ACME/DNS/native объектов257 не создавали; cleanup256 сохранён, passwords unchanged. Guard исправляет ложный success при duplicate import, но ещё не реализует безопасную уникальную замену: при следующем старом алгоритме duplicate name будет честно failed. Следующий258 — стратегия unique imported generation, verified rebinding и сохранение старого working leaf до подтверждения нового, затем реальная приёмка с fingerprint/TLS и полным откатом в разрешённом scope. Без этого пункт renewal остаётся открытым.
|
||||
|
||||
## 12.5.256 — реальный scheduler renewal, дубликаты native имён и полный откат (2026-10-15)
|
||||
|
||||
Начат2026-10-14, завершён2026-10-15 по Новосибирску. Пятичасовой лимит сбросился, недельный остался ограниченным. По действующему разрешению254 снят новый native/SQL baseline, own jobs/certificates/DNS0, token/zone/account проверены. Первый UI issue exact mmt253-8e62a941.pngs.top/manual →done, trusted TLS/private-key/native SHA-256 подтверждены. [UI](ux-ui/acceptance/acme256-live-ui.json), [before](ux-ui/acceptance/acme256-tls-before.json).
|
||||
|
||||
Native date reader255 теперь правильно даёт validFrom/validUntil в UTC и daysLeft90, совпадающие с X509. Но statusunknown: REST7.24.5 не присылает flags/revoked/expired. Первый enable-triggered run был skipped/renewed0, без нового ACME order; comparator expectation renewed1 не прошёл и сохранён отдельно [skip](ux-ui/acceptance/acme256-renewal-skipped.json). Каталог не должен выдумывать revocation state. Для renewal правило уточнено: достаточно подтверждённого срока и начавшегося непротиворечивого validity window; unknown/missing/changed clock, missing start, future start и reversed window по-прежнему не создают job. Это соответствует прежнему разрешённому renewal даже для explicit revoked/expired, не объявляет сертификат valid.
|
||||
|
||||
Collector native-clock→canonical-state→issue тесты: stable offset создаёт одну задачу, changed/missing не создаёт; отсутствующие REST revocation flags с известными dates позволяют renewal, неизвестные/future/reversed dates блокируют. Все8 profile scripts, contracts/backend build, scoped lint passed. Production backend ux-certificates256/source528/compiled1080 совпал, healthy, frontend251/DB/Portal сохранены. Изменённый scope не требовал повтора полной регрессии249.
|
||||
|
||||
После исправления один enable-triggered scheduler run (interval86400/threshold90), без run-now: scheduler issue →done, receipt ok/renewed1/errors0, затем enabledfalse до следующего интервала. Реально served TLS сменился с342d36bc… на70b7b9f1… и совпал с новым private-key native leaf; доверие/SNI не отключались. [After](ux-ui/acceptance/acme256-tls-after.json), [jobs](ux-ui/acceptance/acme256-jobs.json), [run](ux-ui/acceptance/acme256-renewal.json).
|
||||
|
||||
Приёмка renewal всё равно открыта: /certificate содержит2 leaf с одинаковым logical name mmt253-8e62a941, разными .id/SHA-256 и private-key=true. [Duplicate leaves](ux-ui/acceptance/acme256-duplicate-leaves.json). Next collector отвергнет неоднозначность; import ACK + done не доказывают устойчивую замену. Fresh TLS действительно served new leaf, поэтому не заявляем, что TLS остался старым. До fresh sample ошибочно скопированный вручную fingerprint не прошёл SHA-256 validation; затем использован точный файл native report через SCP. Предусловие statusvalid оказалось неверным для REST flags; первый scheduler run безопасно skipped, после уточнения policy выполнен один реальный order. Не суммируем skip как успешное renewal.
|
||||
|
||||
Cleanup сначала столкнулся с REST401/500; точный ответ resource500: too many concurrent logins (6). Временно остановлен только backend, затем восстановлены configured www-ssl/api-ssl, удалены оба own leaf/chain/PEM. Certificates/file stable metadata/configured services/normalized export совпали с fresh baseline; исключены dynamic connections и directory mtime. [Native](ux-ui/acceptance/acme256-native.json). Backend снова запущен и healthy, Portal послеcleanup оба CHR читает безошибочно; пароли не менялись. REST concurrency остаётся отдельным воспроизведённым ограничением.
|
||||
|
||||
TXT приложение удалило; own A удалена по exact name/type/content/ID, DNS0 обоихимён [DNS](ux-ui/acceptance/acme256-cloudflare.json). ACME/renew settings восстановлены целиком, scheduler refresh применён, его empty-run metadata затем восстановлена exact SQL compare. Own issue jobs удалены, private token/baseline/helper/SQL файлы удалены с Debian и локальный secret fixture удалён. Historical events/scheduler receipts/CA records сохранены; CA revocation не заявляется.
|
||||
|
||||
Следующий257 — post-import подтверждение unique logical name/expected X509 fingerprint/private key перед применением/успехом и безопасная стратегия уникальной замены без потери старого working leaf. Дополнительно проработать per-device REST concurrency/login cap. Эти дефекты не маскируются сообщением successful acceptance; новое разрешение на тот же согласованный сценарий не запрашивается без изменения его риска/объёма.
|
||||
|
||||
## 12.5.255 — native даты с подтверждённым offset для каталога и renewal (2026-10-14)
|
||||
|
||||
После измерения254 добавлен общий readCertificateRowsWithClock: читает gmt-offset перед каталогом, для native timezone-less дат повторно читает clock после; принимает только одинаковые валидные offsets. Native YYYY-MM-DD HH:mm:ss преобразуется в offset-qualified datetime с проверкой календаря, затем UTC; explicit ISO сохраняет свой offset. Не предполагается UTC/пояс backend/будущий DST. rawValidFrom/rawValidUntil остаются исходными. Отсутствующий/некорректный/сменившийся/недоступный clock сохраняет unknown/null и не обходит renewal guard252; ошибка самого каталога сохраняет error. Legacy старые форматы без надёжного контекста не угадываются.
|
||||
|
||||
Общий reader подключён к live catalog и default renewal dependency, disabled/strict-ID guards сохранены. В штатном цикле добавлены read-only clock запросы, мутаций native/DNS нет. Успех этой калибровки подтверждён для CHR7.24.5; другие версии/форматы остаются ограничением до соответствующих измерений. Все восемь certificate profile scripts прошли, contracts/backend build и scoped lint passed. Новые проверки покрывают точные from/until254, январский expiry с текущим +02:00, raw preservation, explicit ISO, неверный календарь/offset и missing/changed/failed clock. Полная регрессия249 не повторялась для ограниченного изменения.
|
||||
|
||||
Production backend ux-certificates255 собран и развёрнут, source528/compiled1080 matched, healthy; frontend ux-certificates251 и DB/Portal сохранены. Read-only Portal/state после обновления: оба CHR200 без ошибки,1440/390 без overflow/JS errors/API writes. [Проверки/deployment](ux-ui/acceptance/certificates255-deployment.json), [live](ux-ui/acceptance/certificates255-live-ui.json). Собственных сертификатов после cleanup254 нет, поэтому этот read не объявляется real native-date/renewal acceptance нового образа. Новые выпуски255 не запускались.
|
||||
|
||||
Следующий256: по уже полученному разрешению254 снова снять свежий baseline, выполнить first issue exact mmt253-8e62a941.pngs.top, подтвердить canonical date против trusted X509; затем один enable-triggered scheduler renewal с порогом90/интервалом86400 без дополнительного run-now, сравнить изменённый native/TLS fingerprint и выполнить полный откат. Если импорт оставит старый TLS leaf или даты останутся unknown — зафиксировать реальный отказ, не маскировать. Из-за малого остатка лимита новый внешний цикл сейчас не начат: для него нужен запас на cleanup. Повторное разрешение на этот же сценарий не требуется.
|
||||
|
||||
## 12.5.254 — реальный выпуск и выявленное препятствие renewal (2026-10-14)
|
||||
|
||||
Пользователь разрешил first issue + scheduler renewal + полный откат для exact mmt253-8e62a941.pngs.top на CHR104. Сняты свежие приватные native/SQL baselines: сертификаты0, issue jobs0, CF token отсутствует. Renewal временно выключен штатным API. Token/zone/account проверены200; один UI POST с сохранённым requestId → terminal done/stepdone, UI завершение и JS errors0. [UI](ux-ui/acceptance/acme254-live-ui.json).
|
||||
|
||||
Native leaf exact name/private-key=true, SHA-256 89b6bd15857aaa548a26137fed6378aa2750440565ba0516240ff22e3a5e7e91. Acceptance helper сделал доверенный TLS к104:443 с SNI, rejectUnauthorized=true: hostname/private-key metadata/native fingerprint совпали с served leaf. [TLS before](ux-ui/acceptance/acme254-tls-before.json). Это первый выпуск, не подтверждение смены leaf после renewal.
|
||||
|
||||
Препятствие из реального state: native invalid-before=2026-10-14 15:37:47 и invalid-after=2027-01-12 15:37:46 без timezone. Канонический parser принимает offset-qualified datetime, поэтому validFrom/validUntil/daysLeft=null и statusunknown. По процедуре253 второй order не запускался, порог90/enable/run-now не применялись; unknown guard252 не обходился и время устройства не менялось. [Renewal limitation](ux-ui/acceptance/acme254-renewal.json). Следующий255 — определить корректную семантику native времени/публичного X509 без предположения о timezone и только затем повторить реальный scheduler renewal в рамках уже данного разрешения.
|
||||
|
||||
Откат: www-ssl/api-ssl исходные поля восстановлены, own certificates/PEM files/job удалены. TXT приложение очистило; собственная A удалена по exact name/type/content/ID; оба имени DNS0. [DNS](ux-ui/acceptance/acme254-cloudflare.json). ACME/renew settings восстановлены полностью; scheduler refresh применил исходное enabled/interval, после его пустого run metadata восстановлена ещё раз и exact SQL comparison passed. Секреты/private baselines/restore SQL удалены с Debian и локальный token fixture удалён. Historical event приложения/публичная CA запись не объявляются отозванными.
|
||||
|
||||
Native первый strict whole-collection assertion остановился на volatile metadata, а не неполном удалении: flash directory last-modified изменился при записи собственных файлов, /ip/service включает dynamic connections. Повтор только read-only сравнил exact configured services, file IDs/name/type/size и certificates; исключены directory mtime и dynamic connections, normalized full export совпал. [Native](ux-ui/acceptance/acme254-native.json). Один контрольный REST read вернул401, следующий read resource/certificate/file/services200 со старым паролем; Portal после cleanup оба устройства читает без ошибок. Не делаем вывод о смене пароля из transient401.
|
||||
|
||||
Дополнительная read-only калибровка254: system/clock Europe/Warsaw, gmt-offset +02:00, autodetect=true. Доверенный X509 before=13:37:47Z и until=13:37:46Z; оба native timestamps15:37 соответствуют текущему +02:00, включая будущий январский expiry. Поэтому нельзя просто дописать Z или применить исторический/будущий Warsaw offset +01:00 к январскому endpoint. Нужен явно наблюдаемый offset и проверка его стабильности вместе с чтением native дат; при неизвестном/сменившемся offset сохранять null. Это доказано для конкретного CHR7.24.5, не для всех версий RouterOS.
|
||||
|
||||
Production source/images не менялись, backend ux-certificates252/frontend ux-certificates251; rebuild/regression не повторялись. Продление и замена leaf ещё не приняты; ограничения описаны без объявления failed/blocked теста успешным.
|
||||
|
||||
## 12.5.253 — подготовка проверки реальной замены сертификата при renewal (2026-10-14)
|
||||
|
||||
Подготовлен exact mmt253-8e62a941.pngs.top/certName mmt253-8e62a941 на CHR104/server2. Read-only preflight с Debian: точный FQDN и challenge name имеют0 Cloudflare records, оба CHR REST200 с прежними паролями. Ни DNS/settings/native writes, ни ACME orders не выполнялись. Это не свежий приватный baseline для будущей мутации: его нужно снять непосредственно перед запуском.
|
||||
|
||||
Новый ручной helper backend/scripts/acceptance/acme-renew-tls.mjs делает bounded15s TLS к фиксированному104:443 с exact SNI и rejectUnauthorized=true. Сверяет hostname, native SHA-256/private-key/name и served leaf. Compare требует изменения SHA-256 после повторного выпуска, совпадения native/TLS, корректных дат; output не перезаписывается. Ввод содержит только публичную native сводку, не keys/passwords. Один positive и11 negative comparator случаев passed без сети/CA; syntax и scoped ESLint passed. Это проверка проверяющего инструмента, не реального renewal. Native fingerprint другого алгоритма сначала пересчитывается из публичного PEM, не угадывается.
|
||||
|
||||
Процедура в [TEST-ACME](../deploy/TEST-ACME.md) включает свежий private baseline/settings/managed targets, единственный собственный target, первый UI выпуск, initial TLS, canonical date guard252 и один scheduler renewal. Code review пути settings выявил важное условие: PUT enabled=true вызывает refreshScheduler с немедленным запуском, поэтому дополнительный run-now запрещён. После terminal renewal выключается до следующего интервала. Если дата unknown, повторный выпуск не запускается и ограничение фиксируется. Job done без нового served fingerprint считается провалом, старый leaf не удаляется ради прохождения теста.
|
||||
|
||||
Откат описан по exact IDs/fingerprints/files/record content и исходным settings/services/normalized export, контрольный CHR194 не меняется, перезагрузки/смена паролей не нужны. Публичная CA выдача не объявляется revoked. Справка native полей/import: [MikroTik Certificates](https://help.mikrotik.com/docs/spaces/ROS/pages/2555969/Certificates); факт замены проверяется измерением, документация его не подтверждает для текущего приложения.
|
||||
|
||||
Production код не менялся, Docker build/deploy не нужен, backend ux-certificates252/frontend ux-certificates251 сохранены. Следующий шаг — согласование конкретных двух выдач/renewal с включением www-ssl/api-ssl и полным откатом; разрешение250 относилось к уже завершённому выпуску. До согласия только подготовка/чтение. Реальное renewal, CA revoke и multi-instance остаются открыты.
|
||||
|
||||
## 12.5.252 — выключенные серверы и достоверность результата renewal (2026-10-14)
|
||||
|
||||
Общий getter сертификатов теперь использует parseDbServerId и SQL enabled=true: numeric prefix/небезопасные ID не доходят до БД, выключенные серверы не возвращаются. Executor повторно отклоняет disabled перед DNS/native вызовами. Renewal использует каноническое наблюдаемое состояние вместо legacy expiry=0: неизвестный срок/статус пропускается, ошибка чтения/неоднозначное имя не запускает выпуск. После runner читается свежая запись задачи и проверяются id/server/name/source/domains/keyType/trustStore; renewed увеличивается только при status=done и step=done. Failed даёт error, queued/running и неподтверждённый результат не дают успеха. Local singleflight сохраняется; атомарная защита нескольких backend не заявляется.
|
||||
|
||||
Factory collector позволяет отдельно проверить зависимости без RouterOS/CA. test:certificates включает восемь scripts; новый набор покрывает done/failed/pending, missing/disabled, неизвестный срок, offline/malformed/ambiguous, выключенные настройки, активную задачу, неправильный контекст результата и конкурентный запуск. Executor включает11 сценариев. Локально и в acceptance image профиль прошёл; contracts/backend build, scoped ESLint и diff-check прошли. Полная регрессия249 не повторялась для ограниченного изменения сертификатов.
|
||||
|
||||
Расширенный network-disabled-server harness выполнен на собственной SQL БД с отдельной ограниченной ролью:39 API/SQL checks для home-router/jump-host/exit-node, включая certificates issue404/no job и state200/empty, zero RouterOS contacts. Enabled positive control и bigint IDs above int32/MAX_SAFE_INTEGER прошли без округления. После теста контейнер/БД/роль удалены, отсутствие подтверждено. Это выполняет ранее пропущенную152 ветку в текущем scope; monthly149/IPv6 UDP-worker144 этим тестом не покрыты. [Проверки](ux-ui/acceptance/certificates252-regression.json).
|
||||
|
||||
Production backend ux-certificates252 развёрнут, healthy; source526 и compiled1080 совпали с локальным снимком. Frontend ux-certificates251 и PostgreSQL/Portal сохранены. [Deployment](ux-ui/acceptance/certificates252-deployment.json). Настоящий Portal/read без mocks: certificate state и renew settings200, оба CHR без ошибки чтения;1440/390 без overflow/JS errors/API writes. Первый запуск Edge не стартовал внутри filesystem sandbox; повтор с разрешённым доступом прошёл, это не дефект приложения. [Live UI](ux-ui/acceptance/certificates252-live-ui.json).
|
||||
|
||||
Новых сертификатов, ACME orders, DNS записей, настроек устройств не создавали; native пароли не менялись. Успех fixtures доказывает счётчик/guards, не реальное продление/замену ключа/CA revoke. Следующий253: подготовить конкретную повторную выдачу собственного mmt-домена, сравнение leaf fingerprint и доверенного TLS до/после, восстановление исходных SSL/certs/files/settings/DNS. Выполнение с повторным назначением SSL требует отдельного согласования конкретного сценария; разрешение250 покрывало тот уже очищенный тест.
|
||||
|
||||
## 12.5.251 — понятные последствия выпуска и доступные мастера ReUI (2026-10-14)
|
||||
|
||||
После250 форма явно сообщает: импорт назначает сертификат обоим www-ssl/api-ssl и включает их; trust-store переключатели задают trust-store, не отменяют назначение. Итоговая сводка показывает DNS A-sync как попытку синхронизации с IPv4 сервера и сохранение CNAME. Сетевая логика/API не менялись. Оба trust-store switches получили доступные имена.
|
||||
|
||||
Scoped axe live preview выявил прежние aria-required-children/parent и aria-valid-attr-value: установленный Stepper root role=tablist охватывал nav и контент, nav мешал родительской роли tabs, Content не передавал id/role/aria props. [API](https://reui.io/docs/components/base/stepper?ref=mcp), [preview](https://reui.io/components/stepper?ref=mcp) и примеры прочитаны через MCP; актуальный @reui/stepper прочитан shadcn view и имеет те же пропуски. Установка/переопределение vendor не решает их и не выполнена.
|
||||
|
||||
Добавлен reui-kit/accessible-stepper: переиспользует установленные компоненты/keyboard/focus/styles, добавляет прозрачные display:contents обёртки с tablist/tabpanel, rootgroup без неподходящего aria-orientation, React useId для tab/panel namespace. Контент forceMount с штатным hidden сохраняет все IDREF. Vendor файл, shared theme и animation timings не менялись. Все три потребителя — сертификаты, создание/редактирование серверов, создание бэкапа — переведены на адаптер.
|
||||
|
||||
69 уникальных E2E:57 existing certificates issue/layout + servers + backup operations и12 backup job + новые3 ARIA сценария. Первый набор57 прошёл2.1m, второй12 —32.1s; первоначальные7 issue повторяются в57 и не суммируются. Проверены операции/checkpoints/отказы/права/контекст, серверный wizard320/390/1440, certificate layout320/390/1440, связь каждой tab со своей существующей panel/unique IDs/одна видимая панель и4 ARIA rules во всех трёх формах. TypeScript и scoped ESLint passed. Не заявляем полного axe/WCAG аудита всех трёх страниц.
|
||||
|
||||
Production frontend ux-certificates251 собран и развёрнут, source528 matched, backend ux-containers249 healthy сохранён, PostgreSQL/Portal не пересоздавались. До обнаружения ARIA дефекта выполнялись промежуточные сборки copy/labels; окончательный образ содержит adapter и все последние изменения. Это повтор из-за новых найденных ошибок, не дополнительные принятые сценарии. Для следующих сложных форм сначала локальный scoped axe, затем production build. [Deployment](ux-ui/acceptance/certificates251-deployment.json).
|
||||
|
||||
Настоящий Portal/live preview1440/390: trust www переключается Space, step3/4 показывают назначение SSL независимо от trust toggle и DNS/CNAME; нет overflow/JS errors, четыре scoped axe WCAG2/2.1/2.2 scans violations0. Формы отменены Escape, API writes0/никаких выпусков/новых DNS/native objects. [Live UI](ux-ui/acceptance/certificates251-live-ui.json), [desktop](ux-ui/screens/certificates251-review-desktop.png), [mobile](ux-ui/screens/certificates251-review-mobile.png). Mobile screenshot просмотрен. ReUI checklist пройден в изменённом scope: reuse/семантика/security/scroll/typecheck/lint; неизменённые части не объявляются заново принятыми.
|
||||
|
||||
Следующий252: чтение certificates-service поID всё ещё принимает numeric prefix и disabled row; renewal collector опрашивает его. Collector после runIssueJob прибавляет renewed без чтения terminal job status, хотя runner записывает failed и возвращается без throw; legacy parser подменяет неизвестный срок0. Исправить эти достоверные code-path дефекты и проверить соответствующие service/SQL случаи. Реальная повторная выдача/renewal/CA revoke/multi-instance остаются отдельными неподтверждёнными вариантами, первичный ACME250 уже принят.
|
||||
|
||||
## 12.5.250 — production ACME / Cloudflare / TLS через реальный UI (2026-10-14)
|
||||
|
||||
Пользователь предоставил pngs.top/Cloudflare и разрешил поддомены с префиксом mmt*. После уточнения звёздочки получено согласие на точное имя mmt250-c22a9715.pngs.top и временное назначение www-ssl/api-ssl с откатом. Cloudflare token verify и exact zone query200/success, token/zone active/account matched; оба собственных DNS имени до начала имели0 records. Ключ/почта/account ID только в ignored private fixture; на Debian ключ поступил через разрешённый временный API settings, отдельный secret файл туда не передавался. Native/private settings baseline снят до начала.
|
||||
|
||||
Настоящий Portal/UI без mocks: app Cloudflare test200, settings save200; выбран server2/CHR104, один POST issue с точным CN →200/jobId; backend queued/running →done, UI terminal «Завершена». Production directory Let's Encrypt, не staging/fake CA. CSR/DNS-01/импорт leaf+key+chain прошли; native leaf CN/private-key=true и оба SSL сервиса enabled с этим сертификатом подтверждены. [UI](ux-ui/acceptance/acme250-live-ui.json).
|
||||
|
||||
Независимая проверка: DNS A104.165.244.7; TLSv1.2, обычный rejectUnauthorized=true, peer authorized/SAN exact domain, issuerYR2, срок2026-10-14→2027-01-12; REST по HTTPS200 с прежними учётными данными. TLS проверка не отключалась, CA в локальное доверие не добавлялась. Это проверка конкретного CA/RouterOS клиента, не всех TLS версий/клиентских ОС. [TLS](ux-ui/acceptance/acme250-tls.json).
|
||||
|
||||
Очистка: сначала исходные disabled/certificate/port SSL сервисов, затем только собственные cert/root-chain и PEM files. Исходные certificate/file коллекции и полный нормализованный export совпали. ACME settings восстановлены полностью, включая accountPrivateKey/updatedAt; own terminal job удалён, чтобы не оставлять managed renewal target. Историческое событие теста в журнале приложения сохраняется. После фактического COMMIT начальная проверка Date vs JSON string дала assertion; исправлена только JSON-нормализация и повторное read-only сравнение, native/SQL операции не повторялись. Приватный baseline удалён. [Native](ux-ui/acceptance/acme250-native.json).
|
||||
|
||||
Application TXT cleanup подтверждён GET0; A-sync создал единственную собственную A с content104/proxied=false, она удалена по exact name/type/content/ID. Final FQDN/challenge records0. Остальные DNS записи/zone settings не менялись. [Cloudflare](ux-ui/acceptance/acme250-cloudflare.json). Post-cleanup app settings tokenConfigured=false, own job404/certificate absent, оба CHR certificate read доступны. Выданный сертификат не объявляется отозванным у CA; запись о выпуске остаётся, native экземпляры/ключевые файлы удалены. Все временные credential файлы блока удалены после проверки.
|
||||
|
||||
Runtime backend ux-containers249/frontend ux-containers248 unchanged; source changes только manual acceptance helper/документация, не production код. [Процедура](../deploy/TEST-ACME.md), helper acme-live-issue.mjs syntax/ESLint passed. Backend-профили и E2E не повторялись для документального блока:25 профилей249 и29 E2E248 уже проверены в своих границах. Дополнительный local locator/copy helper ремонт не считается новым live сценарием.
|
||||
|
||||
Следующий251 — явное пояснение последствий в форме: текущий issuer всегда включает www-ssl/api-ssl и синхронизирует DNS A, а экран говорит лишь об импорте/trust-store. Изменить copy существующих шагов, сохранив сетевую логику; профильные UI проверки/build/deploy. Automatic renewal, CA revocation, remote release publishing/multi-instance/WAN и остальные обязательные варианты матрицы ещё не приняты этим выпуском.
|
||||
|
||||
## 12.5.249 — достоверное legacy чтение контейнеров и общая backend-регрессия (2026-10-14)
|
||||
|
||||
Аудит выявил: GET выбранного сервера обходил enabled gate; legacy mapper считал отсутствие status остановкой, memory-high — фактической памятью, скрывал ошибки загрузки пустым массивом. Прямой GET теперь даёт409 для выключенного и404 для отсутствующего сервера до dispatch; прямой service/read тоже не создаёт RouterOS клиент для disabled, aggregate исключает disabled до reader factory. Ошибки/частичные ответы legacy GET дают502; unsupported сохраняет прежний legacy [] для совместимости, подробное availability предоставляется /api/containers/state. ID разбирается общим строгим parseDbServerId, без принятия префикса1abc.
|
||||
|
||||
Legacy service переиспользует канонический readContainerServerState вместо второго скрывающего ошибки опроса. Общий mapper учитывает running/stopped/error flags и unknown, envlists/mountlists и современные list aliases, nullable startOnBoot, memory-current с известным нулём; memory-high и имя контейнера не подменяют расход памяти и неизвестный образ. Десятичный/неверный CPU не обрезается parseInt. Изменение legacy status включает unknown; потребители нового UI уже используют этот статус. В репозитории frontend не обращается к старым GET.
|
||||
|
||||
test:containers дополнен legacy service profile и включён в общий test:all/CI. Настоящий loopback HTTP-транспорт без DB: valid/native running;401/malformed/dependency error не становятся empty; unsupported сохраняет []. Disabled makes0 requests; invalid ID returnsnull до DB. HTTP проверяет selected disabled/missing без read dispatch и502 вместо fake success. Direct state иaggregate disabled guards проверены отдельно. Первый sandbox запуск loopback получил EACCES и не принят; elevated профиль прошёл. Contracts/backend build и ESLint passed; Docker Node22 профиль тоже exit0.
|
||||
|
||||
Из-за изменения общей основы выполнены все25 профилей test:all на собственной ограниченной PostgreSQL БД/роли, без production DSN. Все exit0; сумма378124ms (6мин18с), это не число индивидуальных assertions. Три специальные SQL-ветки пропущены из-за отдельных env/namespace: Monthly149, IPv6 UDP/worker144, network-disabled-server152 (MMAPP_OWN_TEST_DB). Это известные явные ограничения текущего объединённого запуска, не приёмка этих веток. Остальные conditional skip строки сохраняются числом в протоколе, не превращаются в live доказательства. Собственная БД/роль/контейнер удалены, отсутствие проверено. [Регрессия](ux-ui/acceptance/containers249-regression.json).
|
||||
|
||||
Backend ux-containers249 собран/развёрнут и healthy; frontend ux-containers248 сохранён, PostgreSQL/Portal не пересоздавались. Backend source524/compiled1080 совпали без missing/different; версия1.0.0-test.backup249 — метка лабораторной сборки, неGitSHA. [Deployment](ux-ui/acceptance/containers249-deployment.json). Настоящий Portal/read UI1440/390: typed state200 показывает оба CHR unsupported после удаления пакета248, legacy global/selected GET200[] совместимы, overflow/JS errors0, non-auth API writes0. Никаких новых native объектов/перезагрузок/изменений паролей. [Live UI](ux-ui/acceptance/containers249-live-ui.json). ReUI audit checklist для alert-dialog прочитан: используются существующие props/copy; vendored компоненты/стили/тайминги не менялись.
|
||||
|
||||
Пользователь предоставил стенд ACME: pngs.top и разрешённые поддомены с префиксом mmt*. Read-only Cloudflare token verify и exact zone query вернули200/success; token/zone active, account matched. Токен/почта/account ID сохранены только в ignored private fixture, в Git не добавляются. Следующий250 — issuance/импорт/результат через реальный API/UI с очисткой собственных DNS/certificate/file объектов и возвратом исходных настроек. Пока реальная выдача не выполнена. Обнаружено, что текущий issue автоматически назначает сертификат www-ssl/api-ssl; перед применением подготовлен private baseline этих сервисов/сертификатов/файлов/settings. Remote publishing, multi-instance/WAN и прочие ограничения матрицы сохраняются.
|
||||
|
||||
## 12.5.248 — подтверждённое удаление контейнера через UI (2026-10-14)
|
||||
|
||||
В 247 UI отправлял DELETE работающего контейнера и получал 502. Теперь dialog использует последнее состояние выбранного serverId/rosId: удалить можно только stopped; для running/unknown/error показана инструкция остановки и обновления. Backend независимо читает native список и проверяет однозначное stopped, не останавливает контейнер скрыто. Отсутствующий target или неподходящее состояние дают 409 без DELETE; после DELETE каталог читается снова, сохранённый target/сбой/некорректный ответ не становятся ok=true. Выключенный сервер отклоняется до команды. Каталоги/файлы не удаляются отдельными командами приложения; поведение native remove не подменяется обещанием очистки.
|
||||
|
||||
Проверки: test:containers включает новый removal-профиль в общий test:all/CI; проверены native running/unknown/conflicting/transient, отсутствие target, неверный каталог, read failure, удаление только выбранного stopped, повтор без удаления другого target и сбой подтверждения. HTTP проверяет disabled/missing server без dispatch, 409 conflict, 502 uncertainty, ok=true и существующий write-permission contract. Это изолированные service/HTTP проверки, не отдельный live RBAC сценарий. Backend/contracts build, production frontend build и профильный ESLint прошли. 29 уникальных E2E containers-data/operations прошли за 58.8 секунды; ранее в 247 webServer не стартовал, нынешний elevated запуск стартовал успешно, точная причина прошлого таймаута не доказана. В E2E обычный HTTP-путь с тестовыми ответами, не встроенные демонстрационные данные. Полная регрессия не повторялась.
|
||||
|
||||
Пользователь отдельно разрешил повторную установку того же проверенного container NPK из источника 246 и две перезагрузки. Native baseline снят до передачи. Создан собственный mmc248-busybox с veth mmc248-e57b223b и pinned BusyBox digest из 247; core/option/version/device-mode/пароли/registry credentials/bridge/IP/NAT не менялись. Настоящий Portal без моков: UI start200 и native running; dialog1440/390 блокирует удаление и прямой API409; UI stop200 и native stopped; UI remove200/ok=true, строка отсутствует; повторный API409 «уже отсутствует». JS ошибок нет. При изменении viewport закрывающееся меню временно давало scrollWidth780 при width390; после штатной анимации ширина390. Helper ждёт стабилизации, ReUI styles/timings не менялись. Изначальный неверный heading locator исправлен на существующий breadcrumb. [Live UI](ux-ui/acceptance/containers248-live-ui.json).
|
||||
|
||||
Собственные контейнер/veth/image/root/NPK отсутствуют. Container package удалён второй однократной подтверждённой перезагрузкой; исходные installed routeros/option7.24.5 и полный нормализованный export совпали. Автоматический timezone вернулся к исходному Europe/Warsaw после reboot; helper ждёт полного совпадения без исключения clock и не печатает приватный export при ошибке. Двойная запись create в native stages означает дополнительное read-only получение имени существующего объекта, не второе создание. Оба CHR доступны; приватные baseline удалены. SFTP с прежним паролем и прямой workstation REST200 подтвердились: один вход прервался auth timeout до завершения аутентификации, поэтому не означает неверный пароль. Причина прежнего401 не доказана. [Native/cleanup](ux-ui/acceptance/containers248-native.json).
|
||||
|
||||
Backend и frontend ux-containers248 собраны/развёрнуты, backend healthy; frontend не имеет Docker healthcheck. Замороженные build inputs: backend523/frontend527 совпали, compiled backend1080 без missing/different. Поздние acceptance-only helper правки не входят в этот source audit; runtime TS/TSX соответствуют сборке. Изменены только два image tag в приватном .env; PostgreSQL/Portal не пересоздавались. Первая frontend сборка предшествовала уточнению текста о дополнительной очистке, выполнена финальная сборка из уточнённого context. [Deployment](ux-ui/acceptance/containers248-deployment.json). Подход с native флагами и envlists согласуется с [RouterOS manual](https://manual.mikrotik.com/docs/containers/); требование stopped — явная политика безопасного удаления приложения.
|
||||
|
||||
Контейнерная приёмка start/stop/restart/remove закрыта в этих границах; работающий контейнер нужно сначала остановить. Следующий 249 — legacy GET контейнеров: проверить, что прямое чтение выбранного выключенного сервера не опрашивает RouterOS, затем согласовать статусы старого DTO с native flags. ACME Cloudflare token/test-domain, удалённая публикация Gitea, multi-instance/WAN/client OS и остальные ограничения матрицы остаются открытыми. Сам тестовый пакет снова удалён, новое применение без согласия не планируется.
|
||||
|
||||
## 12.5.247 — фактические состояния и жизненный цикл контейнера (2026-10-14)
|
||||
|
||||
Пользователь разрешил конкретный пакет 246 и две перезагрузки. На 104.165.244.7 установлен только container-7.24.5.npk из указанного источника mikrotik.ltd → MikroTikPatch, с ранее проверенным SHA256. Core/option/python/keygen/patch scripts не применялись; версия RouterOS осталась 7.24.5. Образ BusyBox 1.37.0 linux/amd64 закреплён digest busybox@sha256:bdf57e528e45e4433820e045b29b45978255a1c9e38353532d90a01445013f82e. Созданы только собственные контейнер mmc247-busybox, veth mmc247-39da5c21 и каталог; bridge, IP, NAT, маршруты и глобальные registry credentials не изменялись.
|
||||
|
||||
Реальный REST отдаёт stopped/running флаги вместо status и envlists вместо envlist. Общая обработка теперь поддерживает эти поля, сохраняет unknown при переходе, неверном значении или противоречии; отсутствие статуса не считается stopped. Для envlists проверена backend-фикстура, отдельное live создание envlist не выполнялось. test:containers (service + HTTP), сборка contracts/backend и профильный ESLint прошли. Добавлены девять проверок native флагов и проверка alias. E2E containers-data/containers-operations не стартовали: тестовый webServer :3100 превысил 120 секунд; успешной E2E приёмки этот блок не заявляет.
|
||||
|
||||
Через настоящий Portal без моков в UI 1440×1000 получены start 200 → stop 200 → start 200 → restart 200 с ok=true и проверкой rosId. Native состояния независимо подтвердили running → stopped → running. Удаление работающего контейнера через UI вернуло 502/ok=false; причина не доказана, сценарий НЕ принят. Ошибок JavaScript нет. [UI-протокол](ux-ui/acceptance/containers247-live-ui.json).
|
||||
|
||||
Очистка выполнена native API: собственный контейнер остановлен и удалён, veth/image/root/NPK отсутствуют. Container package удалён второй однократной перезагрузкой; оба reboot получили подтверждение. Доступные, но не установленные пакеты RouterOS имеют пустую version — при сравнении учитываются только установленные. После reboot автоматическое определение часового пояса временно отличалось от исходного, затем вернулось к Europe/Warsaw. Попытка PATCH singleton clock получила 400 и ничего не изменила; manual clock restore не применён. Итоговый нормализованный export и исходные installed routeros/option 7.24.5 совпали. Приватный baseline удалён. [Native-проверка и очистка](ux-ui/acceptance/containers247-native.json).
|
||||
|
||||
Backend ux-containers247 развёрнут и healthy; frontend ux-backups237 сохранён. При сборке совпали 521 исходный файл и 1076 compiled файлов; последующие исправления только CLI helper для cleanup не входят в замороженный source audit. [Deployment](ux-ui/acceptance/containers247-deployment.json). Агент не менял passwords/device-mode/keys. С Debian REST работает после обеих перезагрузок; прямой REST с рабочего компьютера возвращал 401, SSH с прежним паролем сначала прошёл, повторный вход не прошёл. Причина расхождения неизвестна; глобальную исправность SSH/пароля не заявляем. Контрольный CHR 194.226.121.150 доступен.
|
||||
|
||||
Следующий блок 248: понятная и безопасная обработка удаления работающего контейнера, приёмка удаления остановленного через UI и повторного действия, затем диагностика запуска E2E и корреляция авторизации без изменения паролей. RBAC/повторное действие в live 247 не проверены. ACME, внешняя публикация релизов и другие ранее записанные ограничения остаются открытыми. Полная регрессия не повторялась.
|
||||
|
||||
## 12.5.246 — пакет контейнеров из указанного пользователем источника (2026-10-14)
|
||||
|
||||
User отклонил official244 с причиной«нужно использовать пакеты с сайтаmikrotik.ltd». Перезагрузки/installation не выполнялись. Прочитан [сайт](https://mikrotik.ltd/) и его ссылка [MikroTikPatch](https://github.com/elseif/MikroTikPatch); inline download template указывает GitHub releases. Зафиксирован [точный7.24.5/x86 archive](https://github.com/elseif/MikroTikPatch/releases/download/7.24.5/all_packages-x86-7.24.5.zip), size29,675,363 иSHA256b293b380e680aece7fd0895889fd77b01133ea5ed6d89b32fb6d53af1936acc9 совпали сGitHub API asset digest/size. Извлечён толькоcontainer-7.24.5.npk1,163,409bytes/SHA25670f1c5281a3d37b347e9a83c81d9daaac511357fe26cfbac11321e2dc1407259. Он отличаетсяотофициального244; подменаартефактаоднимfilenameнепринимается.
|
||||
|
||||
Архив/NPK толькоignored tmp, вGit не публикуются и наCHRнепередавались. Option/main/python packages иpatch/keygen/shell scripts не выбраны/не выполнялись; license/device-mode/password/version/keys не изменялись. Наличиеoption наCHR подтверждено243; происхождение установленногоcore/optionпоhash не сверялось и не объявляетсядоказанным. Совместимость/подписьновогоNPK ещё должнапроверяться самимтекущимRouterOS, беззаменыключей.
|
||||
|
||||
[Процедура](../deploy/TEST-CONTAINERS.md) обновлена: источникомприменениябудетэтот246artifact, официальный244помеченrejectedhistory. Target104.165.244.7/control194.226.121.150/двеplannedcontrolled перезагрузки/ownlifecycle/cleanup остаются. Посколькупредыдущеесогласиепользовательнедал, installation/rebootновогокомплекта ещёсогласуются. Positivecontainerlifecycle непринятподготовкой. [Протокол](ux-ui/acceptance/containers246-requested-source.json).
|
||||
|
||||
Runtimebackend ux-geoip242/frontend ux-backups237 сохранены, nativewrites/reboots0. Следующий247 — реальнаяконтейнернаяприёмкапослесогласия; ожиданиеответанеявляетсяразрешением. Другиеобязательныевнешниесценариитребуютграницвыпуска/конкретныхдоступов.
|
||||
|
||||
## 12.5.245 — новый GeoIP HTTP тест входит в общий CI-профиль (2026-10-14)
|
||||
|
||||
В backend/package.json test:traffic-flow добавленgeoip-download.test.ts передcollector тестом. test:all вызываетэтотprofile один раз, backend/scripts/test.mjs выполняетего черезnpm test; Gitea backend-test вызываетnpm run test --prefix backend. Новой зависимости и отдельного дублирующего test:geoip вtest:all нет. test:geoip остаётся удобной профильной командой. Это только dev/test command metadata, compiledruntime242/API/UI не изменяются; production Docker не пересобирался ради списка тестов, при следующей сборке метаданные попадутвобраз.
|
||||
|
||||
Local24 scripts прошли; SQLbranches безlocal PG честноskipped. Source acceptance image на code242/cache build с текущим package245 command overlay выполнил тотжеprofile в собственной PostgreSQL ролиNOSUPERUSER/NOCREATEDB/NOCREATEROLE/NOBYPASSRLS:exit0/57,066ms/newHTTPtest observedonce. Обычные SQLветки исполнились; ровно2 специализированныеbranches monthly/IPv6 требуютдругих отдельноименованныхown DB иskipped. Ониневыдаются за новуюприёмку; предыдущие222 протоколы остаютсяисторическими. ВременныеDB/role/container удалены и отсутствиеDB/roleподтверждено.
|
||||
|
||||
Первыйharness запуск не нашёлpg из/checks; исправлен createRequire(/app/backend/package.json), DB/role очищены. Затем guardharness ошибочно запрещалобаизвестныхoptional skips при успешномnpm exit0; скорректирован точныйallowlist, финальныйrun57,066ms passed. Повторныепроверки не суммируются. stdoutтестов сохранёнprivately, publicJSON содержитлишьscope/duration/skips/cleanup. [Протокол](ux-ui/acceptance/traffic-flow245.json); helperstraffic-flow-regression.mjs/run-traffic-flow-regression.sh проходятnode --check.
|
||||
|
||||
Userотклонилприменениеофициальногоcontainer244 из-заисточника иуказалmikrotik.ltd. ЭтотNPKнеприменяется, upload/reboot0. Следующий246 фиксируетзапрошенный7.24.5/x86artifact/source/digest иобновлённуюпроцедуру; конкретное согласие на installation/reboot ещё не получено. Productionbackend ux-geoip242/frontend ux-backups237 неизменны.
|
||||
|
||||
## 12.5.244 — конкретный пакет и процедура контейнерной приёмки (2026-10-14)
|
||||
|
||||
Для104.165.244.7 подготовлен официальный [all_packages-x867.24.5](https://download.mikrotik.com/routeros/7.24.5/all_packages-x86-7.24.5.zip), HEAD/GET200,10,476,996bytes. Архив прочитан как данные, извлечён толькоcontainer-7.24.5.npk1,175,697bytes. SHA256 zip6acfd80b3f6edfd23cea14bfcdbbb183a6258acb3aedb3d7b0a23f60a19e51c6, NPK7515c52499bd11b063517c7b48a6553519976098040d9dec67f6bf087876a3c9. Это локально вычисленные отпечаткиHTTPSvendor payload, не отдельнаяvendor checksum; native signature/installation ещё не проверены. Файлы толькоignored tmp, вGitбинарники не добавлены. SSH22 reachable, вход/передача NPK не выполнялись.
|
||||
|
||||
[Процедура](../deploy/TEST-CONTAINERS.md) задаёт target104/control194, private baseline, бинарную передачу с pinned SSH key, single reboot/no retry onunknownack, native7.24.5/package/endpoint proof, own pinned container/veth/bridge lifecycle через Portal, cleanup и возврат исходныхpackages вторымreboot. Device-mode ужеcontainer=true и не меняется; пароли/version/reset не меняются. Это конкретная подготовка, не разрешение/успех установки: upload/install/reboot0. Применение ждёт отдельного согласия пользователя, поскольку меняет пакеты и временно прерывает доступ к CHR.
|
||||
|
||||
Протокол: [artifact preparation](ux-ui/acceptance/containers244-preparation.json). Positive containerstart/stop/restart/remove остаётся открытым. Пока ожидается согласие —245 проверяет независимыйCI regression profile: новый streaming HTTP GeoIP тест242 должен выполняться не только отдельной командойtest:geoip, но и общимtest:all/CI путём без дублей.
|
||||
|
||||
## 12.5.243 — реальные предпосылки контейнеров, ACME и релизов (2026-10-14)
|
||||
|
||||
Десять direct read-only RouterOS запросов:system/package/resource/device-mode/disk/container ×2CHR. Оба доступны7.24.5 stable/x86_64, installed routeros иoption, container feature=true/flagged=false, freeHDD около10GiB/freeRAM около0.8GiB. /container400 на обоих; пакет с именемcontainer не обнаружен. Публичный отчёт сохраняет status/error SHA256, неcredentials/полные error bodies. Приложение GET containers/state200 классифицирует обаunsupported. Это доступность текущего набора функций, а не доказательство отсутствия контейнеров по пустому snapshot или успешного lifecycle.
|
||||
|
||||
Vendor [Container](https://help.mikrotik.com/docs/spaces/ROS/pages/84901929/Container) и [Packages](https://help.mikrotik.com/docs/spaces/ROS/pages/40992872/Packages) указывают требуемый container package. Для positive lifecycle нужны проверенный пакет текущей версии и контролируемая подготовка CHR; установка/перезапуск не выполнены. Новые manual URLs были недоступны web tool; использованы доступные официальные vendor pages, без вывода о совместимости конкретного будущего image по памяти.
|
||||
|
||||
ACME public settings:tokenConfigured=false/defaultZoneConfigured=false; Let’s Encrypt production directory GET200 с ожидаемыми endpoints. Это неDNS challenge, issuance, renew или deployment сертификата. Нужны явный test-domain/Cloudflare scoped token/право на временныеTXT и staging ACME. Секреты и зоны не выдумывались, DNS/account/certificate writes0.
|
||||
|
||||
Gitea — pipeline.gitea/workflows/docker.yml с push main/workflow_dispatch, registry uploads/releases/webhook; соответствующего backend polling job нет. По поручениюno push публикация не запускалась. compute-release.mjs отработал в ignored tmp output, candidate1.47.7/schema valid/current-candidate notes coherent, tagsCreated/pushes/GiteaAPIwrites/registryUploads0. Candidate не является выпущенной версией и не меняетpackage.json/publicmanifest. Отдельно real Portal UIcontainers/releases1440/320 passed:unsupported states, labversion1.0.0-test.backups237, globaloverflow/pageerrors0/non-auth APIwrites0. Первичный UI счётчик включал2 login POST; исправлено разделение auth и business operations, не приложение.
|
||||
|
||||
node --check availability helper passed; runtime code/images unchanged, профильная регрессия не повторялась без оснований. Два собственных сообщения локальных коммитов239/240 приведены к русскому тексту; author/date/trees/workspace dirty files сохранены, downstream commit IDs изменились, push0.
|
||||
|
||||
Протоколы: [native/ACME availability](ux-ui/acceptance/external-jobs243-availability.json), [live UI](ux-ui/acceptance/external-jobs243-live-ui.json), [release dry-run](ux-ui/acceptance/release243-dry-run.json). Следующий244 готовит конкретный vendor package/artifact для контейнерного lifecycle; применение и перезапуск согласовать отдельно после подготовки. REST root cause, multi-instance, clientOS/WAN/publicIPv6 и границы выпуска остаются по матрице.
|
||||
|
||||
## 12.5.242 — реальный GeoIP mirror job и честное состояние cache (2026-10-14)
|
||||
|
||||
В collector обнаруженыfalse-success304 при отсутствующей локальной базе (старый тест прямо принимал это), race до acquisition lock из-за await settings и освобождение timeout после headers вместо body. Теперь gate захватывается до первогоawait; concurrent force409/backgroundskip. Conditional ETag отправляется только после проверки локальной MMDB; missing/corrupt cache требует200 полного файла.304 без validated cache — ошибка, неskippedUnchanged. Partial failures сохраняют дату последнего успешного update и предыдущий файл, добавляя lastError. Новая downloadGeoipDatabase держит120s deadline через streaming body, ограничивает declared/chunked file64MiB и закрывает непригодное тело. Базы проходят existing Country/ASN validation до atomic swap; формат/layout ReUI не менялись.
|
||||
|
||||
Local test:geoip прошёл: реальный HTTP healthy/304, stalls after headers→AbortError, declared/chunked oversize→reject, recovery; collector invalid/cache/concurrent gates; JWT reader cannotmutate/writer/admin allowed. Backend/contracts build и scoped ESLint прошли.15 unique GeoIP settings/responsive/data-collection E2E прошли25.2s; ошибочная первоначальная команда с несуществующимиspec далаNo tests found и не считалась проверкой. Три автоматически перегенерированных старыхGeoIP PNG возвращены к исходным байтам; чужие GRE/VXLAN changes сохранены.
|
||||
|
||||
Final production source516/compiled1072 matched. В own PostgreSQL/files scope выполнены7 укрупнённых сценариев: actual mirror download обеих MMDB12,380,575bytes, Google8.8.8.8→US/ASN15169, actual conditional304/hash unchanged иconcurrent409, missing-country refetch безETag, corrupt-country refetch, controlled invalid MMDB200/uncached304 сохраняютlastSuccessAt, actual recovery иdisabled background0fetch.12 реальных mirror GET200/304; negative country responses явно контролируемые и не выдаются за native WAN failure. Валидация MMDB не подменялась. Temporary DB/role/container/files удалены, CHRcontacts0/mainDBwrites0 в этом scope. Предварительная сборка с иным downloader отдельно проверялась; повтор не прибавлен кunique приёмке.
|
||||
|
||||
Развёрнут только backend ux-geoip242; frontend ux-backups237 image/container ID неизменны. Backendhealthy; real Portal/live GET GeoIP200 иUI1440/320, обе main bases alreadyloaded, globaloverflow0/pageerrors0, POSTupdate0. Main GeoIP job через UI не запускался; реальная загрузка доказана в isolated scope, а не заявлена обновлением данных приложения. Откатbackend ux-backups237 и приватная прежняя.env сохранены на сервере.
|
||||
|
||||
Протоколы: [mirror/SQL](ux-ui/acceptance/geoip-mirror242.json), [deployment](ux-ui/acceptance/geoip242-deployment.json), [live read UI](ux-ui/acceptance/geoip242-live-ui.json). MirrorP3TERX — фактический источник collector без account key. Прямой licensed MaxMind download не реализован текущим collector и не принят этим тестом; актуальность/геолокационная точность всех IP, publicIPv6 geography, multi-process lock, physical WAN failures отдельно.
|
||||
|
||||
| Референс | Схема состояний |
|
||||
| --- | --- |
|
||||
| [ReUI Settings16](https://reui.io/preview/base/settings-16?ref=mcp) | validated cache → conditional304; missing/corrupt → full200 → validate → swap; error → last-good + last-success + warning |
|
||||
|
||||
Следующий243 — read-only availability audit контейнерных/ACME/release jobs на текущем стенде и согласованная матрица реальных remaining dependencies. Не выдумывать Cloudflare/registry credentials и не обновлять RouterOS без отдельной команды.
|
||||
|
||||
## 12.5.241 — тысяча бэкапов со смешанными состояниями файлов (2026-10-14)
|
||||
|
||||
Изменение237 проверено на1000 обычных live-path HTTP DTO (199062bytes), по250 local/missing,both/missing,local/unknown,local/available. Два сценария1440/320 прошли25.2s. UI сохраняет pagination50 строк:DOM2477/2239, ready1203/806ms в dev fixture окружении. Это измерение конкретного запуска, не production SLA/сетевой latency и не доказательство скорости filesystem API1000 файлов.
|
||||
|
||||
Глобальный поиск находит997–999 вне первой страницы и показывает правильные действия:missing local disabled download/restore иrecord-only dialog;both missing допускаетS3;unknown не превращается вmissing. При503 last-good row иdisabled state сохранены; после200 ошибка снята. Страница2/row51 сохранилась послеrefresh. Keyboard Enter/cancel возвращает focus на правильный delete trigger, global overflow отсутствует. Scoped axe по текущимWCAG tags:0violations; UI writes0. Эта проверка не заменяет screen-reader/manual WCAG приёмку.
|
||||
|
||||
Новый large-backups-file-state.spec.ts и scoped ESLint прошли. Existing PNG/screens не перезаписывались; runtime код/образы не изменялись. [ПК metrics](ux-ui/acceptance/backups241-large-1440.json), [320px metrics](ux-ui/acceptance/backups241-large-320.json). Прежняя большая таблица с иными сценариями не считалась повторно новой приёмкой.
|
||||
|
||||
Следующий242 — доступный GeoIP mirror job в own SQL/file scope. В коде есть публичный mirror без licence key; actual paid MaxMind, Cloudflare DNS ACME, registry/container/Gitea jobs требуют отдельного контроля и прав. Остальные внешние группы остаются в матрице.
|
||||
|
||||
## 12.5.240 — retention на реальном S3 и частичный отказ удаления (2026-10-14)
|
||||
|
||||
В production image ux-backups237 запущен compiled pruneBackupsForServer/delete/read service в отдельной PostgreSQL базе с собственным NOSUPERUSER/NOCREATEDB/NOCREATEROLE/NOBYPASSRLS пользователем. Основной каталог/настройки не использовались. Seed8 harmless copies на3 собственных fixture servers:5 точных объектов в новом UUID S3 prefix и5 local files (both учитываются в обеих группах). RouterOS не опрашивался и не применялся; cfg bucket virtual-hosted Selectel, настройки бакета не менялись.
|
||||
|
||||
При keepCount2 первого сервера и намеренно неправильном S3 secret local old copy удалена первой, затем remote delete отказал:BackupPruneError.pruned=1. Failed row/object сохранены, две новые копии и остальные servers неизменны. После возвращения верного secret retry удалил1, следующий prune вернул0. Второй сервер keepCount1 удалил2 старых copies, сохранилlatest both; третий unselected manual local copy не затронут. Все4 retained files прочитаны compiled service с точными исходными байтами/hash; remote-only localFileStatus=not-stored, остальныеavailable.
|
||||
|
||||
Пять укрупнённых SQL/S3 проверок прошли. Cleanup удалил только planned keys и их5 versions/2delete markers (итого7), final listing0, own catalog0. Wrapper удалил temporary DB/role/container и подтвердил отсутствие DB/role. Временные ключевые файлы workstation/Debian удалены; секреты в публичном JSON отсутствуют. node --check passed; runtime источники/образы не менялись, повторной полной регрессии нет.
|
||||
|
||||
Протокол: [retention240](ux-ui/acceptance/s3-retention240.json). Helpers:s3-backup-retention.mjs/run-s3-backup-retention.sh. Это реальное хранилище с контролируемыми SQL/file fixtures, не native scheduler production collection и не физический lost ACK; продолжительная работа, version lifecycle policy, миграция buckets и multiple backend/writers остаются отдельно. Ошибка S3 signature намеренно введена, пароли CHR не менялись.
|
||||
|
||||
Следующий241 проверяет1000 строк нового missing/unknown/both UX237:поиск, pagination, last-good и mobile controls. Затем уточнить доступные external jobs и границы выпуска; семь общих групп не превращать в обещание фиксированного числа проверок.
|
||||
|
||||
## 12.5.239 — восстановление из Selectel S3 через реальный интерфейс (2026-10-14)
|
||||
|
||||
Пользователь явно разрешил передачу тестовых S3 access/secret keys на Debian после отказа automatic approval review. Ключи находились только в приватных ignored/0600 файлах и временных настройках приложения. Перед изменением сохранены raw SQL storage/schedule и10 исходных backup rows приватно. Расписание временно остановлено, virtual-hosted S3 сохранён и проверен через live UI с реальным Portal1.3.1/JWT. Использован новый UUID prefix и ровно один собственный95-byte .rsc: добавление bridge mm-ui239-* с comment=mm-ui239 без портов/адресов. Это специально ограниченный скрипт, не native full export и не полное восстановление CHR.
|
||||
|
||||
Собственный объект записан и прочитан SDK, затем только его строка добавлена в каталог. Через обычный UI скачан файл с совпавшими байтами/SHA256; restore вернул HTTP200 с нужными backupId/serverId. Direct RouterOS на194.226.121.150 подтвердил ровно один bridge, comment, отсутствие bridge ports/IP addresses и неизменность исходных bridges. Через UI удалена только собственная строка/объект:HTTP204, строка исчезла; pageerrors0. Восстановление на втором CHR и полный config restore этим блоком не проверялись.
|
||||
|
||||
Cleanup удалил свой bridge и загруженный .rsc, все версии/delete markers только точного ключа UUID prefix, сверил исходные10 SQL-строк и оба settings rows целиком. Первая попытка остановилась уже после удаления объектов: проверочный SQL-column guard не допускал цифру3 в s3_*; исправлен allowlist имён, повторная очистка прошла. Final-attempt removed0 означает, что версии удалены первой попыткой; конечный listing0 подтверждён. Общее число удалённых версий первой попытки не записано и не выдумывается. Bucket settings, чужие объекты и пароли не менялись. Приватный SQL-снимок и временные ключевые файлы workstation/Debian удалены; production-код и образы ux-backups237 не менялись.
|
||||
|
||||
Acceptance helpers s3-ui-limited-restore.mjs/.cjs проходят node --check. [UI-протокол](ux-ui/acceptance/s3-ui239-browser.json) и [native/cleanup](ux-ui/acceptance/s3-ui239-native.json) фиксируют точные границы. Общая регрессия не повторялась: новых runtime изменений нет.
|
||||
|
||||
| Референс | Схема принятого сценария |
|
||||
| --- | --- |
|
||||
| [ReUI Data Grid Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp), [Sheet8](https://reui.io/preview/base/sheet-8?ref=mcp) | Собственный объект S3 → строка истории → download → подтверждение restore → native bridge → delete → cleanup и исходные настройки |
|
||||
|
||||
Следующий240 — retention в изолированном scope без удаления существующего каталога. Полная конфигурация, массовые экспорты на реальном CHR, миграция buckets, multi-instance, другие ОС/WAN/jobs остаются отдельной приёмкой.
|
||||
|
||||
## 12.5.238 — REST за пределами десятиминутного окна (2026-10-14)
|
||||
|
||||
Read-only workstation-наблюдение длилось763.844s (07:01:21.663Z–07:14:05.507Z):26 циклов с целевым периодом30s, шесть endpoints × два CHR × compiled MikrotikClient/fetch Connection:close. 624 samples и24 diagnostics, все HTTP200; повторные запросы при отказе не выполнялись, потому что отказов не было. Учётные данные передавались из приватного process env, временный env-файл удалён; Basic/JWT/пароли в публичный отчёт не включены. RouterOS configurationWrites0/passwordChanges0.
|
||||
|
||||
На обоих CHR7.24.5 до/после было по2 записи via=api для configured user; SHA256 от id/when изменились. Retained via=rest-api rows844→846 и320→322. Наблюдалась смена записей сессий в окне более10 минут без отказов. Это не доказательство точного cached-login механизма7.24.5 и не контроль firmware: vendor docs уже описывают7.25. Найденный236 vendor fix удаления inactive REST sessions остаётся гипотезой; причины прежних401/500 не установлены. Большое число сохранённых rows нельзя приравнивать к concurrent www sessions или доказанному исчерпанию ресурса.
|
||||
|
||||
Acceptance helper chr-rest-correlated.mjs теперь принимает ограниченные cycles1–32, period1–60s и maxMs10–960s, сохраняя прежние defaults8/12s. Deadline проверяется между циклами, запросы имеют timeout6s; failure diagnostics/финальное чтение могут выйти за целевую длительность. Это не жёсткий end-to-end deadline. Сохранён именно протестированный helper; node --check passed. Production-код и Docker образы после237 не менялись, полная регрессия не повторялась без основания.
|
||||
|
||||
Протокол: [REST763.844s](ux-ui/acceptance/chr238-rest-renewal.json). Следующий239 — реальный S3 restore через UI только собственного bridge без портов/адресов, затем retention в отдельном own scope. REST остаётся открытым для корреляции воспроизведённого сбоя/согласованного сравнения firmware; обновление RouterOS не выполнялось.
|
||||
|
||||
## 12.5.237 — отсутствующие файлы бэкапов и безопасное удаление записи (2026-10-14)
|
||||
|
||||
API добавляет необязательный localFileStatus: available/missing/unknown/not-stored. Локальные проверки ограничены восемью workers и не опрашивают S3. Ошибка доступа/каталог/некорректный путь не превращаются в «файл отсутствует». Для local/missing существующая таблица ReUI показывает «Нет файла», описание и блокирует скачивание/restore. Для both/missing остаётся запрос S3; состояние unknown и старый DTO не блокируются по догадке. Проверка наличия файла перед импортом остаётся обязательной на backend.
|
||||
|
||||
Подтверждение удаления отсутствующего локального файла обещает только удаление строки истории. UI отправляет recordOnly=true и требует HTTP204 с X-Backup-Delete-Mode:record-only. Backend повторно проверяет missing/local/no-S3; появившийся файл даёт409 с сохранением файла и каталога. В этом режиме unlink никогда не вызывается, включая внешнее появление файла после проверки. Общий gate обеспечивает координацию одного процесса; несколько writers/instances остаются отдельной приёмкой.
|
||||
|
||||
Contracts/backend build, TypeScript и scoped ESLint прошли. test:backups прошёл после разрешённого запуска локальных HTTP-фикстур: первоначальный sandbox EACCES127.0.0.1 не был ошибкой приложения. E2E:37 исходных сценариев file/data/operations/storage и2 новых record-only receipt; после поздней защиты повторены20 затронутых сценариев. Итого39 уникальных, повторные запуски не прибавлены. Production owned SQL/API:5 статусов, download200/404, restore400/not-applied/nativeRequests0, сохранение каталога, recreated-file409 и record-only204/header. Собственные DB/role/container удалены; S3/CHR из этой SQL-фикстуры не опрашивались.
|
||||
|
||||
Production backend/frontend ux-backups237 собраны и развёрнуты:508 backend source/1068 compiled и529 frontend source совпали с локальными манифестами. Реальный Portal login и UI1440/390 показали10 существующих local/missing записей, disabled download/restore, корректное описание удаления (только открытие и отмена), pageerrors0/backupwrites0/globaloverflow0. Исходные10 SQL-строк сравнивались целиком до/после; ни одна не удалена. Отсутствующие старые файлы не восстановлены и не объявлены доступными. Приватный SQL-снимок удалён после сверки. Откат: backend ux-backup234/frontend ux-routing218 сохранены.
|
||||
|
||||
Доказательства: [SQL/API](ux-ui/acceptance/backup-availability237.json), [live UI](ux-ui/acceptance/backups237-live-ui.json), [production сверка](ux-ui/acceptance/backups237-deployment.json). Снимки: [ПК](ux-ui/screens/backups237-missing-desktop.png), [телефон](ux-ui/screens/backups237-missing-mobile.png).
|
||||
|
||||
| Референс | Схема доработки |
|
||||
| --- | --- |
|
||||
| [ReUI Data Grid Filtering2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | История → статус файла → доступные действия → подтверждённый результат; missing → только запись → проверка409/receipt204 |
|
||||
|
||||
Следующий238 фиксирует уже выполненное длительное REST-наблюдение. Затем — S3 restore через реальный UI в пределах собственного bridge и retention. Полная конфигурация CHR, arbitrary PKI, другие ОС, public IPv6, multi-instance и внешние jobs не приняты этим блоком.
|
||||
|
||||
## Актуальная точка продолжения — 2026-10-15
|
||||
|
||||
Этапы0–11 завершены в локальных границах журнала. История выполненных внешних блоков и доказательства сохранены в [журнале](ux-ui-stage-12.md) и [протоколе](ux-ui-external-acceptance.md). Реальная Telegram доставка201 и Portal SSO195–199 приняты в описанных границах. Multi-instance, внешние аккаунты/клиентские ОС и оставшиеся профильные сетевые ограничения открыты.
|
||||
|
||||
По поручению2026-10-09 работать укрупнёнными разделами, последовательно на текущей модели: карта возможностей → исправления → профильные тесты → build/deploy → собственные реальные сценарии → cleanup → один локальный коммит без push. Проверять квоту после завершённого раздела; незавершённые проверки явно переносить в журнал.
|
||||
|
||||
## Остаток приёмки по группам — 2026-10-15
|
||||
|
||||
Этапы0–12 завершены в пределах документированной лабораторной приёмки2026-10-15. Ниже семь групп дополнительного охвата; это не обязательные новые этапы основного плана и не обещание числа окон. Принятые сценарии не запускать заново без изменения кода или найденного риска. Для расширения стенда отдельно нужны перечисленные условия.
|
||||
|
||||
| Группа | Подтверждено | Открытый объём / условие |
|
||||
| --- | --- | --- |
|
||||
| REST и достоверность данных | Нативные наблюдения236/238; ограничение shared REST pools257,12 параллельных чтений двух CHR и25 backend-профилей прошли | После fix262 приняты21 burst/252 запроса за10min на одном endpoint; более длительные/иные endpoints, историческая причинность всех401/500 и сравнение версий отдельно |
|
||||
| Клиентские ОС и внешняя сеть | CHR↔CHR/Linux; Android StrongSwan full-tunnel и reconnect227 подтверждены пользователем | Windows/macOS/iOS и другие клиенты; независимые WAN/multi-WAN. Публичного IPv6 на предоставленном стенде нет — проверка требует другого подключения |
|
||||
| Масштаб и устойчивость | Контролируемые PG lock/dedupe/loss/recovery, отдельные multi-process сценарии194/200/201 | Несколько полноценных backend/worker со всеми writers, длительный rekey/traffic, физические потери WAN/DB и maximum throughput |
|
||||
| Хранилища и внешние jobs | Реальные Portal/Telegram195–201, Selectel S3/limited bridge restore/retention228–240, GeoIP mirror242; контейнеры248; production ACME250 и реальное renewal/rotation259 с trusted TLS/cleanup | Large native export/migration buckets/multi-instance S3; CA revocation отдельно не принят. Gitea publishing CI не запускался: действует no push. Direct licensed MaxMind отсутствует в текущей реализации |
|
||||
| Расширенные сетевые конфигурации | GRE/WG/VXLAN/IPsec/OSPF/BFD/BGP в записанных сценариях, включая private IPv6 | from-pool/EUI-64/multiple-address import/export, outer IPv6, произвольная PKI/OID/path-length, независимые внешние peers и длительные переходы. BFD-only gate не гарантирован |
|
||||
| UX, доступность и производительность | UI226, ARIA мастеров251, новая проверка260 текущего runtime описана выше | Default UI260/261:120 unique states30 экранов приняты в автоматическом scope; основная регрессия263:1396 и context264:221 приняты; ручная screen-reader приёмка отдельно. Synthetic timing не field CWV, scoped axe не полная WCAG сертификация |
|
||||
| Границы выпуска | Датированный журнал, протоколы и локальные коммиты без push | [Итоговый акт](ux-ui-acceptance-candidate.md) готов; production-выпуск не выполнялся, лабораторный успех не означает приёмку всех конфигураций |
|
||||
|
||||
Portal offline JWT действует доexp после logout/role change; это записанная граница198, не мгновенная revocation. Controlled Telegram unknown/retry201 не доказывает физическую потерю ACK в WAN. Архивные записи ниже отражают состояние на свою дату; актуальный статус задают эта таблица и верхняя точка продолжения.
|
||||
|
||||
## Цель и обязательные требования
|
||||
|
||||
Информативный, лаконичный и интуитивно понятный интерфейс с полноценной обработкой API, ошибок, прав и состояний данных. ReUI PRO, Frame и стиль `base-nova`; переиспользование установленных компонентов и общих композиций KpiStatGrid, ServerTileRail, CodeExportSheet. Основной сценарий — ПК с адаптацией для телефона; доступность обязательна.
|
||||
|
||||
Изменения выполняются как fullstack-работа: проверять контракт и поведение backend, а не только внешний вид. Не показывать успешную операцию до подтверждения API, не подменять неизвестные значения нулями. Локальные проверки используют реальные HTTP-пути с подменой ответов. Моки достаточны для локальной проверки UI и обработки ответов, но не доказывают применение конфигурации RouterOS, работу JWT в реальном окружении или точность IPFIX.
|
||||
|
||||
## Распределение работы и лимиты
|
||||
|
||||
- Пятичасовое окно — квота использования, а не пять часов непрерывной разработки. Расход заранее неизвестен; этап ограничивается конкретным результатом и проверками.
|
||||
- По умолчанию один крупный этап на окно. Небольшие блоки объединять после проверки доступной квоты. Учитывать и общий недельный лимит аккаунта.
|
||||
- Проверять квоту в начале этапа и после законченного блока. Базовый резерв — 25% пятичасового окна: не начинать новый блок, завершать проверки и сохранять состояние.
|
||||
- Последующие прямые указания пользователя «до конца лимитов» разрешают работать ниже базового резерва, сохраняя возможность завершить проверки, журнал и коммит. Не начинать блок, который нельзя безопасно закончить.
|
||||
- Работать последовательно, без параллельных агентских задач. Не менять модель посреди этапа без необходимости.
|
||||
- После каждого завершённого этапа или самостоятельного проверенного блока делать локальный коммит. **Без push.** Сообщение коммита — по AGENTS.md, с русским subject после префикса.
|
||||
- Исторические проценты и даты сброса из первоначального плана не являются текущими: перед работой получать актуальные лимиты.
|
||||
|
||||
## Этапы и критерии завершения
|
||||
|
||||
| Этап | Объём | Точка завершения | Распределение |
|
||||
| --- | --- | --- | --- |
|
||||
| 0. Подготовка | Зафиксировать состояние проекта, базовые проверки, таблицы и потребителей Filters, исходные экраны | Журнал, исходные ошибки, карта миграции | Первое окно |
|
||||
| 1. Достоверность операций | Сохранение, удаление, опрос серверов; сохранение формы и данных при ошибках | Проверены успех, ошибка API, отсутствие доступа, повторное нажатие | Вместе с 0 при достаточном резерве |
|
||||
| 2. Основа миграции | Связанная группа ReUI Data Grid/TanStack, общая оболочка, одна таблица серверов, подготовка Filters | Эталонная таблица, зависимости и образец миграции | Отдельное окно |
|
||||
| 3. Основные таблицы | Обзор, серверы, мониторинг, трафик, статистика, справочники | Проверены таблицы группы, оставшиеся потребители перечислены | Отдельное окно |
|
||||
| 4. Остальные таблицы | VPN, маршрутизация, управление, системные разделы; удаление старого API Filters | Нет смешения старого и нового API, общие проверки проходят | Отдельное окно |
|
||||
| 5. Состояния данных | Частичные сбои дашборда, последние данные, свежесть, гонки запросов | Проверены первоначальная ошибка, частичный сбой, фоновое обновление | Отдельное окно |
|
||||
| 6. Оболочка и дашборд | Навигация, контекст, подписи, сводка, очередь проблем, переходы к объектам | Проверены схемы и экраны ПК/телефона, переходы работают | Отдельное окно |
|
||||
| 7. Серверы и мониторинг | Единый UX таблиц, деталей и форм; URL-контекст, права | Сценарий «проблема → сервер → действие → возврат» работает | Отдельное окно |
|
||||
| 8. Трафик и статистика | Периоды, единицы, фильтры среза, связь графиков и таблиц, пустые состояния | Нет смешения live/истории и подмены неизвестных значений нулями | Отдельное окно; допускается несколько блоков |
|
||||
| 9. VPN и сетевые операции | WireGuard, IPsec, GRE, VXLAN, Firewall, Filters; выбор устройства, формы | Контекст устройства сохраняется, результат операций подтверждён API | Отдельное окно |
|
||||
| 10. Маршрутизация и диагностика | BGP, OSPF, рекурсивные маршруты, оптимизатор, диагностика, карта, терминал | Проверены профильные сценарии без изменения правил сетевых операций | Отдельное окно |
|
||||
| 11. Администрирование | Пользователи, контейнеры, сертификаты, резервирование, оповещения, сбор данных, релизы, настройки | Общие шаблоны применены, ошибки операций и интеграций понятны | Разделено на 11А и 11Б |
|
||||
| 12. Итоговая приёмка | Доступность, адаптивность, права, производительность, сквозная регрессия | Production build, тесты, ReUI checklist, список ограничений | Отдельное окно |
|
||||
|
||||
Это 13 контрольных этапов, а не обещание уложиться в 13 окон. Основная неопределённость — миграция компонентов и применение изменений в сетевых разделах.
|
||||
|
||||
Этапы 2–4 выполняются в отдельной ветке миграции (`codex/reui-v9-migration`). Промежуточные остановки допустимы с точным перечнем ошибок; выпуск до завершения этапа 4 не допускается. Само завершение этапа не является разрешением на push или deployment.
|
||||
|
||||
## Референсы и схемы
|
||||
|
||||
Для каждой группы экранов сначала использовать одну схему как эталон, затем применять её последовательно. Не пересобирать весь визуальный план в каждом окне.
|
||||
|
||||
| Этапы | Референсы ReUI PRO | Схема доработки |
|
||||
| --- | --- | --- |
|
||||
| 6 | [App Shell 12](https://reui.io/preview/base/app-shell-12?ref=mcp), [Stats 12](https://reui.io/preview/base/stats-12?ref=mcp) | Навигация → сводка → проблемы → измерения |
|
||||
| 2–4, 7–8 | [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Фильтры → таблица → детали → результат |
|
||||
| 7, 9–10 | [List 9](https://reui.io/preview/base/list-9?ref=mcp), [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp) | Сервер → объект → форма → подтверждение API |
|
||||
| 11 | [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp) | Секция → состояние → действие → результат |
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["0–1: подготовка и операции"] --> B["2–4: миграция ReUI"]
|
||||
B --> C["5: достоверность данных"]
|
||||
C --> D["6–8: основные экраны"]
|
||||
D --> E["9–10: сетевые разделы"]
|
||||
E --> F["11: администрирование"]
|
||||
F --> G["12: приёмка"]
|
||||
```
|
||||
|
||||
```text
|
||||
ПК: [Навигация] [Контекст и действия ]
|
||||
[Период / фильтры ]
|
||||
[Сводка ]
|
||||
[Список объектов] [Детали / результат]
|
||||
|
||||
Телефон: [Навигация и контекст]
|
||||
[Действия / фильтры ]
|
||||
[Сводка ]
|
||||
[Список объектов ]
|
||||
[Детали / результат ]
|
||||
|
||||
Данные: контекст → загрузка → подтверждённые данные
|
||||
↘ ошибка + повтор
|
||||
новый контекст ≠ старые данные; неизвестное ≠ ноль
|
||||
```
|
||||
|
||||
## Текущая точка продолжения — 2026-10-15
|
||||
|
||||
Этапы0–11 завершены в границах локальной приёмки; реальные сетевые операции и интеграции дополнительно проверены в12.5. Итоговый статус этапа12 и точный проверенный контур задаются [актом приёмки](ux-ui-acceptance-candidate.md) и верхней датированной записью [журнала](ux-ui-progress.md). Старое утверждение «этапы10–12 не начаты» удалено как не соответствующее результатам.
|
||||
|
||||
| Группа | Завершённый объём | Документ |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | Подготовка, операции, миграция таблиц и состояния данных | [Журнал](ux-ui-progress.md) |
|
||||
| 6–8 | Оболочка, серверы, мониторинг, трафик и статистика | [Этап6](ux-ui-stage-6.md), [этап7](ux-ui-stage-7.md), [этап8](ux-ui-stage-8.md) |
|
||||
| 9–10 | VPN, Firewall, Filters, маршрутизация и диагностика | [Этап9](ux-ui-stage-9.md), [этап10](ux-ui-stage-10.md) |
|
||||
| 11А–11Б | Администрирование, оповещения, интеграции и настройки | [Этап11А](ux-ui-stage-11a.md), [этап11Б](ux-ui-stage-11b.md) |
|
||||
| 12 | Общая регрессия и реальный стенд; ограничения перечислены отдельно | [Этап12](ux-ui-stage-12.md), [матрица](ux-ui-remaining-acceptance.md) |
|
||||
|
||||
Следующие разделы с номерами9.x и датами сентября/начала октября сохраняют исторические результаты. Они не отменяют актуальный статус выше и не задают новую очередь уже завершённых работ.
|
||||
|
||||
## Проверенные экраны Filters — блок 9.46
|
||||
|
||||
| Референс плана | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| Data Grid Filtering 2: устройство → свежесть → таблица | [Экран](ux-ui/screens/filters-desktop.png) | [Экран](ux-ui/screens/filters-mobile.png) |
|
||||
| Sheet 8: Community → действие → подтверждение API | [Форма](ux-ui/screens/filters-rule-desktop.png) | [Форма](ux-ui/screens/filters-rule-mobile.png) |
|
||||
|
||||
Снимки HTTP-фикстур просмотрены; в блоке 9.47 прошли общая регрессия Filters (33 E2E) и production build frontend (34 страницы). Этап 9 остаётся в работе; следующие блоки — ограничения IPsec/VXLAN и общего GRE-каталога по журналу.
|
||||
|
||||
В блоках 9.48–9.52 исправлены чтение, readiness, свежесть и контекст IPsec; прошли профильные операции, ПК/телефон и frontend build. Этап 9 открыт; далее VXLAN/GRE.
|
||||
|
||||
| IPsec — проверенные экраны | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| Устройство → свежесть → клиенты | [Экран](ux-ui/screens/ipsec-desktop.png) | [Экран](ux-ui/screens/ipsec-mobile.png) |
|
||||
| Клиент → форма → подтверждение API | [Форма](ux-ui/screens/ipsec-client-desktop.png) | [Форма](ux-ui/screens/ipsec-client-mobile.png) |
|
||||
| Устройство → peer/сертификаты → действия | [Серверы](ux-ui/screens/ipsec-servers-desktop.png) | [Сервер](ux-ui/screens/ipsec-servers-mobile.png) |
|
||||
|
||||
## Порядок продолжения и журналирования
|
||||
|
||||
Перед работой читать этот план, начало журнала, git status и последние коммиты; сохранять чужие изменения. Затем проверить квоту и выбрать завершённый по смыслу блок текущего этапа.
|
||||
|
||||
После блока записать в `ux-ui-progress.md`:
|
||||
|
||||
- результат и затронутые компоненты;
|
||||
- выполненные проверки и известные ошибки;
|
||||
- оставшийся объём и точный следующий шаг;
|
||||
- решения по API и совместимости;
|
||||
- границы локальной проверки и текущую квоту.
|
||||
|
||||
Профильные проверки выполнять после каждого блока. Полная регрессия — после миграции и при итоговой приёмке; между этапами расширять её при изменении общей основы. Не объявлять этап завершённым только по успешной сборке или тестам на моках.
|
||||
|
||||
Для новой задачи:
|
||||
|
||||
> Продолжи UX/UI-план из docs/ux-ui-plan.md по журналу docs/ux-ui-progress.md. Сначала проверь состояние файлов и остаток лимита. Выполни следующий незавершённый блок, проверь результат, обнови журнал и сделай локальный коммит без push.
|
||||
|
||||
## GRE/VXLAN — локальная визуальная приёмка 2026-09-30
|
||||
|
||||
| Экран / референс | ПК | Телефон | Схема |
|
||||
| --- | --- | --- | --- |
|
||||
| GRE · List 9 / Stats 12 | [Снимок](ux-ui/screens/gre-desktop.png) | [Снимок](ux-ui/screens/gre-mobile.png) | Устройство → сводка среза → туннели |
|
||||
| GRE · Sheet 8 | [Форма](ux-ui/screens/gre-form-desktop.png) | [Форма](ux-ui/screens/gre-form-mobile.png) | Контекст → поддерживаемые поля → подтверждение API |
|
||||
| VXLAN · Data Grid Filtering 2 | [Снимок](ux-ui/screens/vxlan-desktop.png) | [Снимок](ux-ui/screens/vxlan-mobile.png) | Устройство → подтверждённый срез → просмотр |
|
||||
| VXLAN · Sheet 8 | [Экспорт](ux-ui/screens/vxlan-export-desktop.png) | [Экспорт](ux-ui/screens/vxlan-export-mobile.png) | Снимок → актуальность → код → копирование/файл |
|
||||
|
||||
HTTP-фикстуры; layout/клавиатура проверены. Production frontend build и 183 E2E прошли в 9.63. RouterOS/JWT остаются отдельной приёмкой; актуальная точка продолжения — в журнале.
|
||||
|
||||
Этап 9 завершён 2026-09-30 в границах локальной приёмки (209 E2E, frontend/backend build). Внешние ограничения — журнал 9.64. Следующий этап — маршрутизация/диагностика (10); схема и референсы сохраняются, сетевые правила применения не меняются.
|
||||
|
||||
Этап 10 начат 2026-09-30. Карта API, референсы, схема и совместимость: [ux-ui-stage-10.md](ux-ui-stage-10.md). Точная точка продолжения — в журнале.
|
||||
|
||||
## BGP — локальная визуальная приёмка 2026-09-30
|
||||
|
||||
| Экран / референс | ПК | Телефон | Схема |
|
||||
| --- | --- | --- | --- |
|
||||
| BGP · List 9 / Data Grid Filtering 2 | [Снимок](ux-ui/screens/bgp-desktop.png) | [Снимок](ux-ui/screens/bgp-mobile.png) | Устройство → свежесть → сводка → фильтры/сессии |
|
||||
| BGP · Data Grid детали | [Детали](ux-ui/screens/bgp-detail-desktop.png) | [Детали](ux-ui/screens/bgp-detail-mobile.png) | URL сессии → подтверждённые поля / неизвестные значения |
|
||||
| BGP · Stats 12 / Frame | [Аналитика](ux-ui/screens/bgp-analytics-desktop.png) | [Аналитика](ux-ui/screens/bgp-analytics-mobile.png) | Точный срез → достоверные суммы → сравнение |
|
||||
|
||||
27 E2E/сборки прошли; реальные RouterOS/JWT/БД не проверены. Далее — OSPF, точное продолжение в журнале.
|
||||
|
||||
## OSPF — локальная визуальная приёмка 2026-09-30
|
||||
|
||||
| Экран / референс | ПК | Телефон | Схема |
|
||||
| --- | --- | --- | --- |
|
||||
| Интерфейсы · [List 9](https://reui.io/preview/base/list-9?ref=mcp) / [Stats 12](https://reui.io/preview/base/stats-12?ref=mcp) | [Снимок](ux-ui/screens/ospf-interfaces-desktop.png) | [Снимок](ux-ui/screens/ospf-interfaces-mobile.png) | Устройство → свежесть → интерфейсы → подтверждённая операция |
|
||||
| Соседи · [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | [Снимок](ux-ui/screens/ospf-neighbors-desktop.png) | [Снимок](ux-ui/screens/ospf-neighbors-mobile.png) | Поиск → один срез графа/таблицы → фактическое состояние |
|
||||
| Детали · Frame | [Снимок](ux-ui/screens/ospf-detail-desktop.png) | [Снимок](ux-ui/screens/ospf-detail-mobile.png) | URL узла → Router ID → соседи/интерфейсы → возврат фокуса |
|
||||
| BFD · Data Grid / Stats 12 | [Снимок](ux-ui/screens/ospf-bfd-desktop.png) | [Снимок](ux-ui/screens/ospf-bfd-mobile.png) | Срез → состояния → наблюдаемые таймеры/счётчики |
|
||||
|
||||
HTTP-фикстуры; локальная приёмка: 43 основных + 8 source E2E, 9 unit, production frontend. Реальный RouterOS/JWT/БД не проверен. Далее рекурсивные маршруты; точное продолжение в журнале.
|
||||
|
||||
## Рекурсивные маршруты — локальная визуальная приёмка 2026-09-30
|
||||
|
||||
| Экран / референс | ПК | Телефон | Схема |
|
||||
| --- | --- | --- | --- |
|
||||
| [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) / [List 9](https://reui.io/preview/base/list-9?ref=mcp) | [Детали](ux-ui/screens/recursive-routes-detail-desktop.png) | [390 px](ux-ui/screens/recursive-routes-detail-mobile.png), [320 px](ux-ui/screens/recursive-routes-detail-narrow.png) | Устройство → свежесть → группа/таблица → endpoints |
|
||||
| [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp) | [Форма](ux-ui/screens/recursive-routes-form-desktop.png) | [390 px](ux-ui/screens/recursive-routes-form-mobile.png), [320 px](ux-ui/screens/recursive-routes-form-narrow.png) | Полный снимок → параметры → подтверждение API → возврат фокуса |
|
||||
|
||||
48 основных + 8 source E2E, backend recursive regression и production frontend прошли. HTTP-фикстуры; RouterOS/DB/JWT остаются внешней приёмкой. Далее оптимизатор по журналу.
|
||||
|
||||
## Оптимизатор — локальная визуальная приёмка 2026-10-01
|
||||
|
||||
| Экран / референс | ПК | Телефон | Схема |
|
||||
| --- | --- | --- | --- |
|
||||
| Сводка · [Stats 12](https://reui.io/preview/base/stats-12?ref=mcp) / Frame | [Снимок](ux-ui/screens/route-optimizer-overview-desktop.png) | [390 px](ux-ui/screens/route-optimizer-overview-mobile.png), [320 px](ux-ui/screens/route-optimizer-overview-narrow.png) | Источник → объяснение модели → сводка → OSPF |
|
||||
| Настройки · [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp) | [Снимок](ux-ui/screens/route-optimizer-settings-desktop.png) | [390 px](ux-ui/screens/route-optimizer-settings-mobile.png), [320 px](ux-ui/screens/route-optimizer-settings-narrow.png) | Пороги → вес → локальный пересчёт |
|
||||
| Community · [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | [Снимок](ux-ui/screens/route-optimizer-community-desktop.png) | [390 px](ux-ui/screens/route-optimizer-community-mobile.png), [320 px](ux-ui/screens/route-optimizer-community-narrow.png) | Устройство → базовый расчёт → модельная рекомендация → закрепление |
|
||||
|
||||
47 основных + 8 source E2E, backend optimizer/live-maps, production frontend/backend прошли. Исходные значения отдельно от модели; Community apply недоступен, демо только симуляция. HTTP/DI фикстуры; реальный RouterOS/JWT/БД остаётся внешней приёмкой. Далее карта/терминал; ограничения и точное продолжение — в журнале.
|
||||
|
||||
## Карта сети — промежуточные экраны 2026-10-01
|
||||
|
||||
| Экран / референс | ПК | Телефон | Схема |
|
||||
| --- | --- | --- | --- |
|
||||
| Оболочка · [Frame](https://reui.io/components/frame?ref=mcp) / [API](https://reui.io/docs/components/base/frame?ref=mcp) | [Обзор](ux-ui/screens/network-map-overview-desktop.png) | [390 px](ux-ui/screens/network-map-overview-mobile.png), [320 px](ux-ui/screens/network-map-overview-narrow.png) | Источник → свежесть → слои/фильтры → карта |
|
||||
| Детали · Frame / [List 9](https://reui.io/preview/base/list-9?ref=mcp) | [Детали](ux-ui/screens/network-map-detail-desktop.png) | [390 px](ux-ui/screens/network-map-detail-mobile.png), [320 px](ux-ui/screens/network-map-detail-narrow.png) | Устройство → фактические поля → действия → возврат |
|
||||
|
||||
Оболочка и клавиатурные действия проверены (35 + 12 E2E). Камера и читаемость малой топологии доработаны в 10.53 (16 E2E + 2 unit). Pointer/touch и пустые состояния приняты в 10.54: 39 основных + 12 source E2E, 10 unit и production frontend build. Реальные RouterOS/JWT/БД остаются внешней приёмкой; далее терминал.
|
||||
|
||||
### Терминал: локальная приёмка 10.57
|
||||
|
||||
REST запрос → ожидание → подтверждённый output / ошибка с сохранением команды. Выбор устройства и поле команды остаются доступными на ПК и телефоне. Референс — существующий ReUI Frame и List 9; детали проверок в журнале.
|
||||
|
||||
| Экран | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| Готовность | [PNG](ux-ui/screens/terminal-ready-desktop.png) | [390 px](ux-ui/screens/terminal-ready-mobile.png), [320 px](ux-ui/screens/terminal-ready-narrow.png) |
|
||||
| Вывод | [PNG](ux-ui/screens/terminal-output-desktop.png) | [390 px](ux-ui/screens/terminal-output-mobile.png), [320 px](ux-ui/screens/terminal-output-narrow.png) |
|
||||
|
||||
|
||||
### Диагностика: экраны 10.69
|
||||
|
||||
Референс — существующий ReUI Frame/FramePanel и List 9. Устройство → параметры → подтверждённый ответ API/ошибка → копирование или удаление. Расписание относится к 11Б.
|
||||
|
||||
| Экран | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| Готовность | [PNG](ux-ui/screens/probes-ready-desktop.png) | [390 px](ux-ui/screens/probes-ready-mobile.png), [320 px](ux-ui/screens/probes-ready-narrow.png) |
|
||||
| Вывод | [PNG](ux-ui/screens/probes-output-desktop.png) | [390 px](ux-ui/screens/probes-output-mobile.png), [320 px](ux-ui/screens/probes-output-narrow.png) |
|
||||
|
||||
|
||||
## Актуальное продолжение 2026-10-01
|
||||
|
||||
Этап 10 принят локально (10.71): 235 основных + 52 source E2E, 42 unit, frontend/backend build. Реальный RouterOS/Portal/PostgreSQL остаётся внешней приёмкой. Далее 11А — пользователи, контейнеры, сертификаты, резервирование; затем 11Б и 12. История прежних контрольных точек выше не заменяет актуальный журнал.
|
||||
|
||||
Карта этапа 11А: [API, референсы и схемы](ux-ui-stage-11a.md). Точный следующий блок и ограничения — журнал.
|
||||
|
||||
### Администрирование: экраны 11А
|
||||
|
||||
Пользователи и контейнеры приняты локально (11А.8/11А.13); референсы Settings 16 / Stats 12 / Sheet 8 и схемы — [карта 11А](ux-ui-stage-11a.md). Далее сертификаты и резервирование.
|
||||
|
||||
| Экран | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| Пользователи | [Профиль](ux-ui/screens/users-profile-desktop.png), [ошибка](ux-ui/screens/users-error-desktop.png) | [390](ux-ui/screens/users-profile-mobile.png), [320](ux-ui/screens/users-profile-narrow.png) |
|
||||
| Контейнеры | [Обзор](ux-ui/screens/containers-overview-desktop.png), [снимок](ux-ui/screens/containers-export-desktop.png) | [390](ux-ui/screens/containers-export-mobile.png), [320](ux-ui/screens/containers-export-narrow.png) |
|
||||
|
||||
Каталог Evolution защищён от неполного HTTP-ответа в 11Б.3.3.4.1; Подтверждение testConnection исправлено в 11Б.3.3.4.2; состояния интеграции остаются в объёме 11Б. Актуальная точка продолжения: 11Б.3.4.4 — строгие NetFlow API и backend эффекты, затем форма. GeoIP принят локально в 11Б.3.4.3 (13 основных + 6 source E2E, ПК/390/320); реальные интеграции не проверены. GeoIP known/dirty/partial/unknown guard приняты в 11Б.3.4.2. GeoIP RBAC исправлен в 11Б.3.4.1 (traffic read/write вместо catch-all dashboard read). Scheduler принят локально в 11Б.3.3.7 (46 основных + 6 backend source E2E, ПК/390/320); внешние интеграции не доказаны. Параллельных агентов не использовать. Ручные run-now/refresh, общий lock/права и сообщения skipped/partial/event/status приняты в 11Б.3.3.6.3. Точечные операции настроек, ввод и подтверждённый сброс dirty приняты в 11Б.3.3.6.2. Независимые strict settings readers и защита черновиков подключены в 11Б.3.3.5; реальные интеграции остаются внешней приёмкой. Независимые scheduler status/runs и достоверные KPI приняты в 11Б.3.3.3. Strict history/unknown/свежесть приняты в 11Б.3.3.2. Контекст/abort/revision и исходный lint исправлены в 11Б.3.3.1; далее независимые readers/dirty states и операции. GeoIP API принят в 11Б.3.2. Scheduler API основа проверена в 11Б.3.1, пока не подключена к странице. Совместимость JSONB/legacy snapshot и foreign guard проверены в 11Б.2; исходные lint/context ограничения страницы описаны в журнале. Общий runner исправлен в 11Б.1; карта оставшегося этапа — [11Б](ux-ui-stage-11b.md). Этап 11А принят локально в 11А.33: backups 71 основных + 28 source E2E, 27 frontend unit, backend профиль и production build. Backup scheduler cleanup проверен в 11А.32; общий dispatcher/journal status исправлен в 11Б.1, реальные интеграции остаются внешней приёмкой. S3/partial job/initial errors приняты в 11А.31.2.2. Диалоги ошибок приняты в 11А.31.2.1. Frame/первые 9 экранов приняты в 11А.31.1. URL/Filters контекст принят в 11А.30. Клиентский checkpoint restore принят в 11А.29.5. Backend outcome неизвестного импорта принят в 11А.29.4. Идентичность receipt принята в 11А.29.3. Backend cleanup удаления принят в 11А.29.2. Frontend delete/restore/download принят в 11А.29.1, затем URL/Frame/визуальная приёмка и scheduler cleanup. Frontend checkpoint/создание/serial polling приняты локально в 11А.28.2. API/основа наблюдения реализованы в 11А.28.1. Настройки расписания/S3 реализованы в 11А.27.1–11А.27.2. Каталоги/source/права реализованы в 11А.25, backend результат ручных операций исправлен в 11А.26. Сертификаты приняты локально в 11А.24, backups API стал строгим. State API, reader, snapshot merge и nullable представление подключены в 11А.14–11А.17.3; таблица требований — [этап 11А](ux-ui-stage-11a.md). Резервные копии и весь 11А приняты локально в 11А.33; внешние ограничения — журнал.
|
||||
|
||||
| Экран | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| История | [PNG](ux-ui/screens/backups-history-desktop.png) | [390](ux-ui/screens/backups-history-mobile.png), [320](ux-ui/screens/backups-history-narrow.png) |
|
||||
| Настройки | [PNG](ux-ui/screens/backups-settings-desktop.png) | [390](ux-ui/screens/backups-settings-mobile.png), [320](ux-ui/screens/backups-settings-narrow.png) |
|
||||
| Создание | [PNG](ux-ui/screens/backups-create-desktop.png) | [390](ux-ui/screens/backups-create-mobile.png), [320](ux-ui/screens/backups-create-narrow.png) |
|
||||
|
||||
Референсы: [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp), [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp), [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp). Схема: источник → сводка → история/настройки → immutable цель → подтверждение API/неизвестный результат.
|
||||
|
||||
|
||||
| Экран | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| Ошибка удаления | [PNG](ux-ui/screens/backups-delete-error-desktop.png) | [390](ux-ui/screens/backups-delete-error-mobile.png), [320](ux-ui/screens/backups-delete-error-narrow.png) |
|
||||
| Неизвестный импорт | [PNG](ux-ui/screens/backups-restore-unknown-desktop.png) | [390](ux-ui/screens/backups-restore-unknown-mobile.png), [320](ux-ui/screens/backups-restore-unknown-narrow.png) |
|
||||
|
||||
|
||||
| Экран | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| S3 ошибка | [PNG](ux-ui/screens/backups-s3-error-desktop.png) | [390](ux-ui/screens/backups-s3-error-mobile.png), [320](ux-ui/screens/backups-s3-error-narrow.png) |
|
||||
| Partial job | [PNG](ux-ui/screens/backups-partial-job-desktop.png) | [390](ux-ui/screens/backups-partial-job-mobile.png), [320](ux-ui/screens/backups-partial-job-narrow.png) |
|
||||
| Initial error | [PNG](ux-ui/screens/backups-initial-error-desktop.png) | [390](ux-ui/screens/backups-initial-error-mobile.png), [320](ux-ui/screens/backups-initial-error-narrow.png) |
|
||||
|
||||
|
||||
|
||||
Продолжение 2026-10-03: завершён 11Б.3.4.4.1 (строгие NetFlow API, 5 unit и 3 collector/probes E2E, typecheck/ESLint). Следующий блок — 11Б.3.4.4.2: backend экспорт/права и подтверждение сохранения отдельно от запуска listener. Purge и форма ещё требуют доработки.
|
||||
|
||||
Завершён 11Б.3.4.4.2: private export требует traffic write, GET не создаёт ключи, PUT отделяет сохранение от ошибки запуска listener. HTTP/JWT, backend build, lint и permissions прошли. Далее 11Б.3.4.4.3: конкурентное создание ключей/выборочные patch; purge и UI ещё не приняты.
|
||||
|
||||
Завершён 11Б.3.4.4.3: выборочная запись NetFlow patch и условная установка host keys, свежая подтверждённая пара; DI гонка/HTTP/JWT/build/lint прошли. Реальная PG гонка не проверена. Далее 11Б.3.4.4.4 — атомарность purge и частичные результаты.
|
||||
|
||||
Завершён 11Б.3.4.4.4: 6 таблиц/counters purge в общей транзакции, отдельные partition/listener/event warnings и nullable размер файлов. DI/HTTP/API/typecheck/build/lint прошли; реальный PG purge не запускался. Следующий шаг 11Б.3.4.4.5 — форма NetFlow и подтверждённые/частичные/неизвестные операции.
|
||||
|
||||
Завершён 11Б.3.4.4.5: форма NetFlow known/dirty/rights/lock, selective PUT, partial outcomes и review после unknown POST; 12 E2E/form unit/typecheck/lint/production build прошли. Далее 11Б.3.4.4.6 — source/adaptive приёмка, затем общий контракт IP/CIDR/DNS.
|
||||
|
||||
Завершён 11Б.3.4.4.6: 10 NetFlow backend source E2E, 3 responsive, 6 снимков (320 и ПК просмотрены), регрессия GeoIP/collector прошли. Далее 11Б.3.4.4.7: общий IP/CIDR/DNS ввод/фактический порт и отказ конкурентному purge вместо очереди. Затем приёмка NetFlow и Evolution.
|
||||
|
||||
Завершён 11Б.3.4.4.7.1: конкурентный purge получает 409 до удаления, неподтверждённый session lock соединения исключается из пула; DI/backend/build/lint/conflict E2E прошли. Реальный PG overlap не проверен. Далее 11Б.3.4.4.7.2 — общий IP/CIDR/DNS контракт и фактические порты.
|
||||
|
||||
Завершён 11Б.3.4.4.7.2: общий NetFlow IP/CIDR/DNS/ports patch, draft и backend проверяют его; инструкция использует фактический порт. 14 E2E, unit/HTTP/JWT, lint и оба builds прошли. Далее 11Б.3.4.4.7.3 — согласованный host export/маска, затем приёмка NetFlow и Evolution.
|
||||
|
||||
Завершён 11Б.3.4.4.7.3: host export из одного снимка, фактические mask/WG/IPFIX ports, strict keys/peers и безопасные однострочные комментарии. Builder/key/HTTP/JWT/build/lint прошли без запуска host/RouterOS. Далее 11Б.3.4.4.8 — приёмка NetFlow; затем 11Б.3.5 Evolution. Нестандартные prefix allocator не приняты.
|
||||
|
||||
Локальная приёмка NetFlow 11Б.3.4.4.8: 19 основных и 10 source E2E, backend JWT с purge, backend/frontend builds и API tests прошли в описанных блоках. Дублирующий purge Settings заменён переходом к единой панели (link E2E/typecheck). Исходные lint ошибки Settings остаются до его блока. Внешние PG/WG/RouterOS/Portal/нестандартный IPv4 prefix не приняты. Далее 11Б.3.5.1 — строгие Evolution settings/save/test API и затем provider/форма.
|
||||
|
||||
Завершён 11Б.3.5.1 — contracts/Evolution strict settings/save/test API: 3 unit, contracts build/typecheck/lint прошли. Новый PUT helper пока не подключён (backend старый receipt). Далее 11Б.3.5.2 backend selective save/подтверждение, затем provider и форма.
|
||||
|
||||
Завершён 11Б.3.5.2: Evolution backend selective RETURNING save/public receipt и проверка items upstream/test; DI HTTP/JWT, backend build/lint прошли. Старый provider совместим с публичными полями, ещё не мигрирован. Далее 11Б.3.5.3 — provider known/error/time/source; затем форма и upstream catalog validation.
|
||||
|
||||
Завершён 11Б.3.5.3.1: Evolution provider known/error/time/readers/source/strict receipts, статус Settings; 8 provider (один selector повторён), 2 прежних и 6 source E2E, lint/typecheck/production build прошли. Форма/consumer mocks ещё не приняты. Далее 11Б.3.5.3.2 — upstream catalog strict/unknown counts; затем 11Б.3.5.4 форма/consumers.
|
||||
|
||||
Завершён 11Б.3.5.3.2: strict upstream catalog, nullable ASN/community counts, unknown «—» вместо 0. Parser/aggregation/HTTP/JWT/build/typecheck/lint и provider/counts E2E прошли; locator inline details исправлен. Реальный Evolution/PG не принят. Далее 11Б.3.5.4.1 — форма Evolution dirty/rights/lock/key clear/source.
|
||||
|
||||
Завершён 11Б.3.5.4.1: отдельная форма Evolution dirty/rights/lock/clear confirmation/source; 17 основных, 8 source и 3 responsive E2E, typecheck/lint/build прошли. 6 снимков, 320/ПК/clear просмотрены. Общие Settings и live consumer mocks ещё не приняты. Далее 11Б.3.5.4.2 — consumers/sidebar unknown/disabled/no fallback.
|
||||
|
||||
Завершён 11Б.3.5.4.2: live catalog consumers/sidebar/Filters без demo fallback, unknown/disabled/last snapshot и current details; 25 E2E, typecheck/профильный lint/build прошли. 3 community screenshots, 320/ПК просмотрены. Sidebar sync-effect baseline error и Filters unused warnings описаны в журнале. Далее 11Б.3.5.5 — HTTP/JWT catalog и приёмка Evolution.
|
||||
|
||||
Завершён 11Б.3.5.5: Evolution catalog DI HTTP/JWT, один settings snapshot, backend test/build/lint прошли. Evolution принят локально в границах предыдущих form/provider/source/consumer/adaptive проверок; реальный upstream/PG/Portal/RouterOS не принят. Далее 11Б.3.6.1 — достоверные общие Settings без фиктивных сохранений/API keys/MFA; затем system DB, Alerts/Releases/probes.
|
||||
|
||||
Завершён 11Б.3.6.1: общие Settings без фиктивных сохранений/demo keys/MFA, реальная тема/source URL, переходы к инструментам; 32 E2E с одним исправленным locator, 3 source с исправленным alert locator, 8 Evolution source, typecheck/lint/build прошли. 6 screenshots, 320 просмотрены. System DB ещё не принят. Далее 11Б.3.6.1.2 health/source guards; затем 11Б.3.6.2 DB operations.
|
||||
|
||||
Завершён 11Б.3.6.1.2: DataSource health token/revision/abort/ABA, explicit checking и validated health body. 2 unit, 10 source/health, 16 Settings/Evo provider и 8 Evo source E2E, typecheck/lint/build прошли; два test setup уточнены. System monitor остаётся отдельным reader. Далее 11Б.3.6.2.1 — system DB API/credentials in events; затем backend outcomes и UI.
|
||||
|
||||
Завершён 11Б.3.6.2.1: system DB export PGDMP/leaf filename и restore strict receipt/limits/abort без повтора; DATABASE_URL удалён из новых event payload. 3 unit группы/typecheck/lint/backend и frontend builds прошли. UI/backend partial/restore transaction не приняты. Далее 11Б.3.6.2.2 — backend transaction/outcomes/DI HTTP/JWT, затем 11Б.3.6.2.3 форма.
|
||||
|
||||
Завершён 11Б.3.6.2.2.1: DI restore executor/--single-transaction/cleanup warning, file choose без фиктивного success, confirmation до receipt. 4 DI/3 API/2 browser tests, backend/frontend builds/typecheck/lint прошли; реальный PG restore не запускался. System DB не принят полностью. Следующий точный шаг 11Б.3.6.2.2.2 — backend core/restart/event partial outcomes + DI HTTP/JWT/concurrency; затем 11Б.3.6.2.3 source/lock/unknown UI.
|
||||
|
||||
2026-10-03: завершён 11Б.3.6.2.2.2, подтверждённый backup/restore отделён от restart/audit warnings; nonqueued concurrency, HTTP/JWT/API/UI проверки прошли локально. Далее DB форма 11Б.3.6.2.3.
|
||||
|
||||
2026-10-03: завершён 11Б.3.6.2.3.1, отдельная DB форма/lock/checkpoint/адаптивность; 10 E2E, API/proxy tests и build прошли. Далее source/ABA/unmount и приёмка DB.
|
||||
|
||||
2026-10-03: 11Б.3.6.2.3.2 — 6 source и 18 соседних E2E прошли; база принята в локальных границах. Далее 11Б.4.1 Alerts contracts/API.
|
||||
|
||||
2026-10-03: 11Б.4.1 — строгие Alerts output schemas/API и сверка save receipts; 5 unit/builds/typecheck/lint прошли. Module пока не подключён. Далее 11Б.4.2.1 backend Telegram.
|
||||
|
||||
2026-10-03: 11Б.4.2.1.1 — selective Telegram UPDATE RETURNING, strict send receipt; 7 DI/send tests/build/lint прошли. confirm-stability пропущен без PG. Далее HTTP/JWT 11Б.4.2.1.2.
|
||||
|
||||
2026-10-03: 11Б.4.2.1.2 — реальные Alerts HTTP/JWT gates и один Telegram stored snapshot, профильные tests/build/typecheck/lint прошли. Далее rules/groups 11Б.4.2.2.1.
|
||||
|
||||
2026-10-03: 11Б.4.2.2.1.1 — общая нормализация rules/groups и 400 до удаления; 8 unit и backend profile/builds/typecheck/lint прошли. Далее transaction receipt 11Б.4.2.2.1.2.
|
||||
|
||||
2026-10-03: 11Б.4.2.2.1.2 — transaction rules receipt/readback/lock, DI/API/JWT/build/typecheck/lint прошли. Реальный PG rollback/overlap и optimistic revision не приняты. Далее Alerts UI 11Б.4.3.1.
|
||||
|
||||
2026-10-03: 11Б.4.3.1.1 — live Alerts без первоначальных demo/0, strict primary reader/known/time, 3 E2E/lint/typecheck/build прошли. Далее independent secondary readers/source 11Б.4.3.1.2.
|
||||
|
||||
2026-10-03: 11Б.4.3.1.2.1 — strict secondary API (GRE partial failures/unknown status), 4 unit/typecheck/lint прошли. Module не подключён. Далее 11Б.4.3.1.2.2 independent UI/source.
|
||||
|
||||
## 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.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).
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,461 @@
|
||||
# Этап 10: маршрутизация и диагностика
|
||||
|
||||
Статус: завершён в границах локальной приёмки 2026-10-01 (10.71), внешние ограничения ниже. Работа последовательно, ReUI PRO/base-nova и существующий Frame. Правила применения сетевых операций не меняются.
|
||||
|
||||
## Референсы и схема
|
||||
|
||||
| Область | Референс | Схема доработки |
|
||||
| --- | --- | --- |
|
||||
| Устройства и сессии | [List 9](https://reui.io/preview/base/list-9?ref=mcp) | Контекст → подтверждённые объекты → проблемы |
|
||||
| Таблицы | [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Срез → фильтры → состояние данных → детали |
|
||||
| Детали и диагностика | [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp) | Объект → запрос → результат / ошибка с сохранением контекста |
|
||||
|
||||
Референсы перенесены из принятого плана; новые registry-компоненты не требуются.
|
||||
|
||||
[Устройство / URL] → [Подтверждённый снимок + время получения]
|
||||
↓
|
||||
[Сессии / маршруты / карта]
|
||||
↙ ↘
|
||||
[Частичный отказ] [Детали / диагностика]
|
||||
последние данные контекст сохранён
|
||||
статус неизвестен ↓
|
||||
[Результат API / повтор]
|
||||
|
||||
## Карта работ и порядок
|
||||
|
||||
| Порядок | Раздел / API | Обнаруженная проблема | Проверка результата |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | BGP: /bgp/sessions, новый /bgp/catalog | Отказ устройства превращается в []; нет проверки ответа/частичных ошибок; неизвестный мониторинг выдаётся за online | Успех, пустой опрос, частичный/полный сбой, повтор, смена источника |
|
||||
| 2 | OSPF: /ospf/all | Частичный отказ подменяется пустыми neighbors/areas/interfaces/BFD/routes | Последний снимок, неизвестные статусы и показатели |
|
||||
| 3 | Рекурсивные маршруты | Ответы каталогов и смена устройства требуют проверки; операции связаны с историей | Readiness, точный serverId, повтор/ошибка, URL |
|
||||
| 4 | Оптимизатор | Ошибка зависимого каталога скрывается; общий сбой удаляет последние данные | Неполнота явно показана, применение требует достоверного контекста |
|
||||
| 5 | Карта сети | GRE failures игнорируются; отказ GRE/probes превращается в пустые данные; нет общей защиты поздних ответов | Кэш и неизвестные рёбра/узлы, смена источника, пустые/ошибочные состояния |
|
||||
| 6 | Терминал | Проверить права, готовность устройства, поздний вывод и повторные отправки | Точный контекст, сохранение вывода, подтверждение выполнения |
|
||||
| 7 | Диагностика GRE: /servers/:id/probes/run, ros-src-address, filters/gre-tunnels | Отмена показана как done, нет строгого output/single-flight/source cleanup; каталоги маскируют ошибки | Подтверждённый результат, отмена отдельно, точный контекст, ошибки и права; расписание в 11Б |
|
||||
| 8 | Приёмка | ПК/телефон, клавиатура, переходы и профильная регрессия | Схемы/PNG, сборки, сценарии; внешние ограничения отдельно |
|
||||
|
||||
## Совместимость и границы
|
||||
|
||||
- Новый BGP-каталог sessions/failures. Старый агрегат /bgp/sessions сохраняет массив для оповещений; его миграция — 11Б. Новый экран не должен использовать неоднозначный агрегат.
|
||||
- Отказ выборного BGP-опроса должен иметь ошибочный HTTP-статус вместо успешного пустого массива.
|
||||
- Время получения браузером не объявляется временем измерения RouterOS. При сбое прошлые данные доступны, но не считаются текущими.
|
||||
- Неизвестные счётчики/статусы не подменяются нулями/успехом. Не добавляем недоступные API или фиктивные действия.
|
||||
- HTTP-фикстуры не подтверждают реальные RouterOS/JWT/БД и применение маршрутов/команд. Полный accessibility/performance аудит — этап 12.
|
||||
|
||||
## Блок 10.1 — подготовка
|
||||
|
||||
Прочитаны реализации BGP, OSPF, карты, оптимизатора и точки интеграции рекурсивных маршрутов/терминала. Сохранены порядок, схема, референсы и решение по совместимости BGP. Далее — серверный каталог с failures и проверкой контекста.
|
||||
|
||||
## Блок 10.2 — BGP API
|
||||
|
||||
Каталог sessions/failures и проверка контекста добавлены; старый агрегат совместим. Выборный отказ возвращает 503. Unit/Fastify/TypeScript/lint/backend build прошли. Следующий блок — потребитель нового каталога на экране BGP.
|
||||
|
||||
## Блок 10.3 — данные BGP
|
||||
|
||||
Экран мигрирован на каталог: валидация, кэш отказавшего устройства, неизвестные состояния, постоянный повтор и изоляция источника. 12 E2E/TypeScript/lint прошли. Далее — поля BGP, URL/свежесть и визуальная приёмка.
|
||||
|
||||
## Блок 10.4 — поля BGP
|
||||
|
||||
Новый parser сохраняет неизвестные таймеры/счётчики/AFI, не подменяет префиксы UPDATE-счётчиками; legacy API сохранён. Удалён придуманный экспорт. 13 E2E/unit/live-maps/TypeScript/lint/backend build прошли. Далее — URL/свежесть/источник/layout.
|
||||
|
||||
## Блок 10.5 — BGP URL/свежесть
|
||||
|
||||
server/session/tab и возврат/reload сохраняют контекст; недоступный объект не подменяется. Время успешного опроса каждого устройства не обновляется при отказе. 19 различных E2E/TypeScript/lint прошли. Далее — ASN/type, URL фильтров и layout.
|
||||
|
||||
## Блок 10.6 — BGP ASN/type
|
||||
|
||||
Отсутствующие/невалидные ASN и тип неизвестны; legacy parser сохранён. Unit/15 E2E/TypeScript/lint прошли. Далее — URL фильтров и layout.
|
||||
|
||||
## Блок 10.7 — фильтры BGP URL
|
||||
|
||||
Поиск/тип/состояние/FilterQuery сохраняются и валидируются; AFI варианты соответствуют снимку. 21 E2E, четыре unit, TypeScript/lint прошли. Далее — desktop/mobile и сборка BGP, затем OSPF.
|
||||
|
||||
## Блок 10.8 — BGP приёмка
|
||||
|
||||
27 E2E, unit/TypeScript/lint, frontend/backend build прошли. Шесть PNG просмотрены, мобильные подписи/детали исправлены. Далее — строгий каталог OSPF (BFD/routes сейчас скрывают свои ошибки). Внешние границы — журнал.
|
||||
|
||||
## Блок 10.9 — OSPF каталог
|
||||
|
||||
Строгий /ospf/catalog возвращает failures устройства; BFD/routes ошибки не скрываются. Снимок устройства атомарен, legacy /all и правила оптимизации сохранены. Unit/HTTP/backend build прошли; два исходных lint warning. Далее — экран OSPF.
|
||||
|
||||
## Блок 10.10 — OSPF данные
|
||||
|
||||
Каталог/inventory валидируются, кэш отказавшего устройства сохраняется, состояния/KPI неизвестны, топология не подменяет полный опрос. Убраны фиктивные live costs/mock применение. 17 E2E/TypeScript/lint прошли (два старых warning). Далее — операции/URL/свежесть/поля/layout.
|
||||
|
||||
## Блок 10.11 — OSPF операции
|
||||
|
||||
Lock/readiness, существующее mm:servers:write, валидация подтверждения и постоянная ошибка с повторным чтением. Поздний read/write не действует в другом источнике. 21 OSPF E2E/TypeScript/lint прошли (два старых warning). Далее — URL/времена/поля/layout.
|
||||
|
||||
## Блок 10.12 — OSPF времена
|
||||
|
||||
Время успешного опроса устройства сохраняется при отказах; подтверждение оптимизации API имеет отдельную отметку. Семь E2E/TypeScript/lint прошли. Далее — поля/URL/layout.
|
||||
|
||||
## 10.13. Состояния соседства и BFD
|
||||
|
||||
Все восемь состояний из [RouterOS OSPF](https://help.mikrotik.com/docs/spaces/ROS/pages/331612216/routing%2Bospf) сохранены. Переходные состояния — amber/Pending, неизвестные — neutral/Unknown, подтверждённый Down — red. Строгий каталог не подставляет Down при отсутствующем BFD state; старые endpoints совместимы. 14 E2E, два unit-теста, TS и обе production-сборки прошли. Далее неизвестные показатели, URL и визуальная приёмка.
|
||||
|
||||
## 10.14. Неизвестный cost соседа
|
||||
|
||||
Отсутствующий интерфейс не означает cost=10: таблица/линия/панель показывают «—». 11 E2E и TS прошли. Backend defaults/nullable показатели остаются следующим блоком.
|
||||
|
||||
## 10.15. Диапазон AS клиента BGP
|
||||
|
||||
Схема клиента принимает null либо 1..4294967295, согласованно со строгим backend parser. Неверный ответ сохраняет кэш как неизвестный. 13 data E2E и TS прошли.
|
||||
|
||||
## 10.16. Cost в области OSPF
|
||||
|
||||
Ключ включает устройство/interface/areaId. Конфликты шаблонов и недопустимый cost остаются неизвестными. 4 unit, 7 E2E и TS прошли; алгоритм оптимизации не изменён.
|
||||
|
||||
## Следующий блок: nullable показатели строгого каталога
|
||||
|
||||
| Поля | Текущее поведение | Требуемый результат и проверка |
|
||||
| --- | --- | --- |
|
||||
| BFD packets-rx/tx, state-changes | Отсутствие/ошибка превращается в 0 | null при отсутствии/ошибке, подтверждённый 0 сохраняется; сумма неизвестна при неполном составе |
|
||||
| BFD multiplier | Отсутствие превращается в 3 | null без фактического значения; диапазон проверить отдельно от состояния |
|
||||
| BFD tx/rx/hold timers | parseMs возвращает 0, UI скрывает даже известный 0 | Разделить null/0; проверить RouterOS duration, не подменять actual-tx желаемым интервалом |
|
||||
| Neighbor priority/state-changes | Подстановка 1/0 | null при неизвестности, priority=0 сохраняется; таблица показывает «—» |
|
||||
| Interface cost/priority/hello/dead | Подстановка 10/1/0 | Строгий parser отдельно от legacy/optimizer; неизвестный cost запрещает предложение оптимизации по неполному каталогу |
|
||||
| Route metric | ospf-metric подменяется distance | Distance не является OSPF cost; отсутствие metric остаётся null, отдельная проверка legacy совместимости |
|
||||
| Instance version/router-id | Подстановка/default значения | Сверить реальные признаки RouterOS; не дописывать измерения без источника |
|
||||
|
||||
Порядок: отдельные catalog DTO и strict parser → backend fixtures (missing/zero/malformed/known) → Zod → таблицы/сводка/топология → readiness операций → API E2E → профильная сборка. Старые endpoints и оптимизатор сохраняют совместимость, пока отдельный контракт не проверен. Значения cache при отказе помечаются последним снимком; времена чтения/записи остаются раздельными.
|
||||
|
||||
После nullable блока: URL устройства/вкладки/поиска с back/reload и отсутствующим устройством; при переходе по истории во время write обязательно освободить lock прежней операции только в соответствующем контексте. Затем одна desktop/mobile схема и скриншоты; не считать OSPF принятым до этих проверок.
|
||||
|
||||
## 10.18. Nullable BFD и соседство
|
||||
|
||||
Строгий каталог сохраняет null/0 отдельно для BFD timers/counters/multiplier и priority/stateChanges соседа. Actual TX не подменяется desired TX; units/clock duration проверяются строго. 15 HTTP E2E, raw backend fixtures, TS/backend build прошли. Далее interface/instance/route nullable contract и readiness. [RouterOS BFD](https://help.mikrotik.com/docs/spaces/ROS/pages/191299691/BFD) и [OSPF](https://help.mikrotik.com/docs/spaces/ROS/pages/331612216/routing%2Bospf) — источники семантики.
|
||||
|
||||
## 10.19. Nullable интерфейсы и метрики
|
||||
|
||||
Строгий catalog DTO сохраняет неизвестные поля interface/instance; route metric не подменяется distance. Наблюдаемый interface cost=0 сохранён согласно [RouterOS OSPF](https://help.mikrotik.com/docs/spaces/ROS/pages/331612216/routing%2Bospf); политика записи min=1 прежняя. При unknown costs/flags операция не предлагается. 21 E2E, 4 unit, backend regression и обе production-сборки прошли. Далее URL/layout и дополнительная проверка метаданных.
|
||||
|
||||
## 10.20. URL и завершение записи после history
|
||||
|
||||
Device/tab сохранены в URL; invalid/missing context не расширяет срез. Unmounted child освобождает lock только живого родителя, который перечитывает каталог; source unmount игнорирует старый callback. 17 основных + 8 source E2E, два unit, TS/lint прошли. Далее search/object context/layout.
|
||||
|
||||
## 10.21. Поиск и узел
|
||||
|
||||
q/node сохраняются вместе с server/tab. Таблица и топология отражают один срез; пустой поиск не утверждает отсутствие конфигурации. 28 разных E2E, 3 unit, TS/lint и frontend production прошли. Accessible search/close; операция явно относится ко всем интерфейсам устройства. Далее metadata/layout/keyboard.
|
||||
|
||||
## 10.22. Подтверждённые метаданные/узлы
|
||||
|
||||
Route subtype и BFD multihop неизвестны без наблюдения. Router ID refs/ambiguity не создают ложную связь устройств; только уникальный фактический ID объединяет узлы. 13 E2E, 2 identity unit, backend regression/build и TS/lint прошли. Далее layout/keyboard/motion/приёмка.
|
||||
|
||||
## 10.23. Приёмка OSPF на ПК/телефоне
|
||||
|
||||
Срез устройства → свежесть → профильная сводка → граф/таблица → детали → подтверждение API. Детали на телефоне под графом; Escape возвращает фокус; reduced motion соблюдается. 43 основных + 8 source E2E, 9 unit и production frontend прошли; screenshot/keyboard/motion проверены. Прежние BGP/OSPF backend fixtures/build прошли в 10.22. OSPF принят локально, следующий раздел — рекурсивные маршруты. Реальный RouterOS/JWT/DB не проверен.
|
||||
|
||||
## 10.24. Операции рекурсивных маршрутов
|
||||
|
||||
Strict receipts/serverId, общая блокировка save/delete/restore, форма и последний снимок при ошибке; разные routing tables и скрытые поиском endpoints сохранены. 35 E2E, TS/lint, обе сборки и config-sync прошли; 11 общих history повторно прошли после разделения доступности read/write. Далее backend validation, URL/source и observed metadata/layout. Legacy parser пока не мигрирован; сетевые правила применения прежние.
|
||||
|
||||
## 10.25. Валидация PUT/restore
|
||||
|
||||
Явный список и точный serverId обязательны; повреждённая версия не превращается в empty/default конфигурацию. HTTP injection проверяет отказ до сети; auth/config-sync/build/lint прошли. Intentional empty и canonical snapshot без id совместимы; алгоритм применения прежний. Далее URL/source, observed parser и layout.
|
||||
|
||||
## 10.26. URL/history/source
|
||||
|
||||
server/q/route/table принадлежат экрану; default replace, выбор/раскрытие history. Missing-device fallback панели запрещён. Source lock сохраняется над device context; late write освобождает lock и запускает чтение текущего среза только соответствующего источника. 38 разных основных + 8 source E2E, 2 unit, TS/lint и production frontend прошли. Далее observed metadata и layout.
|
||||
|
||||
## 10.27. Строгий наблюдаемый каталог
|
||||
|
||||
Отдельные catalog endpoints сохраняют legacy потребителей. Неполный owned snapshot отклоняется целиком до сохранения; нули, disabled и unset scope сохранены. Gateway active означает использование в маршруте, без заявления о reachability; страна только явная. 42 основных + повторные 18 data/values, 8 source, backend parser/HTTP/config-sync/build и TS/lint прошли. Далее визуальная приёмка. Реальная версия RouterOS требует отдельной проверки.
|
||||
|
||||
## 10.28. Локальная приёмка рекурсивных маршрутов
|
||||
|
||||
48 основных + 8 source E2E, backend recursive tests, lint/production frontend прошли. 1440/390/320 px, keyboard раскрытие, trap и возврат фокуса, parent-owned scroll; шесть экранов в плане. Неизвестный тип не подменяется EN. ReUI audit consumer-композиции выполнен без изменения vendor/theme. Далее оптимизатор; RouterOS/DB/JWT остаются внешней приёмкой.
|
||||
|
||||
## 10.29. Community: расчёт и симуляция
|
||||
|
||||
Live таймерный успех убран; demo симуляция явно подписана, cleanup/lock сохранены. Модельная базовая цепочка и индекс в баллах обозначены; автоприменение недоступно, ECMP/RPF/VRF локальные. Исправлены mock-ID матриц. 6 E2E, TS/lint прошли. Далее strict чтение и OSPF операции; раздел ещё не принят.
|
||||
|
||||
## 10.30. Согласованные источники расчёта
|
||||
|
||||
Строгие inventory/rules/probes, Promise.allSettled и публикация только полного valid snapshot. Partial сбой сохраняет предыдущее; initial неизвестность без нулей; epoch/freshness. 16 E2E + 2 unit, lint/production frontend прошли. Далее OSPF preview/apply; модельные fallback и metadata legacy пока явно ограничены.
|
||||
|
||||
## 10.31. Строгий preview OSPF
|
||||
|
||||
Контекст serverId/веса, полный список изменений/counts/ids; metadata strict catalog, повтор/last preview/late context. 12 профильных + ранее 16 существующих (24 разных), TS/lint прошли. Apply receipt и происхождение backend модельных значений ещё требуют проверки; далее 10.32.
|
||||
|
||||
## 10.32. Подтверждённое OSPF применение и RBAC
|
||||
|
||||
Strict receipt/server/weight, ref lock, readonly/disabled контекст и reread любого результата. 16 E2E, readonly повтор, TS/lint, обе production сборки и auth tests прошли. Specific OSPF rights согласованы: preview read, apply write; signed JWT со stub handlers без RouterOS/DB. Далее backend provenance: legacy cost/metric defaults ещё не приняты как observed данные.
|
||||
|
||||
## 10.33. Backend cost и валидация плана
|
||||
|
||||
Observed selector вместо default cost/disabled; неоднозначные шаблоны отклоняются до write. Полный план валидируется, disabled сервер 409. DI HTTP/unit без RouterOS/DB, live-maps regression/backend build прошли; lint два прежних unused warning. Ранжирование прежнее, model fallback/clamp ещё требуют отдельного отображения. Далее layout/контекст.
|
||||
|
||||
## 10.34. Адаптивность оптимизатора
|
||||
|
||||
1440/390/320 px, keyboard/ARIA и disabled ECMP; native fieldset композиция исправлена после визуального обнаружения невидимых KPI. Семантические токены четырёх таблиц, девять снимков в плане; 35 E2E, TS/lint и production frontend прошли. Teardown catalog отказ backend записан в журнале. URL/source и model provenance ещё открыты.
|
||||
|
||||
## 10.35. Отсутствующие индексы Community
|
||||
|
||||
Без полной цепочки индексы неизвестны, рекомендации нет даже при пороге 0. 7 E2E, 3 unit, TS/lint прошли; расчёт существующих цепочек прежний. Далее URL/source-контекст.
|
||||
|
||||
## 10.36. URL устройства оптимизатора
|
||||
|
||||
server сохраняет выбор/reload/history без потери других параметров. Неизвестный/disabled/malformed explicit контекст не подменяется и не запускает preview/metadata; явный select восстанавливает работу. 22 E2E, 3 unit, TS/lint и production frontend прошли. Далее source/provenance; Home tabs URL пока вне блока.
|
||||
|
||||
## 10.37. Source isolation оптимизатора
|
||||
|
||||
8 E2E late preview/apply success/failure × backend/mode через настройки, новый снимок и отсутствие старых receipt/error/reread. TS/lint прошли. Production frontend из 10.36; реальные операции вне локальной приёмки. Далее model provenance и карта/терминал.
|
||||
|
||||
## 10.38. Смысл метрик preview
|
||||
|
||||
Короткое пояснение расчётных Ping/скорости, без изменения ranking/write. Lint и 14 preview E2E прошли. Далее provenance полей с сохранением observed 0/null; снимки 10.34 ещё без нового текста. Оптимизатор/этап 10 целиком не приняты.
|
||||
|
||||
## 10.39. Observed метрики WAN–JH/JH–Exit
|
||||
|
||||
Исходные значения/дата пробы отдельно от неизменной модели. Матрица не подменяет unknown моделью, полные цепочки явно расчётные. 2 unit, 9 E2E, TS/lint и ReUI audit прошли. Далее backend OSPF provenance; screenshots ещё требуют обновления.
|
||||
|
||||
## 10.40. OSPF provenance API
|
||||
|
||||
Shared контракт и backend observed исходные значения/даты, UI модель отдельно от снимка. Legacy без observed даёт неизвестность; rank/write прежние. Backend optimizer/live-maps, 30 E2E, TS/lint и обе production сборки прошли. Далее Router ID ambiguity, затем visual acceptance.
|
||||
|
||||
## 10.41. Однозначность Router ID
|
||||
|
||||
Полный опрос enabled inventory без first-match; duplicate ownership/unknown/failed каталог отклоняет план до write. Known disabled/empty и одинаковый ID одного устройства допустимы. Optimizer suite/backend build прошли, lint два прежних warning. Реальный RouterOS каталог ещё внешняя приёмка; далее screenshots.
|
||||
|
||||
## 10.42. Live WAN без подстановки
|
||||
|
||||
Нет mock catalog/synthetic WAN в live topology; отсутствие uplinks объяснено с переходом к серверу. 6 unit, 16 E2E, TS/lint прошли. Далее подписи и Community scope перед визуальной приёмкой.
|
||||
|
||||
## 10.43. Настройки/Community scope
|
||||
|
||||
Порог в баллах, обновление расчёта, инертный гистерезис недоступен; рекомендации только своего home. 4 unit, 10 E2E, TS/lint прошли. Девять снимков обновлены; header clipping ещё исправить перед acceptance.
|
||||
|
||||
## 10.44. Локальная приёмка оптимизатора
|
||||
|
||||
47 разных основных + 8 source E2E, backend optimizer/live-maps, production frontend/backend прошли; девять финальных снимков, ReUI audit/TS/lint. Исходные метрики отдельно от модели, full receipts/URL/source, без mock WAN/foreign Community. Внешние RouterOS/DB/JWT ограничения в журнале. Далее карта сети и терминал, этап 10 ещё открыт.
|
||||
|
||||
## Блок 10.45 — согласованный снимок карты сети (2026-10-01)
|
||||
|
||||
- Servers/GRE/probes публикуются вместе после строгой проверки схем, уникальности и владельцев. Частичный каталог GRE и неизвестные ссылки отклоняются; первоначальный отказ не становится пустым успешным ответом. При фоновом сбое сохраняется последний полный снимок с явным предупреждением.
|
||||
- Время ответа браузера отделено от измерений. Новый источник пересоздаёт контекст; epoch/alive запрещают позднему ответу и DNS изменять новую карту.
|
||||
- 2 unit, 9 HTTP E2E и TypeScript прошли. ESLint карты содержит 5 исходных ошибок и 1 warning; сравнение с HEAD подтвердило отсутствие новых. Их исправление включено в дальнейшую приёмку карты. Next dev имеет собственный пустой alert, поэтому тест восстановления проверяет именно сообщение карты.
|
||||
- Далее неизвестный статус, ресурсы и GRE без синтетических live значений; Flow/DNS, URL/доступность и приёмка карты ещё не завершены.
|
||||
|
||||
|
||||
## Блок 10.46 — неизвестный статус карты (2026-10-01)
|
||||
|
||||
- Nullable API status преобразуется в unknown: нейтральный узел/бейдж, отдельные фильтр и счётчик. Неизвестность не увеличивает offline. Общий ServerStatus расширен; потребители users/optimizer передают неизвестность как null, dashboard SVG имеет нейтральный стиль.
|
||||
- 104 E2E карты/дашборда/серверов/мониторинга и TypeScript прошли. Новых lint ошибок нет: карта — прежние 5 ошибок/1 warning, users — прежний set-state-in-effect, dashboard helper — прежние 2 unused warning. В серверном URL тесте был внутренний Next dev warning; сценарий завершился успешно.
|
||||
- Далее убрать синтетические live CPU/RAM/HDD/uptime/history и GRE, затем проверить Flow/DNS и доступность карты.
|
||||
|
||||
|
||||
## Блок 10.47 — измерения карты без синтетических live значений (2026-10-01)
|
||||
|
||||
- CPU/RAM/uptime читаются независимо из API, сохраняют нули и неизвестность; HDD, температура и история CPU не генерируются для live. Указано фактическое polledAt либо неизвестное время. Демо-ресурсы доступны только с явным demo=true.
|
||||
- GRE fallback по id отключён по умолчанию, карта явно включает его только в mock. Общий helper также убрал выдуманный fallback из live internet path. Probe DL/UL не округляются до целых, неизвестный Ping имеет нейтральный цвет. Catalog latency сохраняет дробь; модель WAN→JH ещё требует отдельного пояснения.
|
||||
- 4 unit, 19 E2E карты/дашборда и TypeScript прошли. Lint сравнен с HEAD: новых проблем нет; прежние prefer-const в layout и React правила карты будут устранены при её приёмке.
|
||||
- Далее Flow Map/DNS: строгие envelopes, частичный отказ/свежесть/гонки; модельные линии, URL-контекст, доступность и адаптивность ещё впереди.
|
||||
|
||||
|
||||
## Блок 10.48 — достоверность NetFlow и DNS карты (2026-10-01)
|
||||
|
||||
- NetFlow принимает полный DTO backend за 5 минут: поля/flags/счётчики не заменяются default нулями. При отказе сохраняется предыдущий снимок, первоначальная неизвестность и время ответа браузера обозначены отдельно; статус приёмника не выдаётся за свежесть измерения. Обновить повторяет оба независимых чтения.
|
||||
- Опрос не перекрывает и не отменяет медленный запрос каждые 4 секунды. Cleanup/epoch запрещают старый ответ; скрытие обеих flow групп приостанавливает обновление без потери последнего снимка.
|
||||
- DNS envelope проверяет точный набор имён и IPv4/null. Новая topology не использует прежний DNS; отказ/неразрешённые имена явно предупреждают о неподтверждённых связях. Неполные API данные выводят краткую понятную ошибку вместо технического JSON Zod.
|
||||
- 6 unit, 20 разных E2E (19 общих + новый slow, 8 Flow повторены после финального изменения) и TypeScript прошли. Новых lint проблем нет. Первые Flow фикстуры не перехватывали health и получили ECONNREFUSED; фикстуры исправлены, повтор чистый.
|
||||
- Далее отдельные source/race E2E, достоверность модельных WAN линий/выбранных объектов, затем URL и доступность/адаптивность карты.
|
||||
|
||||
|
||||
## Блок 10.49 — поздние ответы при смене источника карты (2026-10-01)
|
||||
|
||||
- Добавлена отдельная source-конфигурация Playwright (:3101, исходный backend :8000 и новый :8101). 12 сценариев snapshot/Flow/DNS × backend/mock × успех/отказ подтверждают, что прежняя карта, сервис и ошибка не попадают в новый источник, а старый ответ не запускает дополнительные чтения.
|
||||
- Все 12 E2E и lint новых тестов/config прошли. Default suite исключает source-файл; Next серверы запускаются последовательно.
|
||||
- Далее выбранные детали из текущего снимка, подписи модельных WAN связей и прежние lint ошибки карты; затем URL, клавиатура, телефон и визуальная приёмка.
|
||||
|
||||
|
||||
## Блок 10.50 — актуальные детали и модель связности карты (2026-10-01)
|
||||
|
||||
- Открытые детали server/GRE заново разрешаются по стабильной идентичности в текущем снимке: свежие name/status/resources не остаются на сохранённом объекте. Unknown latency/sessions/IPsec выводятся как неизвестность, не offline/0/Plain. Primary/backup GRE — только приоритет визуализации; WAN API — аплинк каталога.
|
||||
- Пунктир WAN→JH прямо обозначен моделью связности. Live модель не анимируется как активный маршрут и не показывает сумму latency как RTT линии; Ping модели подписан отдельно в деталях. Probe значения сохраняют нули/частичные DL/UL; подпись показывает probe ID, дату Ping и неизвестное время скорости.
|
||||
- Узлы всех ролей получили имя устройства и keyboard Enter/Space. Пульсация размера нарушала стабильность области кнопки; удалена, имя видно и для JH/Exit. Прежние React set-state/refs/immutability/exhaustive-deps и prefer-const устранены без подавления lint.
|
||||
- 24 E2E карты, TypeScript и lint карты/helpers/tests прошли. Новая проверка подтверждает 0 Ping, дробную DL при неизвестной UL и старую дату пробы. Реальная сеть остаётся внешней приёмкой.
|
||||
- Далее URL-контекст, клавиатурные действия остальных объектов и адаптивность/Frame/screenshots карты.
|
||||
|
||||
|
||||
## Блок 10.51 — URL-контекст карты (2026-10-01)
|
||||
|
||||
- URL сохраняет server/WAN, status filter, q и режим services/countries. Перезагрузка и история восстанавливают детали/срез; поиск заменяет текущий history entry. Посторонние query/hash сохраняются. Выбор GRE/сервиса пока локальный, pan/zoom/drag также локальные.
|
||||
- Строго проверяются дубли, длины и enum. Неверный URL показывает ошибку до чтения inventory, сброс очищает только поля карты. Отсутствующий server или WAN явно недоступен; первый другой объект не выбирается. Nullable server status совместим с unknown filter.
|
||||
- 2 URL unit, 11 E2E URL/details (7 URL повторены после исправления тестового encoded-space matcher), TypeScript и lint прошли. В production ещё требуется общий build после адаптивной композиции.
|
||||
- Далее ReUI Frame, панели и интерактивные SVG controls: keyboard/focus, телефон, reduced motion, скриншоты и локальная приёмка карты.
|
||||
|
||||
|
||||
|
||||
## Блок 10.52 — Frame, доступные действия и детали карты (2026-10-01)
|
||||
|
||||
- Установленный ReUI Frame объединяет toolbar, SVG и детали с parent-owned высотой. На ПК детали справа; на телефоне занимают рабочую область, закрытие возвращает карту. Выбор устройства доступен вне SVG, длинные имена переносятся по словам, отсутствует горизонтальный overflow на 1440/390/320 px.
|
||||
- Действия устройства используют стандартный Base UI Dialog с действительными ссылками и обработкой отказа clipboard. Слои — Popover; Escape возвращает фокус и сохраняет server URL. Узлы устройств/WAN/сервисов и метрики GRE/Flow доступны Enter/Space; кнопки названы, декоративные иконки скрыты от screen reader.
|
||||
- SVG использует semantic tokens; reduced motion отключает animateMotion. Экспорт сохраняет CSS переменные/фон и сериализуется XMLSerializer как standalone SVG. Nullable UL не выводится строкой null; неизвестный IPsec явно подписан.
|
||||
- 35 основных + 12 source E2E, TypeScript и lint прошли; ReUI Frame checklist прочитан. Первые регрессионные тесты выбирали скрытые option после добавления селектора: селекторы ограничены SVG, повтор чистый. 6 снимков проверены визуально.
|
||||
- Далее 10.53: камера по границам объектов и читаемость малой топологии, pointer/touch и пустые состояния; текущие overview снимки ещё показывают слишком мелкий граф. Production build — после этого блока. Реальные RouterOS/JWT/БД не проверены.
|
||||
|
||||
|
||||
## Блок 10.53 — камера и читаемость карты (2026-10-01)
|
||||
|
||||
- ViewBox учитывает реальное соотношение сторон canvas; начальное вписывание включает устройства, WAN, сервисы и подписи. Оно выполняется один раз на источник и не сбрасывает ручной zoom после обновления API. Кнопка/горячая клавиша вписывают текущие объекты; wheel/drag используют ту же геометрию.
|
||||
- Название вынесено под узел; на телефоне размер текста компенсирует SVG масштаб, длинная подпись сокращена при сохранённом полном accessible name/деталях. Страна обозначена ISO при отсутствии площадки и до загрузки внешнего изображения флага. Легенда — доступные раскрываемые обозначения вне SVG.
|
||||
- WAN карточка получила Enter/Space и aria-pressed. 2 camera unit + 16 E2E layout/details/URL, TypeScript и lint прошли; после ISO fallback повторены 5 layout E2E, TypeScript и lint. Снимки обновлены.
|
||||
- Далее pointer/touch, закрытие деталей с возвратом фокуса, пустой inventory/пустой срез; затем production build и локальная приёмка карты. Реальная сеть не проверена.
|
||||
|
||||
|
||||
## Блок 10.54 — Pointer/touch и локальная приёмка карты (2026-10-01)
|
||||
|
||||
- Pointer Events/capture удерживают drag за пределами canvas; основной указатель отделён от остальных, cancel/lost capture завершают жест без залипания. Touch-action отключает прокрутку только на SVG; детали продолжают прокручиваться. Фокусируемый canvas поддерживает стрелки, zoom/fit имеют клавиатурные альтернативы.
|
||||
- Закрытие деталей кнопкой/Escape возвращает фокус к выбору устройства. Пустой inventory явно предлагает серверы; поиск без результатов даёт сброс только среза. Без подтверждённого снимка экспорт недоступен; загрузка объявляется role=status.
|
||||
- Карта принята локально: 39 основных + 12 source E2E, 10 unit, TypeScript, lint и production frontend build прошли. ReUI Frame checklist повторён, адаптивные снимки обновлены. Touch проверен через реальный Chromium input protocol; физических телефонов в приёмке нет.
|
||||
- Границы: HTTP фикстуры не подтверждают RouterOS/JWT/БД; WAN пунктир остаётся моделью, Flow свежесть — время браузерного ответа; SVG флаги зависят от существующего CDN. Фильтр сохраняет приглушённые узлы как контекст, pan/zoom/drag локальные. SVG XML валиден, сторонние SVG viewers отдельно не проверены.
|
||||
- Далее 10.55: терминал — API-контракт, выбранное устройство/host из URL, достоверность выполнения и ошибки/повтор/права. Этап 10 ещё не завершён.
|
||||
|
||||
|
||||
## Блок 10.55 — достоверный REST терминал и URL (2026-10-01)
|
||||
|
||||
- Frame/ServerRailLayout сохранены; нет фиктивного Connected/admin prompt/LIVE/SSH или обещания Tab completion. Устройство выбирается явно, server/host восстанавливаются из URL; неизвестный/неоднозначный host не выбирает другое устройство. History/reload/query/hash сохраняются. Неверный URL останавливает чтение каталога.
|
||||
- Каталог и output проверяются строго; первоначальная ошибка отличается от пустого списка. Фоновый отказ сохраняет каталог/черновик и приостанавливает новые команды до успешного обновления. Ключ источника/device/host и abort cleanup запрещают прежний вывод; запрос защищён немедленным lock.
|
||||
- При API/legacy error или таймауте команда остаётся в поле; успех показан только после валидного output, пустой вывод подписан. Поле/кнопка остаются видимыми во время ожидания, после завершения фокус возвращается. Быстрые команды только подставляют; clear — локальная очистка без API, история до 100 команд/вывод до 1000 строк.
|
||||
- Frontend права соответствуют текущему backend: каталог mm:servers:read, POST exec mm:servers:write. Терминал в permissionForPath связан с servers:read. Правила RouterOS команд не расширены.
|
||||
- 12 E2E, 3 unit, TypeScript и lint прошли; clear добавлен затем проверен повтором quick/history E2E и lint. ReUI checklist прочитан. Production/screenshots — после backend/source/адаптивной приёмки терминала.
|
||||
- Далее 10.56: backend exec не должен маскировать BFD/API отказ пустым успехом; DI route тесты. Реальная сеть/JWT/БД не проверены.
|
||||
|
||||
|
||||
## Блок 10.56 — честный backend exec (2026-10-01)
|
||||
|
||||
- BFD/API отказ не подменяется пустым успехом: upstream ошибка возвращает 502/error, неподдерживаемая команда или неверные аргументы — 400/error; успешный output сохраняет прежнюю форму. Frontend 10.55 понимает новые ошибки и legacy error: output.
|
||||
- Прежний диагностический allowlist сохранён. Ping/log парсятся целиком, нулевые/частичные/повторные аргументы отклонены до обращения RouterOS; прежние caps count=20, limit=200 сохранены. Сетевые write команды не добавлены; RBAC не изменён.
|
||||
- Отсутствующие BGP/BFD status, OSPF cost/type/BFD/version/area/changes и firewall counter не выдаются за active/down/10/broadcast/no/2/0. Ping timeout виден без TTL, неизвестная packet loss — ?, нулевые измерения сохранены. Resource memory отказывается от NaN/overflow.
|
||||
- createExecRoutes допускает DI для тестов; production defaults — прежние DB/MikrotikClient. test:exec включён в backend test. Route/RBAC DI тесты, backend test:auth, build и lint прошли. Подписанные JWT проверяют текущий middleware до device lookup; это не приёмка реального портала/RouterOS/БД.
|
||||
- Далее source/cancel/timeout/пустой/disabled/invalid URL E2E терминала, адаптивные снимки и production frontend; затем локальное завершение этапа 10.
|
||||
|
||||
## Блок 10.57 — локальная приёмка терминала (2026-10-01)
|
||||
|
||||
- Терминал принят локально: 20 основных E2E (17 данных и 3 адаптивных), 8 source E2E, TypeScript, lint и production frontend build прошли. Проверены timeout/поздний ответ, пустой/disabled каталог, неверный URL, сохранение команды, смена режима/backend и 1200 строк вывода.
|
||||
- Снимки ready/output для ПК, 390 и 320 px сохранены. Общая мобильная кнопка ServerRail теперь ограничена шириной и сокращает длинное имя; гидратация учитывает cleanup. 12 регрессионных сценариев GRE/VXLAN/IPsec/OSPF/recursive прошли; восемь обновлённых снимков просмотрены и сохранены. ReUI Frame checklist повторён.
|
||||
- Границы: HTTP fixtures/DI доказывают обработку UI/API, не реальный RouterOS/БД/портал. REST терминал не является SSH-сессией; clear локальный, отмена/timeout не подтверждают остановку на устройстве.
|
||||
- Этап 10 остаётся в работе: обнаружен отдельный /probes (Диагностика GRE), который ещё требует приёмки. Далее 10.58: строгий результат, single-flight и отмена запросов диагностики; каталоги/URL/права и backend — отдельными блоками. Расписание относится к 11Б.
|
||||
|
||||
|
||||
## Блок 10.58 — достоверный результат диагностики GRE (2026-10-01)
|
||||
|
||||
- /probes проверяет строковый output и legacy error; неверный контракт не превращается в пустой успех. Пустой подтверждённый вывод подписан, цель/параметры сохраняются после отказа.
|
||||
- Немедленный single-flight lock закрывает повторный Enter; disabled устройство и неподтверждённый каталог не запускают запрос. Стоп/Остановить все отменяют ожидание со статусом cancelled, без заявления об остановке RouterOS. Таймаут 60 с показывает неизвестность результата и требует ручного повтора.
|
||||
- Cleanup отменяет запрос; ключ режима/backend исключает перенос прежней истории/вывода. Удаление выполняющегося теста отменяет ожидание. Существующие Frame/состав инструментов/сетевые правила сохранены.
|
||||
- 7 основных и 4 source E2E, 2 unit, TypeScript и production frontend прошли. Новые helper/test файлы проходят lint. Страница сохраняет исходные 8 set-state-in-effect ошибок и 2 предупреждения: сравнение ESLint HEAD/current подтвердило одинаковые counts; это не чистый lint страницы.
|
||||
- Далее 10.59: каталог серверов/ошибка/повтор и неизвестный status; затем URL-контекст, права, GRE каталог, backend probes и адаптивная приёмка. Расписание отдельно в 11Б. Реальный RouterOS не проверен.
|
||||
|
||||
|
||||
## Блок 10.59 — каталог устройств диагностики (2026-10-01)
|
||||
|
||||
- Каталог проверяется по типам id/host/status/enabled/type, уникальности id и конечной неотрицательной latency. Неизвестный status отображается как unknown, не offline. Abort/cleanup запрещают прежний результат после ухода/смены источника.
|
||||
- Отказ сохраняет последний список и черновик; ошибка API показана отдельно от пустого каталога. Обновить допускает ручной повтор. Во время обновления/ошибки запуск приостановлен; время получения последнего каталога видимо. Фоновая загрузка не удаляет форму.
|
||||
- 12 основных + 4 source E2E, 3 unit, TypeScript и production frontend прошли. Первый прогон новых тестов остановился на пересечении role=alert с Next route announcer; alert каталога именован, повтор 12/12 чистый. Helper/tests проходят lint; исходные ошибки страницы остаются (catalog эффект исправлен, остальные эффекты/расписание ещё не приняты).
|
||||
- Далее 10.60: права страницы/запуска должны соответствовать фактическим /api/servers read/write. Затем GRE каталог, URL/device context, backend и адаптивная приёмка. Внутреннее sessions=0 не отображается в диагностике и не является измерением; заменить при общей типизации. Реальная сеть не проверена.
|
||||
|
||||
|
||||
## Блок 10.60 — права диагностики (2026-10-01)
|
||||
|
||||
- permissionForPath(/probes) соответствует каталогу servers:read, вместо прежнего fallback dashboard:read. Запуск и Enter требуют servers:write, как текущий POST /servers/:id/probes/run; серверный RBAC не расширен. Нет servers:read — каталог не запрашивается.
|
||||
- GRE каталог требует filters:read; без него не выполняется GET, BW запуск недоступен с понятной причиной. Остальная разрешённая диагностика остаётся доступной. Права расписания будут приняты отдельно в 11Б.
|
||||
- 14 E2E, TypeScript, production frontend, профильный lint и backend test:exec/test:auth прошли. Auth exec тест теперь проверяет также probes HTTP путь подписанными JWT на настоящем requireAuth/permissionForRequest со stub handler: read/network write запрещены, servers write/admin допущены. Это не проверка production probes handler/RouterOS/портала.
|
||||
- Далее 10.61: GRE каталог — ошибка не равна пустому списку, строгий контракт/cleanup/повтор. Затем URL, backend probes и адаптивная приёмка. Исходные 7 эффектных lint ошибок страницы ещё открыты.
|
||||
|
||||
|
||||
## Блок 10.61 — достоверный GRE-каталог диагностики (2026-10-01)
|
||||
|
||||
- Переиспользован filtersGreResponseSchema; подтверждается форма ответа, уникальность и принадлежность serverId. Только enabled текущий сервер вызывает GET. Abort/cleanup запрещают поздние GRE после смены устройства/источника.
|
||||
- Ошибка сохраняет прошлый список, отдельно подписана и даёт Повторить GRE. Loading/error не выдаются за пустой каталог. BW требует ready, включённый выбранный туннель и непустой remoteAddress; отказ объяснён. Ping и другие инструменты не блокируются независимым GRE отказом.
|
||||
- 18 основных E2E + 2 поздних GRE + 2 disabled/no-address BW, 4 source E2E, 3 unit, TypeScript и production frontend прошли. Профильный test lint чистый. В странице остаются 6 прежних эффектных lint ошибок и 2 предупреждения; GRE эффект устранён без suppressions.
|
||||
- Далее 10.62: проверить точность подписи/preview DNS (сейчас имитирует /resolve server=1.1.1.1, backend использует DNS приложения); затем URL выбор без fallback, ros-src-address контракт, backend probes ошибки/аргументы/метрики, адаптивные снимки и локальная приёмка. /probes пока не принят, этап 10 не завершён.
|
||||
- Остаток окна при сохранении около 4%; RouterOS/БД/внешний DNS не проверены. История локальная, отмена HTTP не подтверждает остановку устройства. Расписание/формы сбора остаются 11Б.
|
||||
|
||||
|
||||
## Блок 10.62 — честный DNS preview и inline ошибка (2026-10-01)
|
||||
|
||||
- DNS в /probes подписан как DNS приложения; preview описывает параметры резолвера хоста backend. Не обещает /resolve MikroTik или server=1.1.1.1, которых текущий dnsLookupText не использует. Демонстрационный источник отмечен отдельно.
|
||||
- readProbeOutput отклоняет DNS ;; ERROR: внутри многострочного output, а не только error: в начале; inline отказ не превращается в done/live. Цель и тип остаются для ручного повтора. Backend DNS реализация/сетевые правила не изменены.
|
||||
- 4 unit, 5 профильных E2E (DNS/error/retry, malformed/legacy/timeout и GRE malformed), lint helper/tests, TypeScript в production frontend build прошли. Первый DNS тест использовал description как accessible name; исправлен на реальное имя DNS, повтор 5/5 чистый. Production build повторён отдельно после завершения E2E.
|
||||
- Остановка при 98% использования пятичасового окна; все блоки сохранены локальными коммитами без push. Следующий шаг 10.63: восстановление /probes server из URL без первого-device fallback, сохранение query/hash/back/reload, контракт/cleanup ros-src-address. Затем backend probes DI (невалидные id/аргументы, HTTP ошибки вместо legacy output, DNS/MTU/неизвестные метрики), доступность/адаптивные снимки и приёмка.
|
||||
- Этап 10 ещё в работе; /probes не принят. Остались 6 прежних set-state-in-effect ошибок и 2 предупреждения страницы, включая расписание (11Б). История локальная; HTTP моки не подтверждают реальные RouterOS/БД/DNS/портал.
|
||||
|
||||
|
||||
## Блок 10.63 — устройство диагностики из URL (2026-10-01)
|
||||
|
||||
- /probes читает server через useSearchParams/Suspense. Выбор явно сохраняется pushState; остальные query/hash, back и reload сохранены. Нет автоматического выбора первого устройства в live/демо; ServerRail preserveSelection удерживает исходный контекст.
|
||||
- Повторный/пустой/некорректный server останавливает API до монтирования содержимого. Отсутствующее устройство показывает отдельную ошибку/сброс выбора, выключенное — причину недоступности. Без выбора запуск и зависимые запросы не выполняются. GET ros-src-address также ограничен подтверждённым enabled устройством.
|
||||
- 29 основных + 4 source E2E, 2 URL unit, профильный lint, TypeScript и production frontend прошли. Старые тесты выбирают server=1 явно; при переходе в demo выбирают реальное demo устройство вместо прежнего fallback.
|
||||
- Далее 10.64: строгий ros-src-address контракт и привязка preview к id/host с отменой/повтором; затем backend probes DI/аргументы/ошибки/метрики, доступность/адаптивная приёмка. Этап 10 остаётся в работе. Моки не доказывают реальные RouterOS/DNS/БД.
|
||||
|
||||
|
||||
## Блок 10.64 — IPv4 источника preview (2026-10-01)
|
||||
|
||||
- ros-src-address проверяет host текущего устройства и канонический IPv4/null. Preview привязан к id+host; поздний ответ/ошибка отменяются при смене устройства/источника. Запрос идёт только для enabled устройства и инструментов ping/traceroute/mtu; DNS приложения не запрашивает этот источник.
|
||||
- Error/loading/null отличаются; ошибка имеет ручной повтор. В UI явно указано: preview справочный, backend повторно определяет src-address при запуске. Ошибка preview не меняет сетевые правила и не запрещает разрешённую диагностику; неизвестный FQDN адрес показан ?, а не прежним IP.
|
||||
- 36 основных E2E (29 данных + 7 IPv4), 4 source E2E, unit decoder, профильный lint, TypeScript и production frontend прошли. Реальный DNS/RouterOS не проверен.
|
||||
- Далее 10.65: DI backend probes, честные HTTP ошибки вместо legacy error output, сохранение allowlist/методов; затем строгие аргументы и MTU/неизвестные измерения. Доступность, адаптивная приёмка /probes и прежние lint эффекты ещё открыты. Расписание остаётся 11Б.
|
||||
|
||||
|
||||
## Блок 10.65 — честный HTTP контракт backend диагностики (2026-10-01)
|
||||
|
||||
- createProbeRoutes допускает DI поиска устройства/клиента/источника/DNS/BW peer; production defaults сохранены. Строгий положительный целый serverId запрещает parseInt префиксы; body должен быть объектом. Allowlist ping/traceroute/bandwidth/dns/route/mtu не расширен.
|
||||
- Upstream/client/resolve отказ возвращает 502/error, DNS inline ;; ERROR также не считается успешным output. Неизвестный сервер — 404, неподдерживаемый инструмент/отсутствующая цель — 400. DB ошибки сохраняют стандартный 500. Frontend уже поддерживает error ответы и legacy output.
|
||||
- IPv4 определяется только для ping/traceroute/mtu; DNS приложения/route/BW не требуют этого независимого DNS запроса. Параметры/лимит traceroute и прежние инструменты сохранены.
|
||||
- Backend test:probes включён в общий test; DI HTTP тесты, test:exec/test:auth, backend build и lint прошли. JWT тест probes теперь регистрирует настоящий createProbeRoutes с подменой getServer: read/network write запрещены до lookup, servers write/admin допускаются до 404. Это не реальный портал/RouterOS/БД/DNS.
|
||||
- Далее 10.66: строгие typed аргументы с сохранением существующих caps/defaults, отказ disabled устройства, MTU не должен считать пустой ответ/неизвестность успешной пробой; затем метрики, адаптивность и приёмка /probes. Этап 10 ещё не завершён.
|
||||
|
||||
|
||||
## Блок 10.66 — аргументы и достоверность MTU (2026-10-01)
|
||||
|
||||
- Zod проверяет typed tool/target/числа/boolean/enum/timeout до lookup; число не берётся из строки, false не превращается в true. Неполная цель/невалидный timeout/небезопасные значения дают 400. Существующие defaults и caps ping 100/8192/255, trace 64 hops/3 probes/10–3000 ms/budget 58 s и BW 3–120 s сохранены для валидных аргументов.
|
||||
- Disabled сервер/получатель BW дают 409 до сетевого действия. MTU требует подтверждённый received=1 либо корректный ответ seq/time; пустой/неизвестный/ошибочный ответ даёт 502 и прекращает новые пробы. Timeout не называется fragment needed; полный набор timeout остаётся неизвестным MTU, не 0/1500.
|
||||
- Таймер traceroute теперь снимается в finally после завершения; общий срок и отмена сохранены, тестовый процесс больше не ждёт лишние 58 секунд.
|
||||
- Backend test:probes/test:exec, build и lint прошли; HTTP DI покрывает bad types, disabled, unknown MTU, успешный seq=0, все timeout, caps/trace boolean/time. 2 frontend E2E подтвердили 403/502 и сохранение цели/повтор. JWT тест отправляет валидный probes payload; реальные RouterOS/БД/сеть не проверены.
|
||||
- Далее 10.67: достоверные ping/BW/route показатели и строгий IPv4/CIDR; затем отмена backend запроса, клавиатура/адаптивность, прежние эффекты и локальная приёмка /probes. Этап 10 ещё в работе.
|
||||
|
||||
|
||||
## Блок 10.67 — неизвестные измерения и маршрутный срез (2026-10-01)
|
||||
|
||||
- Ping сохраняет seq=0/TTL=0/sent=0/received=0, отсутствующие/невалидные счётчики помечает ?, пустой ответ подписан без измерений. Нет ложного avg-rtt из поля time суммарной строки. BW/trace пустые показатели показывают —, известный ноль сохранён.
|
||||
- Route требует IPv4 target до lookup. IPv4/CIDR парсятся целиком, без parseInt префиксов/лишних сегментов. Неизвестные active/prefix записи не превращаются в no route: неполнота явно показана, при наличии подтверждённого маршрута он подписан best confirmed match. Distance unknown не становится 255/0; routing-mark missing не называется main.
|
||||
- Existing main/active filtering, longest-prefix/distance ordering и сетевые методы сохранены; malformed/unknown записи не используются как подтверждённые маршруты.
|
||||
- Backend test:probes/build/lint прошли; DI HTTP проверяет нули/unknown ping/BW, плохой target/CIDR, mixed known/unknown маршруты и приоритеты. Моки не проверяют реальную FIB/RouterOS/IP.
|
||||
- Далее 10.68: корректная привязка отмены к жизненному циклу HTTP ответа и прекращение последующих MTU проб; затем клавиатура/адаптивность и локальная приёмка /probes. Этап 10 ещё в работе.
|
||||
|
||||
|
||||
## Блок 10.68 — отмена backend диагностики (2026-10-01)
|
||||
|
||||
- Abort привязан к aborted HTTP запросу/незавершённому response close; нормальное завершение чтения тела не считается отменой. Listeners снимаются в finally. Перед/после зависимых await проверяется сигнал; отмена не начинает новые MTU пробы.
|
||||
- Ping/traceroute/MTU получают AbortSignal в post; bandwidthTest принимает необязательный сигнал и передаёт его в существующий post. Старые вызовы совместимы, таймауты/allowlist/параметры сохранены. DNS и route GET не обещают физическую отмену текущего upstream запроса, после закрытия ответа результат не подтверждается.
|
||||
- Локальные TCP HTTP тесты доказали: обычный trace body не отменяет запрос; закрытие browser fetch доходит до mock RouterOS клиента для ping/trace/MTU/BW; MTU выполняет только одну пробу. Настоящий MikrotikClient BW POST закрывается при abort на локальном fake HTTP RouterOS. Это не подтверждение остановки реального RouterOS процесса.
|
||||
- Полный backend npm test завершился exit 0; DB-зависимые тесты явно skipped из-за ECONNREFUSED PostgreSQL 127.0.0.1:5432, не приняты по этому прогону. test:probes/build/profile lint повторены после транспортного теста. Mikrotik service сохраняет две исходные prefer-const ошибки 117/874; ESLint HEAD/current совпал, suppressions не добавлены.
|
||||
- Далее 10.69: доступность и адаптивность диагностики, семантические токены, подписи/вывод/clipboard и снимки; затем профильная регрессия и локальная приёмка /probes. Расписание в 11Б, реальные RouterOS/БД/портал остаются внешними ограничениями.
|
||||
|
||||
|
||||
|
||||
## Блок 10.69 — доступность и адаптивность диагностики (2026-10-01)
|
||||
|
||||
- Сохранена композиция Frame/FramePanel, OpsPanel и ServerRail; API Frame и ReUI checklist сверены. Vendor/theme не изменены. Цвета диагностики используют семантические токены, анимация учитывает reduced motion, кнопки/переключатели и область вывода имеют доступные имена и состояния.
|
||||
- Вывод ограничен последними 1000 строками с явной отметкой; переносится и прокручивается внутри панели с высотой родителя. Удаление возвращает фокус на запуск, clipboard отказ показывает ошибку и сохраняет данные. Демо явно подписано; вымышленные время и положительная окраска неизвестных счётчиков убраны.
|
||||
- На 1440/390/320 px нет горизонтального переполнения; команда на телефоне использует всю доступную ширину, адрес цели читается, DNS подписан как тест приложения. Сохранены и визуально проверены шесть снимков ready/output.
|
||||
- TypeScript, 37 data/source E2E, 4 layout/clipboard E2E и 4 context E2E прошли. Production frontend build прошёл. Lint изменённого теста чистый; в странице остаются четыре прежние set-state-in-effect ошибки (три в расписании, одна в выборе BW). Новых ошибок/предупреждений нет.
|
||||
- Далее 10.70: убрать эффект выбора BW в диагностике, дополнить проверку клавиатуры/успешного clipboard и локальную приёмку. Расписание и три его lint ошибки перенесены в 11Б; реальные RouterOS/БД/портал не приняты по мокам.
|
||||
|
||||
|
||||
## Блок 10.70 — контекст BW и клавиатурные действия (2026-10-01)
|
||||
|
||||
- Выбор GRE для BW вычисляется из текущего каталога без setState в effect. Первоначальный выбор сохраняет прежнее поведение; ручной выбор привязан к устройству. Если выбранный GRE исчез, запуск блокируется до нового явного выбора, другой туннель не подставляется.
|
||||
- Ожидание DNS теперь подписано как DNS-запрос приложения. Клавиатурой проверены DNS/CNAME, Enter из поля цели, копирование результата с подтверждением и удаление с возвратом фокуса.
|
||||
- TypeScript и lint тестов прошли. Профильный прогон: 42 сценария passed; один новый тест сначала упал из-за неполной GRE HTTP-фикстуры, после исправления контракта и aria селектора прошёл отдельным повтором. Производственный код не обходил проблему теста. Прежняя диагностическая lint ошибка устранена; три оставшиеся относятся к расписанию 11Б.
|
||||
- Далее 10.71: итоговая профильная регрессия этапа 10, production build, перечень внешних ограничений и локальная приёмка. Затем 11А: пользователи. Моки не доказывают реальную сеть/БД/портал.
|
||||
|
||||
|
||||
## Блок 10.71 — локальная приёмка этапа 10 (2026-10-01)
|
||||
|
||||
- Этап 10 завершён в границах локальной приёмки: BGP/OSPF/рекурсивные маршруты/оптимизатор/карта/терминал/диагностика. Схемы и снимки сохранены в плане; ReUI Frame/Data Grid v9 и base-nova сохранены, новые vendor компоненты не добавлены.
|
||||
- Совместный профильный прогон — 235 E2E passed; отдельные source конфигурации — 52 E2E passed (BGP 4, OSPF 8, recursive 8, optimizer 8, map 12, terminal 8, probes 4). 42 профильных unit passed. Probes backend HTTP/cancel/BW transport повторены, frontend/backend production build прошли. Снимки регрессии обновлены без изменений дизайна остальных принятых экранов.
|
||||
- Общий backend test ранее завершился exit 0 с явными skipped DB сценариями: PostgreSQL недоступен. Реальные RouterOS/JWT/БД, выполнение сетевых команд, применение маршрутов и остановка процессов остаются внешней приёмкой. Полный проектный accessibility/performance/lint аудит — этап 12.
|
||||
- Сохраняются известные исходные lint ограничения: три set-state-in-effect в расписании диагностики (11Б), две prefer-const в Mikrotik service; другие исходные предупреждения описаны в профильных блоках. Не объявляются чистым общепроектным lint.
|
||||
- Далее 11А.1: карта администрирования и API; затем 11А.2: достоверная загрузка пользователей и серверного каталога. 11А/11Б/12 ещё не завершены.
|
||||
@@ -0,0 +1,483 @@
|
||||
# Этап 11А: пользователи и администрирование устройств
|
||||
|
||||
Статус: завершён локально 2026-10-01 (11А.33); внешние ограничения приведены в приёмке. ReUI PRO/base-nova, существующие Frame, KpiStatGrid, Data Grid v9 и Sheet. Изменения последовательно, локальные коммиты без push.
|
||||
|
||||
## Референсы и схемы
|
||||
|
||||
| Область | Референс | Схема |
|
||||
| --- | --- | --- |
|
||||
| Обзор раздела | [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp) / [Stats 12](https://reui.io/preview/base/stats-12?ref=mcp) | Источник → подтверждённая сводка → проблемы → действие |
|
||||
| Таблицы | [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Фильтры → объект → детали → результат API |
|
||||
| Формы | [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp) | Контекст → форма → проверка → подтверждённый результат / сохранённый черновик |
|
||||
|
||||
[Источник и права]
|
||||
↓
|
||||
[Каталоги + свежесть] → [Ошибка: последние данные, явный повтор]
|
||||
↓
|
||||
[Объект / детали] → [Форма с черновиком]
|
||||
↓
|
||||
[Подтверждение API / частичное выполнение]
|
||||
↓
|
||||
[Повторное чтение / восстановление контекста]
|
||||
|
||||
## Карта реализации
|
||||
|
||||
| Порядок | Раздел / API | Исходная проблема | Точка завершения |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | Пользователи: /users, /servers | Live начинает с INIT_USERS; Promise.all связывает независимые отказы; нет свежести и защиты смены источника | Пустой/unknown/ошибка различаются, последний снимок и read-only права |
|
||||
| 2 | Профиль и привязки: /users/:id, /bindings | Многошаговое сохранение, нет lock удаления, refresh ошибка проглатывается; Sheet эффект может сбросить форму | Частичное выполнение явно показано, повтор без дублей, успешный API отдельно от refresh |
|
||||
| 3 | Interface catalog | Ошибка превращается в []; каталог может сохранять прежнее устройство; peer ошибки требуют проверки | Контекст и доступность, точный выбор, сохранение формы |
|
||||
| 4 | Пользователи UI | «Пригласить» фактически создаёт профиль; icon actions без имён, raw colors, доступность формы | ПК/390/320, клавиатура, понятные подписи/токены |
|
||||
| 5 | Контейнеры | Отказ очищает прошлые объекты, Promise.all и операции требуют защиты/валидации | Состояния снимка, реальные подтверждения действий, контекст/права |
|
||||
| 6 | Сертификаты | Сводка, доступность экспорта/операций и конкретный сервер требуют аудита | Неизвестные статусы, действительный экспорт и ошибки API |
|
||||
| 7 | Резервирование | Общий Promise.all четырёх источников, polling задач/интеграций и сохранение требуют аудита | Частичные сбои и состояние job без ложного завершения, форма сохранена |
|
||||
| 8 | Приёмка 11А | Сквозные действия и общие компоненты | Профильная регрессия, production build, снимки, внешние ограничения |
|
||||
|
||||
## Границы
|
||||
|
||||
- Права пользователя в профиле и Portal JWT авторизация приложения — разные существующие контракты; не менять правила выдачи доступа в UX исправлениях.
|
||||
- Сохранение профиля и привязок сейчас несколько HTTP запросов. Не обещать атомарность и не повторять подтверждённое создание после частичного отказа.
|
||||
- Серверный каталог — зависимость формы прав/привязок; отсутствие доступа или отказ не должен обнулять сохранённые разрешения.
|
||||
- Backend/моки не подтверждают реальный Portal, PostgreSQL, RouterOS, выдачу сертификатов, восстановление backup или доступность S3. Реальную приёмку перечислять отдельно.
|
||||
- Оповещения, сбор данных, интеграции, релизы, настройки и расписание диагностики — 11Б.
|
||||
|
||||
|
||||
## Блок 11А.2 — достоверная загрузка пользователей (2026-10-01)
|
||||
|
||||
- Live не содержит INIT_USERS/демо серверов до API. Пользователи и серверы читаются независимо: быстрый список появляется до медленного каталога; отказ одной зависимости сохраняет другую и последние подтверждённые данные. Unknown KPI — —, подтверждённый пустой список — отдельное состояние.
|
||||
- Получение пользователей имеет время браузерного чтения и ручной повтор. Смена backend/mode размонтирует прежний контекст, читатели отменяются и поздние ответы не меняют новый экран. Схемы обязательны; дубли ID отклоняются.
|
||||
- Права users read/write и server read проверены перед запросами/действиями. Без подтверждённых актуальных каталогов редактирование приостановлено; неизвестный общий серверный каталог не показывается числом 0. Icon действия получили имена; «Пригласить» заменено фактическим «Добавить пользователя».
|
||||
- 12 data E2E + 4 context E2E, профильный lint и TypeScript прошли. Production frontend прошёл в приёмочной сборке после подготовки нового контекста; дальнейшие операции ещё не приняты. Mock ветка подписана как локальное демо.
|
||||
- Далее 11А.3: lock удаления/сохранения, сохранение диалога/черновика при ошибке, поздние мутации и отдельное подтверждение API от refresh. Затем частичное сохранение привязок без дублей и interface catalog. Реальные Portal/БД ещё не проверены.
|
||||
|
||||
|
||||
## Блок 11А.3 — подтверждённое удаление пользователя (2026-10-01)
|
||||
|
||||
- DELETE имеет single-flight lock, AbortSignal/30s срок и защиту позднего ответа после размонтирования. Ожидание блокирует повтор/отмену диалога; ошибка остаётся в диалоге с возможностью повторить, target не теряется.
|
||||
- Удаление требует существующий backend контракт HTTP 204; успешный 200 с произвольным телом не принимается. Подтверждённая строка удаляется сразу, а отказ последующего refresh не называется отказом удаления: API результат и необходимость повторного чтения показаны отдельно.
|
||||
- 17 data/operations E2E + 6 context E2E, TypeScript и профильный lint прошли. Проверены 403/503/неверный ответ, двойной click, Escape, refresh error, поздний success/error прежнего backend. Созданы общие HTTP-фикстуры пользователей.
|
||||
- Далее 11А.4: безопасное сохранение профиля/черновика и частичных привязок, без повторного создания при подтверждённом первом шаге. Сохранение ещё не принято; interface catalog и визуальная приёмка далее. Реальный Portal/БД не проверен.
|
||||
|
||||
|
||||
## Блок 11А.4 — многошаговое сохранение профиля и привязок (2026-10-01)
|
||||
|
||||
- Общий mutation lock, отмена/30s срок каждого запроса, защита прежнего источника; Sheet не сбрасывает черновик при изменении каталога/подтверждённом промежуточном шаге. Во время отправки поля/кнопки и закрытие блокируются.
|
||||
- UserSaveCheckpoint сохраняет подтверждённый id профиля и каждую привязку. После частичного отказа повтор читает профиль/привязки, обновляет профиль по этому id и продолжает diff без второго POST пользователя/повторной подтверждённой привязки. Потерянный ответ DELETE/POST привязки сверяется чтением. Это несколько HTTP запросов, не атомарная транзакция.
|
||||
- При неизвестном исходе POST профиля повтор заблокирован; доступно чтение списка, черновик сохранён. 4xx создания допускает исправление/повтор. UI не присваивает найденный по login чужой профиль автоматически. Подтверждённый профиль/привязки отделены от отказа refresh.
|
||||
- Ответы проверяют userId/login, отправленные поля/права и контекст привязки. Wrong role/sections/servers не подтверждают сохранение. IDs в URL кодируются. Техническая многострочная ошибка схемы заменена понятной краткой ошибкой — иначе footer выходил за экран; обнаружено E2E, исправлено и повторено без ослабления теста.
|
||||
- 5 fault-injection unit, 27 различных data/operations E2E и 8 context E2E прошли; TypeScript, профильный lint и production frontend прошли. В UserSheet остаётся одна исходная catalog set-state-in-effect ошибка; она входит в следующий блок, suppressions нет.
|
||||
- Далее 11А.5: строгий interface catalog, loading/error/empty, точный сервер и поздние ответы/peer сбои; затем форма/таблица, клавиатура и ПК/телефон. Реальная БД/Portal не проверены.
|
||||
|
||||
|
||||
## Блок 11А.5 — каталог интерфейсов формы (2026-10-01)
|
||||
|
||||
- Каталог привязан к serverId/host; ожидание, error и подтверждённое empty различаются. Поздний ответ другого устройства отменяется. При повторе сохраняются прошлые строки/время получения, выбор блокируется до успешного чтения; черновик формы не сбрасывается.
|
||||
- API схемы отклоняют дубли интерфейсов/пиров, отсутствующий peer snapshot и пустые ключи. Ошибка peers показана явно, не выдаётся за пустой список; выбор неподтверждённого пира блокируется. Перед привязкой выбранные объекты сверяются с текущим каталогом.
|
||||
- IPsec теперь выбирает конкретного клиента/CN как требует backend; раньше весь ipsec-vpn отправлялся с пустым ключом. WireGuard остаётся выбором public-key. Время handshake/активности не называется текущим подключением.
|
||||
- Frame scroll имеет высоту родителя и min-h-0 flex цепочку. Демо каталог вычисляется при рендере; последняя исходная UserSheet set-state-in-effect ошибка устранена без suppressions.
|
||||
- 25 catalog/operations E2E, TypeScript и профильный lint прошли. Проверены API/malformed/дубли/неполные peer данные, empty/loading, поздний success/error другого сервера, WG failure/retry, IPsec CN payload и прежние операции.
|
||||
- Далее 11А.6: backend достоверность interface catalog (сейчас snapshot/история без метаданных, неизвестные флаги и скрытый IPsec failure); затем UI/доступность и локальная приёмка пользователей. Реальные RouterOS/DB/Portal не проверены.
|
||||
|
||||
|
||||
## Блок 11А.6 — backend метаданные каталога интерфейсов (2026-10-01)
|
||||
|
||||
- Добавлен /users/interface-catalog-state с serverId/source/sampledAt/inventoryComplete/failures и nullable running/disabled. Старый /interface-catalog и форма interfaces/boolean сохранены для совместимости; новый frontend будет подключён в следующем блоке.
|
||||
- Явный пустой raw snapshot не заменяется трафиком; malformed snapshot возвращает 502. Missing snapshot допускает явно подписанный fallback только к одной последней дате traffic_samples: SQL ограничен sampledAt, старые интерфейсы/peer/loopback исключены. Unknown флаги не превращаются в false.
|
||||
- WireGuard/IPsec failure не скрывается за пустыми пирами; каталог IPsec клиентов отдельно от физического состояния интерфейса, running/disabled неизвестны. Неподтверждённые клиенты raw IPsec интерфейса показаны peersError; нет дубля ipsec-vpn.
|
||||
- Строгий новый контракт и factory DI проверяют serverId, источник/полноту, время, peer keys/дубли и точный контекст ответа. GET остаётся в существующем mm:users:read; правила сетевых действий/авторизации не изменены.
|
||||
- Backend build, профильный lint, inventory parser и Fastify HTTP тесты прошли. test:users включён в общий test; прежние binding unique/cascade тесты явно skipped из-за отсутствия PostgreSQL. SQL/реальный RouterOS ещё требуют внешней приёмки.
|
||||
- Далее 11А.7: подключить frontend к state контракту, показать источник/дату/частичные отказы и неизвестное состояние; обновить HTTP-фикстуры и проверить регрессию. Затем визуальная приёмка пользователей.
|
||||
|
||||
|
||||
## Блок 11А.7 — frontend state каталог (2026-10-01)
|
||||
|
||||
- UserSheet использует /interface-catalog-state, строго проверяет новый контракт и точный serverId. Legacy reader экспортирован для совместимости, новый экран к неоднозначному envelope не возвращается.
|
||||
- UI отдельно показывает браузерное получение и время/источник среза. Snapshot и частичная traffic history подписаны; unknown не становится пустым каталогом. Nullable running отображается неизвестным состоянием, а исторические флаги не называются текущими.
|
||||
- Частичные failures интерфейсов/WG/IPsec видны сразу с повтором, включая пустой IPsec failure. IPsec-vpn подписан как каталог клиентов, а не физический интерфейс. Демо и live состояния сохраняют прежнюю композицию Frame/Stepper.
|
||||
- 44 различных data/operations/catalog E2E + 8 context E2E, TypeScript, профильный lint и production frontend прошли. Фикстуры перенесены на новый state envelope; отдельные negative тесты не дополняют отсутствующие метаданные автоматически.
|
||||
- Далее 11А.8: семантические токены таблицы/формы, доступные имена, права/клавиатура, ПК/390/320 и снимки. После приёмки пользователей — контейнеры. Реальная БД/RouterOS/Portal остаётся внешней приёмкой.
|
||||
|
||||
## Блок 11А.8 — доступность и локальная приёмка пользователей (2026-10-01)
|
||||
|
||||
- Существующие ReUI Stepper/Data Grid/Frame сохранены. Семантические токены, явные имена действий/прав, aria-pressed/expanded, клавиатурное раскрытие строки, подпись текущего шага. Vendor компоненты и тема не изменены; checklist ReUI проверен.
|
||||
- Sheet занимает ширину телефона; min-w-0 fieldset удерживает шаги в 320 px, выбор роли переносится вертикально без разрыва слов. Ошибка сохранения внутри области прокрутки, footer остаётся доступен; обязательные поля имеют aria-invalid/describedby и получают фокус.
|
||||
- Закрытие формы возвращает фокус к актуальной кнопке строки после её замены Data Grid. Найден и исправлен исходный no-op прав: отсутствующие section/server разрешения добавляются при явном выборе; «выбрать всё» охватывает показанные разделы/серверы.
|
||||
- 48 уникальных data/operations/catalog/layout E2E, 8 context E2E, TypeScript, профильный lint и production frontend прошли. HTTP payload проверен для отсутствующих разрешений. 12 снимков ПК/390/320 сохранены; просмотрены обзор/профиль/каталог/ошибка, горизонтальная прокрутка ограничена таблицей.
|
||||
- Пользователи приняты в границах локальных HTTP-подмен. Реальные Portal/PostgreSQL/RouterOS остаются внешней приёмкой; прежние DB binding тесты skipped.
|
||||
- Далее 11А.9: достоверный state API контейнеров. Аудит выявил превращение отказов устройств/envs/mounts в пустые списки, неизвестного статуса в stopped и недостоверное общее empty. Затем подключение frontend, операции и UX; сертификаты/backup ещё не приняты.
|
||||
|
||||
|
||||
## Блок 11А.9 — достоверный backend каталог контейнеров (2026-10-01)
|
||||
|
||||
- Добавлен GET /api/containers/state с общим collectedAt и состояниями каждого enabled сервера. available + [] означает подтверждённую пустую загрузку, unsupported — отсутствие /container, error — отказ чтения. Сбой одного устройства сохраняет остальные.
|
||||
- Загрузка envs/mounts независима, partial failures явно включены в контракт. Неизвестные status/startOnBoot не становятся stopped/false; отсутствующий образ не подменяется именем контейнера; нулевые CPU/RAM сохранены.
|
||||
- Runtime контракт отклоняет отсутствующие/дубли RouterOS ID, чужой serverId, неверные состояния/даты и дубли устройств/ошибок. Новый reader не выдаёт синтетический rosId для сетевого действия.
|
||||
- Старые /containers и /servers/:id/containers, mapper и сетевые операции сохранены для совместимости. RBAC соответствует существующим правилам: каталог dashboard read, команды server write; новых разрешений не введено.
|
||||
- Backend build, профильный lint, новые service/HTTP tests и старый mapper test прошли. test:containers включён в общий test. Тесты без PostgreSQL/RouterOS; реальные чтения ещё требуют внешней приёмки.
|
||||
- Далее 11А.10: frontend state reader, независимые серверы/контейнеры, последний снимок, unknown KPI, свежесть и защита смены источника. Затем подтверждённые команды, доступность/ПК/телефон.
|
||||
|
||||
|
||||
## Блок 11А.10 — frontend состояния контейнеров (2026-10-01)
|
||||
|
||||
- Live читает строгий /containers/state и отдельно /servers; slow/error одной зависимости не скрывает другую. Duplicate server IDs отклоняются. До подтверждения нет демо/ложного empty, неизвестные KPI и rail counts — —.
|
||||
- Последний успешный снимок сохраняется при общем отказе и отдельно по устройству при частичной ошибке. Неизвестный status виден явно; envs/mounts partial, unsupported и known empty различаются. Браузерное получение каждого каталога подписано.
|
||||
- Ключ backend/mode и prefsHydrated изолируют контекст; AbortController/revision/30s защищают чтение. Исчезнувший выбранный сервер не заменяется «всеми». Права соответствуют существующим dashboard read/server read/write; без свежих необходимых каталогов команды блокируются.
|
||||
- Неподключённая кнопка создания disabled. Существующая композиция Frame/KpiStatGrid/ServerRail сохранена; семантическая и мобильная приёмка впереди.
|
||||
- 14 data E2E, 4 source-context E2E, TypeScript, профильный lint и production frontend прошли.
|
||||
- Далее 11А.11: single-flight команд, строгий ok:true, подтверждение API отдельно от фактического состояния/refresh, диалог удаления и поздние мутации. Затем экспорт/доступность/ПК/390/320. Реальный RouterOS/БД остаётся внешней приёмкой.
|
||||
|
||||
|
||||
## Блок 11А.11 — подтверждённые команды контейнеров (2026-10-01)
|
||||
|
||||
- POST start/stop/restart/remove проходит через typed reader со строгим ok:true, проверкой serverId/rosId и 30s сроком. Single-flight ref блокирует все карточки; поздние ответы после ухода/смены backend не меняют UI.
|
||||
- Текст результата подтверждает команду API, фактический статус определяется повторным чтением. Ошибка refresh не отменяет подтверждение; подтверждённо удалённая карточка убирается до чтения.
|
||||
- Удаление использует устойчивый AlertDialog с target/ошибкой/повтором. Ожидание блокирует Escape/отмену. 4xx — отклонение, malformed/network/5xx — неподтверждённый или частичный результат; новое действие требует явного чтения каталога. Исчезнувший target повторно не отправляется.
|
||||
- 26 data/operations E2E, 8 context E2E, TypeScript, профильный lint и production frontend прошли. Модель сетевых команд/авторизации backend не менялась; реальные операции RouterOS требуют внешней приёмки.
|
||||
- Далее 11А.12: доступность, семантические токены, ПК/390/320 и достоверность экспорта/метрик. Аудит экспорта выявил шаблонные veth IP и команды, которые не являются экспортом реального устройства; это нельзя выдавать за резервную конфигурацию.
|
||||
|
||||
|
||||
## Блок 11А.12 — достоверный снимок и интерфейс контейнеров (2026-10-01)
|
||||
|
||||
- Недостоверный генератор RSC (шаблонные IP veth, неподтверждённые настройки и некорректные env команды) заменён JSON-снимком каталога в существующем CodeExportSheet. Файл содержит наблюдаемые поля, collectedAt, source и partial failures; явно подписан как снимок, не конфигурация/backup.
|
||||
- memory-high — лимит памяти по [MikroTik Container](https://help.mikrotik.com/docs/spaces/ROS/pages/84901929/Container), расход RAM теперь только memory-current (МиБ); отсутствие метрики не становится 0. Новые RouterOS list/mountlists и несколько envlist обрабатываются; неполные env/mount ответы становятся partial error.
|
||||
- Семантические токены, русские статусы, aria имена/pressed, поиск/переносы и 44px меню на телефоне. Sheet на всю ширину, footer переносится на 320 px через props; vendor/theme и композиция Frame/ServerRail/KpiStatGrid не изменены. Неизвестный статус не предлагает запуск/перезапуск; KPI по статусам — —.
|
||||
- 30 уникальных data/operations/layout E2E суммарно прошли (последний полный прогон 29/30, оставшийся narrow исправлен и все 4 layout повторно прошли); 8 context E2E, backend tests/build, TypeScript, профильный lint и production frontend прошли. Скачанный JSON проверен; 6 снимков сохранены и просмотрены.
|
||||
- ReUI checklist проверен в границах адаптации. Далее 11А.13: URL-контекст и clipboard отказ/фокус, затем локальная приёмка контейнеров и аудит сертификатов. Общие ошибки Clipboard в CodeExportSheet требуют обработки; реальный RouterOS/БД ещё не проверен.
|
||||
|
||||
|
||||
## Блок 11А.13 — контекст и локальная приёмка контейнеров (2026-10-01)
|
||||
|
||||
- URL восстанавливает server/status/q, поддерживает Back/reload, сохраняет чужие параметры/hash. Дубли, неверные ID/status и слишком длинный поиск показывают ошибку со сбросом. Использован существующий preserveSelection ServerRail; исчезнувшее устройство не заменяет контекст.
|
||||
- Устранены Clipboard rejection/отсутствие API в общей CodeExportSheet: сообщение с повтором/скачиванием вместо ложного «Скопировано». Бейдж относится к конкретному скопированному тексту; прежний каскадный effect заменён контролируемым сбросом при открытии/изменении начального формата. Дизайн/vendor/theme сохранены.
|
||||
- Закрытие снимка и отмена удаления возвращают фокус к актуальной кнопке карточки; после исчезновения карточки предусмотрен fallback на обновление.
|
||||
- 40 контейнерных E2E, 8 source-context, 10 профильных проверок экспорта, URL unit, TypeScript, профильный lint (включая общую оболочку) и production frontend прошли. Backend state тесты/сборка приняты в 11А.12. Контейнеры приняты локально; создание/логи/редактирование явно disabled, реальный RouterOS/БД требует внешней проверки.
|
||||
- Далее 11А.14: observed state API сертификатов. Исходный mapper делает отсутствующий срок daysLeft=0, status=valid, keySize=0/trusted=false; это нельзя выдавать за наблюдаемые значения. Legacy API/renew/issue должны сохранять совместимость до отдельной миграции; frontend, ACME jobs, настройки и экспорт сертификатов ещё не приняты.
|
||||
|
||||
|
||||
## Блок 11А.14 — observed state API сертификатов (2026-10-01)
|
||||
|
||||
- Добавлен совместимый GET /certificates/state: collectedAt, отдельные enabled устройства, подтверждённые строки или error. Новое чтение /certificate не использует tolerant getCertificates, скрывавший неверный ответ как [].
|
||||
- Новый CertificateObserved не подменяет отсутствующие срок/keySize/trusted/rosId. daysLeft nullable, status unknown; даты без часового пояса/некорректного календаря остаются raw полями и не используются для вычисления срока. Известные UTC/offset даты нормализованы; valid требует известных сроков и сведений об отзыве. Неизвестный будущий/неполный сертификат не становится valid.
|
||||
- Контракт отклоняет дубли/чужой контекст, несогласованные срок/статус и error со строками. Частичный отказ одного устройства сохраняет остальные; общий DB отказ — HTTP 500, неверный envelope — 502.
|
||||
- Legacy DTO/API, parser ролей, ACME issue/renew и сетевые операции сохранены для совместимости. Frontend ещё читает legacy; эти сценарии не приняты и требуют последующей миграции.
|
||||
- Backend build, профильный lint, observed service/HTTP tests и прежний certificate-parse test прошли. test:certificates включён в общий test. PostgreSQL/RouterOS/ACME не использованы в тестах; локальные bare-time даты требуют отдельной проверки часового пояса устройства.
|
||||
- Далее 11А.15: typed frontend reader и immutable merge последних снимков; затем 11А.16 — таблица/детали/unknown KPI, partial сбои, freshness, контекст/права. ACME settings/jobs/экспорт — последующие блоки. Резервирование, 11Б и итоговый 12 ещё не приняты.
|
||||
|
||||
|
||||
## Блок 11А.15 — typed reader и последние снимки сертификатов (2026-10-01)
|
||||
|
||||
- readCertificatesState использует строгий новый контракт, GET, caller AbortSignal + 30s срок. Unknown поля сохраняются; malformed/duplicate/чужой контекст, 204 и ошибки HTTP не становятся успешным пустым каталогом.
|
||||
- mergeCertificateSnapshots хранит latest отдельно от confirmed: отказ устройства сохраняет последний успешный снимок с его временем, первоначальный отказ имеет confirmed=null. Подтверждённое empty очищает строки; исчезнувшие enabled устройства удаляются; восстановление заменяет свой снимок без мутации прежнего состояния.
|
||||
- 5 fault/HTTP unit, TypeScript, профильный lint и production frontend прошли. Reader/merge готовы к подключению; текущая страница ещё использует legacy DTO. Приёмка сертификатов не завершена.
|
||||
- Далее узкая проверка setup ошибки клиента устройства (11А.16), затем миграция страницы/таблицы/деталей на observed nullable поля и независимые состояния. Не заменять null числом 0/false, не терять partial rows и выбранный сервер; ACME settings/jobs/экспорт проверять отдельными блоками.
|
||||
|
||||
|
||||
## Блок 11А.16 — изоляция setup ошибок устройств (2026-10-01)
|
||||
|
||||
- В обоих новых state каталогах создание клиента/reader перенесено внутрь защищённого чтения устройства. Setup исключение одного клиента становится его error/partial, остальные строки остаются доступны; общий каталог не срывается.
|
||||
- Container reader создаётся один раз и используется для /container/envs/mounts. Certificate reader остаётся отдельным для каждого устройства; сетевые команды, Legacy API и авторизация не изменены.
|
||||
- Fault тесты setup для обоих каталогов, test:containers, test:certificates, backend build, профильный lint и diff check прошли. Frontend production/TypeScript проверены в 11А.15; новых frontend изменений в этом блоке нет.
|
||||
- Последняя квота: 96% пятичасового и 77% недельного использовано. Новый большой блок не начинать при этом остатке; продолжить после проверки актуальной квоты.
|
||||
- **Точный следующий шаг — 11А.17:** подключить readCertificatesState + mergeCertificateSnapshots в app/(main)/certificates/page.tsx. Мигрировать CertificatesDataGrid и CertificateExpandedDetail на CertificateObserved/совместимый view type без nullable→0/false; обновить фильтры/KPI, independent server read, error/partial/freshness, prefsHydrated/key backend-mode и отмену/revision чтения. Проверить live HTTP failures/unknown/empty/partial/recovery/права/смену источника, TypeScript/lint/build, обновить журнал и сделать локальный коммит без push.
|
||||
- Далее отдельными блоками ACME settings и renew, issue job polling/частичное выполнение, реальный экспорт/импорт сертификатов, UX/ПК/390/320. Резервные копии, 11Б и общий 12 ещё не приняты; реальные RouterOS/Portal/PostgreSQL/ACME/S3 проверки остаются внешними.
|
||||
|
||||
|
||||
## Подключение observed сертификатов: следующий блок 11А.17
|
||||
|
||||
Референсы: существующий [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) / [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp). Сохранить композицию DataGrid v9/Frame/ServerRail и семантические токены.
|
||||
|
||||
| Данные | Сейчас в legacy UI | Требование observed UI |
|
||||
| --- | --- | --- |
|
||||
| Срок отсутствует / дата без timezone | daysLeft=0, возможный valid | —, raw дата с пояснением, unknown; не включать в подтверждённо действительные/истекающие |
|
||||
| keySize/trusted отсутствуют | 0 / false | Размер/доверие неизвестны, действия определяются API/правами |
|
||||
| Отказ одного устройства | Общий error или краткий toast | latest.error постоянно виден, confirmed строки/время сохранены |
|
||||
| Начальный отказ | Пустая таблица/нули | Список и KPI неизвестны, явный повтор |
|
||||
| Подтверждённое empty | Пустая таблица | Известный пустой каталог и нули; очищает предыдущий снимок |
|
||||
| Смена источника | Общий эффект старого контекста | Изолированный key + отмена/revision; поздний ответ не меняет новый экран |
|
||||
|
||||
[Источник и права] → [Независимые state + servers]
|
||||
↓
|
||||
[latest ошибка / confirmed снимок]
|
||||
↓
|
||||
[KPI известных данных → таблица → детали]
|
||||
↓
|
||||
[ACME/экспорт: последующие блоки]
|
||||
|
||||
Проверенные заготовки: shared/api/certificates.ts (readCertificatesState), lib/certificate-snapshots.ts, новый contracts CertificateObserved. Legacy API/renew/issue ещё используются, их миграцию не считать завершённой.
|
||||
|
||||
## Блок 11А.17.2 — state каталог на странице сертификатов (2026-10-01)
|
||||
|
||||
- Страница читает readCertificatesState и независимо строгий каталог серверов. Снимки сохраняются при общем/частичном отказе; подтверждённое empty очищает прежние строки. Отображаются время каталога и время последнего успешного чтения каждого устройства.
|
||||
- useCertificateCatalog отменяет чтения при unmount/смене источника, использует revision и общий срок 30s. Результат одного источника не ждёт другой; источники разделены key mode/backend после prefsHydrated.
|
||||
- Неизвестная/частичная сводка показывает — с объяснением, фильтр неизвестных статусов доступен. Выбор сервера сохраняется при отказе каталога; неизвестный статус сервера не превращается в offline на rail.
|
||||
- Refresh теперь повторяет строгий GET state, не подмешивает legacy DTO и не объявляет частичный результат полным успехом. Write-действия требуют права сертификатов, выпуск также требует доступного каталога серверов. Неподключённый импорт отключён вместо ложного сообщения об успехе.
|
||||
- 12 профильных HTTP E2E, TypeScript, ESLint и production frontend прошли. API контракт/сетевые правила не менялись.
|
||||
- Следующий блок 11А.17.3: URL server/status/q и проверки позднего ответа при смене mode/backend. Затем отдельные блоки ACME/renew, issue polling, UI/экспорт и приёмка. Сертификаты в целом, резервные копии, 11Б/12 не приняты; реальные RouterOS/ACME/Portal проверки остаются внешними.
|
||||
|
||||
## Блок 11А.17.3 — URL и изоляция источника сертификатов (2026-10-01)
|
||||
|
||||
- server/status/q читаются из URL: reload/Back сохраняют контекст, чужие параметры и hash не теряются. Дубликаты, неизвестные статусы, некорректные ID и слишком длинный поиск явно отклоняются; сброс не удаляет чужой контекст. Mock srv ID поддержан отдельно.
|
||||
- Недоступный сервер не заменяется всеми устройствами; ошибка ссылки скрывает строки. Нет совпадений отличается от подтверждённого пустого каталога. Моковые данные подписаны явно.
|
||||
- 3 URL unit, 6 URL E2E и 4 E2E смены backend/mode с поздним успехом/ошибкой прошли. ESLint/TypeScript прошли; production сборка URL/Suspense прошла до финального добавления подписи моков, после него повторены TypeScript и E2E.
|
||||
- Далее 11А.18: строгие ответы/отмена API ACME/renew/issue, затем достоверные формы настроек и issue checkpoint/polling. Настройки, выпуск и общая приёмка сертификатов пока не приняты.
|
||||
|
||||
## Блок 11А.18 — строгие API настроек и выпуска сертификатов (2026-10-01)
|
||||
|
||||
- ACME/renew settings и issue request/ответы проверяются существующими contracts схемами. Malformed/204 не считаются успешным сохранением; пустой jobId и чужая задача в polling отклоняются. Legacy list/refresh тоже валидируют DTO.
|
||||
- Все certificate API принимают caller AbortSignal вместе со сроком 30s. Ошибка Cloudflare с backend message сохраняет понятную причину вместо HTTP Bad Request. Payload проверяется до mutation запроса.
|
||||
- 5 новых API fault тестов + 5 snapshot/reader тестов, TypeScript и профильный ESLint прошли. Следующий блок 11А.19 — достоверное чтение и сохранение renew настроек, затем ACME и issue polling. Реальные ACME/RouterOS операции пока не приняты.
|
||||
|
||||
## Блок 11А.19 — достоверные настройки автообновления (2026-10-01)
|
||||
|
||||
- Renew форма начинает с unknown, а не enabled/default расписания. Ошибка чтения оставляет операции заблокированными до подтверждённого GET; есть явный повтор и отдельные read/write права. Read-only не выдаётся за недоступный backend.
|
||||
- Числа проверяются без parseInt/default/clamping: целый интервал от 300 и срок 1–90. Ошибка/204/malformed PUT сохраняет подтверждённое состояние и dirty черновик. Переключатель меняется только после подтверждения, toggle/schedule имеют общий синхронный lock.
|
||||
- Фоновый GET не стирает dirty черновик; запросы отменяются при unmount, поздний ответ не меняет другой источник и не показывает старый toast. Disabled MM не объявляется доказательством включённого RouterOS ACME.
|
||||
- 10 renew E2E, повторные 12 data E2E, 2 context E2E позднего PUT, TypeScript/ESLint и production frontend прошли. HTTP fixtures приведены к реальному renewBeforeDays контракту.
|
||||
- Следующий блок 11А.20: выделить достоверную форму ACME, неизвестное чтение, сохранение черновика/токена, общий lock save/test и отмена; затем issue checkpoint/polling и приёмка сертификатов.
|
||||
|
||||
## Блок 11А.20 — достоверная форма ACME (2026-10-01)
|
||||
|
||||
- ACME форма выделена в собственный компонент с прежней OpsPanel/ReUI композицией. До подтверждённого GET настройки и состояние токена неизвестны; read-only читает фактические значения, сохранение/тест требуют write права.
|
||||
- Dirty URL/zone/token сохраняются при фоновом чтении и отказе PUT. Токен очищается только после валидного подтверждения; tokenConfigured=false при отправленном токене не считается успехом. Пустое поле сохраняет прежний секрет на backend.
|
||||
- Save/test имеют общий синхронный lock и блокируют поля на время операции; test не объявляется сохранением. Ошибка Cloudflare видна с причиной. При unmount запросы отменяются, старые ответы/toast не попадают в другой источник.
|
||||
- 10 ACME E2E, 2 поздних PUT context E2E, 2 read-only E2E, TypeScript/ESLint и production frontend прошли.
|
||||
- Следующий блок 11А.21: совместимость реального issue DTO (backend serverId сейчас числом, failed step не включён в контракт), затем сохранение job checkpoint и отмена polling без повторного POST. Выпуск/общая приёмка сертификатов, backups/11Б/12 остаются незавершёнными.
|
||||
|
||||
## Блок 11А.21.1 — совместимость issue DTO (2026-10-01)
|
||||
|
||||
- Реальный backend issue DTO теперь преобразует числовой PostgreSQL serverId в строковый ID контракта; результат проверяется схемой вместо приведения step через as. JSON/JSONB имена доменов поддержаны, malformed значения отклоняются.
|
||||
- В enum шага добавлен failed, который уже записывает runner. Ошибка задачи и finishedAt сохраняются, а не теряются при frontend strict parse. Сетевой runner/порядок операций и правила прав не менялись.
|
||||
- 4 DTO unit, backend test:certificates/build, профильный ESLint, повторные 10 frontend API/snapshot unit и frontend TypeScript прошли.
|
||||
- Далее 11А.21.2: poll helper с отменой и проверкой ожидаемого server/name/domains, затем сохранённый checkpoint на странице и live HTTP fault тесты повторного нажатия/ошибки/смены источника.
|
||||
|
||||
## Блок 11А.21.2 — отменяемое наблюдение issue задачи (2026-10-01)
|
||||
|
||||
- pollCertificateIssue проверяет jobId, сервер, имя и домены перед наблюдением результата. queued/running не считаются успехом; done требует шага done. failed возвращает реальную ошибку задачи.
|
||||
- Caller abort отменяет задержку и блокирует позднее наблюдение; polling ограничен 120 чтениями и сроком 5 минут, каждое HTTP чтение имеет свой срок. Ошибка GET/истечение наблюдения не объявляются failed задачей и не запускают новый POST.
|
||||
- 5 fault unit и TypeScript/ESLint прошли. Helper пока не подключён к форме.
|
||||
- Следующий блок 11А.21.3: повторяемое создание issue с устойчивым requestId на backend, затем frontend checkpoint и возобновление наблюдения. Это необходимо, чтобы потеря POST ответа не провоцировала второй выпуск.
|
||||
|
||||
## Блок 11А.21.3 — устойчивое создание issue задачи (2026-10-01)
|
||||
|
||||
- В запрос выпуска добавлен необязательный UUID requestId. Backend использует существующий primary key задачи и INSERT ON CONFLICT DO NOTHING: повтор идентичной цели возвращает тот же jobId без повторной очереди, другая цель/source с тем же ID получает 409. Старые клиенты без requestId продолжают получать независимые UUID. Миграция БД не нужна.
|
||||
- Request ID сохраняется и проверяется frontend API; чужое подтверждение отклоняется. Server ID должен быть безопасным положительным целым, имя/домены не могут быть пустыми после trim. Контракт нормализует поля перед созданием.
|
||||
- 4 request helper unit (включая конкурентный повтор), HTTP handler fault проверки, backend test:certificates/build, 6 frontend API unit, polling unit, frontend TypeScript и профильный lint прошли. Проверки helper/HTTP используют тестовый repository; реальный PostgreSQL INSERT и RouterOS выпуск остаются внешней приёмкой. Runner и сетевой порядок операций не менялись.
|
||||
- Следующий блок 11А.21.4: frontend checkpoint с заранее созданным requestId и неизменной целью, resume GET/poll без нового ID, сохранение в пределах источника, отмена и HTTP fault/context проверки.
|
||||
|
||||
## Блок 11А.21.4 — сохраняемая задача выпуска на странице (2026-10-01)
|
||||
|
||||
- До POST создаётся requestId и immutable цель, записывается checkpoint sessionStorage по backend URL. Невозможность первоначальной записи не отправляет выпуск. Reload восстанавливает ту же задачу; моковый режим не показывает live checkpoint. Повреждённая запись блокирует новый выпуск.
|
||||
- Принятый job повторно наблюдается GET/poll без POST. Неподтверждённый запрос сначала проверяет известный ID; при 404 повторяет тот же POST/requestId, защищённый backend от дублей. Read/write права разделены. Ошибка GET/чужая цель не считаются успешным или failed выпуском.
|
||||
- Sheet/Stepper сохраняют цель и блокируют её изменение после принятия; реальный failed и частичное выполнение показаны явно. Новый выпуск после terminal требует отдельного действия и начинается с пустого имени/доменов. Закрытие формы не объявляется отменой server job. После done ошибка перечитывания каталога не меняет результат задачи. Неподключённый FileImportDialog с ложным callback удалён.
|
||||
- При unmount отменяются POST/poll/задержки; поздние успех/ошибка не меняют другой backend/mode и не показывают старый toast.
|
||||
- 3 checkpoint + 5 poll unit, 7 issue E2E, 8 source/context E2E, TypeScript/ESLint и production frontend прошли. Реальный PostgreSQL/ACME/RouterOS выпуск не проверен; pending job восстановление после перезапуска backend требует отдельной инфраструктурной приёмки.
|
||||
- Следующий блок 11А.22: семантические токены, клавиатура/ПК/390/320, снимки и профильная регрессия сертификатов. Импорт/экспорт приватного ключа остаются явно недоступны; безопасный JSON снимок каталога можно добавить отдельно. Затем резервные копии и 11Б/12.
|
||||
|
||||
## Блок 11А.22 — визуальная и профильная приёмка UI сертификатов (2026-10-01)
|
||||
|
||||
- Состояния таблицы/предупреждений используют semantic success/warning/destructive. Раскрытие деталей имеет native кнопку с именем, aria-expanded и клавиатурой; исходные нераспознанные даты RouterOS показываются явно без подмены нормализованной датой.
|
||||
- Общее количество остаётся известным при неизвестных статусах/сроках, отдельные классификации показывают —. Мобильный фильтр сохраняет подписи в горизонтальном контейнере; Sheet использует full width через data-side вариант, footer переносится. Vendor/theme не изменены.
|
||||
- 9 PNG (обзор/детали/форма × ПК/390/320) сохранены и просмотрены. Layout проверки включают отсутствие горизонтального overflow страницы/формы, клавиатурное раскрытие, поиск и возврат фокуса после Escape.
|
||||
- Профильная регрессия: 48 main E2E + 16 context E2E, 26 frontend unit, backend test:certificates, frontend/backend production build, TypeScript/профильный ESLint и ReUI checklist прошли. Реальные PostgreSQL/ACME/RouterOS/S3 не проверялись.
|
||||
- UI сертификатов принят в этих локальных границах. При сверке runner найден отдельный дефект: ошибка appendEvent после успешного выпуска попадает в общий catch и записывает failed; fire-and-forget onStep может перезаписать terminal шаг.
|
||||
- **Следующий блок 11А.23:** отделить события/ошибки метаданных runner от результата реальной операции, упорядочить onStep записи, защитить terminal от повторного запуска и cleanup lock при setup ошибке; fault unit/backend checks. Затем метаданные JSON snapshot/окончательная приёмка сертификатов и резервные копии.
|
||||
|
||||
### Экраны сертификатов
|
||||
|
||||
| Область | Проверенные изображения | Схема |
|
||||
| --- | --- | --- |
|
||||
| Обзор | [ПК](screens/certificates-overview-desktop.png), [390](screens/certificates-overview-mobile.png), [320](screens/certificates-overview-narrow.png) | Свежесть → известный итог / неизвестные классификации → настройки → таблица |
|
||||
| Детали | [ПК](screens/certificates-details-desktop.png), [390](screens/certificates-details-mobile.png), [320](screens/certificates-details-narrow.png) | Фильтр → native раскрытие → поля и unknown → исходные даты |
|
||||
| Выпуск | [ПК](screens/certificates-issue-desktop.png), [390](screens/certificates-issue-mobile.png), [320](screens/certificates-issue-narrow.png) | Цель → проверка → requestId → та же задача → подтверждение API |
|
||||
|
||||
## Блок 11А.23 — достоверный результат backend issue runner (2026-10-01)
|
||||
|
||||
- События и ошибки записи прогресса отделены от результата ACME/RouterOS. Ошибка appendEvent после успеха не записывает failed; ошибка итоговой записи остаётся ошибкой наблюдения, без повторного импорта. Очередь перехватывает setup rejection, process lock освобождается при любой ошибке.
|
||||
- onStep записи выполняются последовательно и завершаются перед terminal. Done/failed/running записи не запускают сетевую операцию заново; восстановление running после перезапуска требует отдельной инфраструктурной сверки, автоматический replay не добавлен.
|
||||
- Реальная фаза dns_a_sync добавлена в контракт. Диагностические callback строки Cloudflare сохраняются отдельными событиями, старые DB строки читаются как dns_a_sync. Порядок ACME/DNS/RouterOS не изменён.
|
||||
- 10 fault unit runner, 5 DTO unit, полный backend test:certificates/build, 14 frontend API/poll/checkpoint unit, TypeScript и профильный ESLint прошли. PostgreSQL/ACME/RouterOS остаются внешней приёмкой; lock действует в одном процессе, распределённый lease не реализован.
|
||||
- **Следующий блок 11А.24:** закрыть локальную приёмку сертификатов с явными ограничениями и начать строгие API-контракты резервных копий. JSON metadata snapshot необязателен; PEM/private key import/export остаётся недоступным.
|
||||
|
||||
## Блок 11А.24 — локальная приёмка сертификатов и API резервных копий (2026-10-01)
|
||||
|
||||
- Сертификаты приняты локально по 11А.14–11А.23: state/unknown/частичные сбои, URL, права, renew/ACME формы, checkpoint выпуска и runner, 48 main + 16 context E2E и ПК/390/320 снимки. После runner исправления backend профиль/10 fault unit/5 DTO unit, frontend API/poll/checkpoint и production сборки прошли. Реальный PostgreSQL, ACME, RouterOS, восстановление running после рестарта и распределённая блокировка остаются внешней приёмкой. PEM/private key import/export не реализованы; JSON metadata snapshot не обязателен для принятого объёма.
|
||||
- Backups API использует общие Zod-контракты: список без дублей, обязательное storage, корректные даты/размеры; job counters и результаты согласованы, terminal имеет время окончания, чужой ID не принимается. Partial done с failures остаётся частичным результатом. Удалён неиспользуемый createBackups, ожидавший синхронные created вместо фактического job ack.
|
||||
- Настройки и ответы restore/test/sync проверяются, запросы принимают AbortSignal и 30s срок. DELETE требует фактический HTTP 204, IDs кодируются. Некорректный запрос создания/расписания отклоняется до HTTP; известные false/0/empty не подменяются.
|
||||
- 6 API fault unit, frontend TypeScript/профильный ESLint, backend и frontend production build прошли. Backups UI/операции ещё не приняты: Promise.all, отсутствие source/mode/RBAC guard, сброс черновика, повтор POST, интервал polling и ошибки событий требуют следующих блоков. Реальные PostgreSQL/RouterOS/S3 не проверялись.
|
||||
- **Следующий блок 11А.25:** независимые подтверждённые каталоги backups/servers/schedule/storage, source guard и read/write права, initial/empty/stale/partial состояния. Далее формы настроек, создание/опрос, restore/delete/download и визуальная приёмка.
|
||||
|
||||
## Блок 11А.24.1 — актуальная E2E-фикстура резервных копий (2026-10-01)
|
||||
|
||||
- Полный TypeScript после строгого BackupItem обнаружил старую admin-tables фикстуру без обязательного storage. Добавлено фактическое local; API-схема не ослаблена.
|
||||
- Повторный полный TypeScript и 2 существующих E2E резервных копий (сортировка/подтверждение удаления, Filters) прошли. Production frontend/backend и API unit выполнены в 11А.24.
|
||||
- Далее 11А.25: независимые каталоги, права и источник страницы.
|
||||
|
||||
## Блок 11А.25 — независимые каталоги резервных копий (2026-10-01)
|
||||
|
||||
- После hydration страница привязана к mode/backend. Live не начинает с демонстрационных строк; mock использует локальный каталог с явной подписью и отключёнными операциями. Запросы отменяются при unmount/новом чтении, revision подавляет поздние ответы.
|
||||
- История, серверы, расписание и хранилище читаются независимо с отдельными known/error/receivedAt. Отказ/медленный ответ зависимости не скрывает историю. Initial unknown, loading, подтверждённый empty и старый подтверждённый список различаются; ручной повтор и время чтения показаны. 0 байт остаётся 0 Б.
|
||||
- Read/write/server read права проверены перед запросами/действиями. Создание требует актуальный каталог серверов и хранилища; удаление/restore отключены для reader, download требует read. Restore для удалённого serverId недоступен.
|
||||
- Фоновое чтение не сбрасывает dirty черновики. Сводка расписания/назначения берётся из подтверждённых DTO; draft не называется сохранённым. UI настроек пока ожидает оба DTO, отдельные формы/валидация/частичное сохранение входят в следующий блок.
|
||||
- 12 data E2E + 2 существующих table/Filters E2E + 4 context E2E, полный TypeScript, профильный ESLint и production frontend прошли. Реальные PostgreSQL/RouterOS/S3 не проверены.
|
||||
- **Следующий блок 11А.26:** backend достоверность резервного копирования/restore при сбоях журнала событий. Затем 11А.27 формы настроек, dirty/секреты/проверка S3/общий lock, создание и polling, delete/restore/download, URL и визуальная приёмка. Весь backups ещё не принят.
|
||||
|
||||
## Блок 11А.26 — результат операций отделён от событий (2026-10-01)
|
||||
|
||||
- Ручной job и restore используют безопасную запись событий: отказ журнала не прерывает запуск, не превращает созданные файлы в failed и не возвращает ошибку после подтверждённого импорта RouterOS. Process job вынесен в тестируемую функцию; map задач локален экземпляру routes.
|
||||
- Создание использует общий строгий request контракт, поддерживает прежние numeric IDs. Дубли/невалидные/отсутствующие выбранные серверы отклоняются до создания задачи; молчаливое выполнение только части запроса удалено. Frontend ack проверяет total всех выбранных целей.
|
||||
- Персональные ошибки остаются partial done с created/failures. Ошибка S3 загрузки сохраняет локальную копию и uploadError; итоговое событие имеет warning и число ошибок загрузки. Frontend polling пока требует отдельной доработки, чтобы не называть такой done полным успехом.
|
||||
- 3 fault unit job, HTTP handler проверки create/restore при отказах событий, invalid target/no side effect/partial/RBAC, test:backups (включая S3 client), backend production build, 6 frontend API unit, TypeScript/профильный lint прошли. Реальный PostgreSQL/RouterOS/S3 не проверен; jobs in-memory теряются после рестарта, requestId/idempotency ещё не реализованы.
|
||||
- **Следующий блок 11А.27:** достоверные формы расписания/хранилища, independent known состояния, dirty/секреты/partial save/общий mutation lock и S3 test без скрытого сохранения. Далее 11А.28 создание/checkpoint/polling; scheduler event/setup cleanup дополнительно проверить в 11А.26.1 или 11Б.
|
||||
|
||||
## Блок 11А.27.1 — независимое сохранение настроек и расписания (2026-10-01)
|
||||
|
||||
- Расписание и хранилище имеют отдельные кнопки/PUT/подтверждения. Отказ одного DTO не скрывает известную соседнюю форму. Общий settings lock защищает save/test/sync от повторов; поля заблокированы на время отправки, старый GET отменяется. Unmount отменяет мутацию и подавляет поздние toast/state.
|
||||
- Числовой черновик сохраняет blank/дробный/выходящий за диапазон ввод: значения не clamp/parseInt. Валидация 0–23/0–59/1–28/1–365 до HTTP. Доступны произвольные минуты. Точный формат сохраняется; enabled binary backup требует явного выбора поддерживаемого .rsc. Недоступность .backup не заменяется обещанием «скоро».
|
||||
- Пустой список serverIds обозначает явный режим всех включённых устройств, включая будущие; пустой ручной выбор не отправляется. Устаревшие выбранные IDs требуют изменения/обновления. Backend семантика расписания не изменена.
|
||||
- API подтверждает отправленные поля и наличие нового секретного ключа. Ошибка остаётся в постоянном Alert/черновике; только подтверждённый save очищает secret. Test/sync S3 используют сохранённую конфигурацию и не делают скрытый PUT; dirty форма просит явно сохранить её.
|
||||
- 10 helper/API unit, 12 data + 9 settings E2E (повтор после исправления a11y имени checkbox), 8 context E2E, полный TypeScript/профильный ESLint и production frontend прошли. Реальные PostgreSQL/RouterOS/S3 не проверены.
|
||||
- **Следующий блок 11А.27.2:** валидация S3/доступные имена полей, корректная свежесть последнего теста при изменении конфигурации, секрет/невалидный ack/API error/test без PUT и профильная проверка. Затем создание/checkpoint/polling, остальные операции и визуальная приёмка.
|
||||
|
||||
## Блок 11А.27.2 — достоверные настройки и последняя проверка S3 (2026-10-01)
|
||||
|
||||
- S3 форма валидирует обязательные Bucket/Access key/Secret key или наличие сохранённого секрета, HTTP(S) Endpoint. Пустое secret поле оставляет существующий ключ; пробельный новый ключ отклоняется. Поля и toggles имеют доступные имена. Dirty настройка имеет статус «Не сохранено», показ/скрытие секрета не считается изменением конфигурации.
|
||||
- Backend сбрасывает lastTestAt/error при фактическом изменении S3-конфигурации/ключей. Test запись проверяет updatedAt через условный UPDATE; изменившаяся конфигурация требует повторной проверки. UI показывает «Проверено ранее» и дату, не Connected; API error с подтверждённым settings обновляет последний receipt. Реальный PostgreSQL optimistic UPDATE ещё требует внешней приёмки.
|
||||
- Совместимость строгого backup API с PostgreSQL подтверждена mapper unit: raw timestamp преобразуется в ISO того же момента. Null server/0 byte/uploadError сохраняются; invalid дата/размер отклоняются. Сравнение timestamp receipt учитывает представление PostgreSQL, а не только строковое равенство.
|
||||
- 28 data/settings/storage E2E, 11 frontend helper/API unit, 3 DTO + 3 storage update + 3 job fault unit и HTTP/S3 профиль, frontend/backend production build, TypeScript/профильный ESLint прошли. Реальные PostgreSQL/RouterOS/S3 и конкурентные внешние клиенты не проверены.
|
||||
- **Следующий блок 11А.28:** single-flight создание, immutable цель/checkpoint, наблюдение без setInterval гонок и ложного полного успеха при failures/uploadError. Jobs сейчас in-memory: рестарт backend означает потерю наблюдения; автоматический повтор неизвестного POST недопустим. Затем delete/restore/download, URL, scheduler cleanup и визуальная приёмка.
|
||||
|
||||
## Блок 11А.28.1 — идентичность задачи и основа наблюдения (2026-10-01)
|
||||
|
||||
- Create request принимает необязательный UUID requestId; job/ack содержат canonical serverIds, job содержит заметку. Повтор той же цели/заметки в том же backend процессе возвращает прежний job; конфликт ID возвращает 409. Конкурентный повтор после async catalog lookup резервируется одним Map insert, без второй очереди. Старые клиенты без ID получают отдельные UUID.
|
||||
- Событие запуска записывается независимо от очереди/ack, чтобы медленный журнал не держал запуск. GET job контракт проверяет цель, число устройств и принадлежащие ей created/failures. API ack проверяет request ID/все serverIds, неизвестное тело не подтверждает операцию.
|
||||
- Добавлены строгий checkpoint по backend URL и serial polling helper: immutable request до POST, cross-check наблюдения, AbortSignal/срок чтения/наблюдения, read failure/timeout не становятся failed server job. Outcome отличает полный успех от device failures и uploadError.
|
||||
- 16 frontend API/checkpoint/poll unit, backend test:backups с HTTP concurrent retry/conflict/RBAC, backend production build, полный TypeScript/профильный ESLint прошли. UI пока использует старое создание/setInterval; подключение в следующем блоке.
|
||||
- Jobs/idempotency Map существуют только в текущем процессе. После рестарта API может вернуть 404 для ранее принятой операции; автоматический повтор неизвестного POST не реализован и недопустим без durable repository. Реальные DB/RouterOS/S3/рестарт не проверены.
|
||||
- **Следующий блок 11А.28.2:** frontend checkpoint до POST, общий lock формы, GET-only resume/после reload/неизвестного ответа, точный partial результат, поздние ответы источника и профильные E2E. Затем остальные операции/URL/визуальная приёмка.
|
||||
|
||||
## Блок 11А.28.2 — сохраняемая задача создания резервных копий (2026-10-01)
|
||||
|
||||
- До POST сохраняется immutable requestId/serverIds/заметка в sessionStorage по backend URL. Первичная ошибка записи не отправляет запрос. Форма блокирует изменение цели после передачи; закрытие не объявляется отменой server job. При подтверждённом 4xx создания черновик остаётся доступным для исправления.
|
||||
- Reload/неизвестный POST восстанавливает ту же задачу. Любой resume выполняет только GET/serial polling: 404 in-memory job означает неизвестный результат/возможный рестарт, не разрешение второго POST. Некорректный checkpoint/чужая цель не допускают новое создание. New task доступен только после известного terminal и отдельного действия.
|
||||
- Done с device failures/uploadError показывает подтверждённый частичный результат и созданное количество; полный success требует всех файлов без ошибок. Неуспешное перечитывание истории отдельно сохраняет подтверждение job. Общий lock формы исключает двойной POST; settings при активном/неизвестном job недоступны.
|
||||
- Late POST/poll/задержки отменяются при unmount и не меняют другой backend/mode, не показывают старый toast. Sheet адаптирован full width через data-side вариант; footer переносится, цель и job ID сохраняются.
|
||||
- 9 job E2E + 28 data/settings/storage регрессии, 16 context E2E, TypeScript/профильный ESLint/production frontend прошли; helper/backend проверки выполнены в 11А.28.1. Реальные PostgreSQL/RouterOS/S3/рестарт не проверены; durable job repository отсутствует.
|
||||
- **Следующий блок 11А.29:** delete/restore/download: synchronous locks, контекст/отмена, точное подтверждение цели и отделение API результата от refresh; backend partial cleanup и правила восстановления проверить. Затем URL, Frame/адаптивность, scheduler cleanup и приёмка backups.
|
||||
|
||||
## Блок 11А.29.1 — подтверждение операций и отмена старого контекста (2026-10-01)
|
||||
|
||||
- Delete/restore используют синхронный общий lock и immutable цель. Ошибка API сохраняет диалог/файл и показывается внутри него; Escape/отмена заблокированы во время запроса. Только DELETE 204 удаляет подтверждённую строку и закрывает диалог. Ошибка отдельного refresh не отменяет подтверждение удаления.
|
||||
- Restore сверяет filename и говорит об API-подтверждении импорта, а не о проверенной рабочей конфигурации. Полная идентичность serverId/backupId и неизвестный результат импорта требуют следующего backend/API блока.
|
||||
- Download имеет single-flight по файлу, caller AbortSignal/срок чтения и проверку MIME. HTML/JSON 200 не сохраняются как бэкап; object URL освобождается. Unmount/source отменяют все три операции и подавляют поздние toast/скачивание/state.
|
||||
- Предупреждение restore вынесено из HTML-абзаца, устранена ошибка вложенности/hydration.
|
||||
- 9 API unit, 6 operations E2E (повтор после исправления HTML), все 28 context E2E, TypeScript, профильный ESLint и production frontend прошли. Реальные RouterOS/PostgreSQL/S3 не проверены.
|
||||
- **Следующий блок 11А.29.2:** backend cleanup удаления: не игнорировать S3 ошибки, удалять запись после файлов, сохранить возможность повторить частичную очистку. Исходные bucket/endpoint в записи не хранятся — историческое происхождение S3 остаётся ограничением. Затем restore identity/неизвестный результат, URL/Frame/адаптивность и scheduler/приёмка.
|
||||
|
||||
|
||||
## Блок 11А.29.2 — подтверждённая очистка перед удалением записи (2026-10-01)
|
||||
|
||||
- Backend удаляет S3 объект и локальный файл до записи каталога. Ошибка S3/диска/DB выходит наружу, не превращается в 204. Отсутствие рабочего S3 подключения при s3Key отклоняет удаление. Сохранившаяся запись позволяет повторить частичную очистку; local rm force и S3 DeleteObject допускают уже отсутствующий объект.
|
||||
- Имя локального файла проверяется до любых side effects: разделители/traversal/absolute target отклоняются, путь остаётся внутри storage/backups. Проверки не удаляют реальные файлы.
|
||||
- Диалог явно указывает текущее подключение S3. Записи исторически хранят только object key, исходные bucket/endpoint не сохранялись: отсутствие объекта в прежнем bucket, очистка версий S3 и внешние конкурентные изменения не подтверждены. Это ограничение не скрыто обещанием физического удаления всех исторических копий.
|
||||
- 3 fault/order/path unit, полный backend test:backups (DTO/storage/job/HTTP/S3), HTTP DELETE 204/500/404 и RBAC, backend production build и профильный ESLint прошли. Frontend изменён только текстом пояснения. Реальные PostgreSQL/RouterOS/S3 не проверены.
|
||||
- **Следующий блок 11А.29.3:** restore receipt backupId/serverId, неизвестный результат импорта и повтор; затем URL/Frame/адаптивность, scheduler cleanup и локальная приёмка резервных копий.
|
||||
|
||||
|
||||
## Блок 11А.29.3 — идентичность подтверждения импорта (2026-10-01)
|
||||
|
||||
- Restore receipt содержит backupId и numeric serverId наряду с filename/актуальным serverName. API проверяет обе цели, страница проверяет filename. UI serverId преобразуется из string в number согласно контракту. Ответ чужого сервера/бэкапа и старый неполный receipt не закрывают диалог и не подтверждают импорт. Переименование сервера не считается ошибкой.
|
||||
- Backend/helper и тестовые HTTP ответы мигрированы вместе. 10 frontend API unit, backend test:backups, 7 operations E2E и 4 restore context E2E, frontend/backend production build, TypeScript и профильный ESLint прошли. Первый прогон выявил string/number ID mismatch; исправлено и проверки повторены.
|
||||
- API receipt подтверждает ответ импорта, не работоспособность конечной конфигурации. Внешние RouterOS/PostgreSQL/S3 не проверены. Потеря ответа и blind fallback после ошибки импорта остаются следующим блоком.
|
||||
- **Следующий блок 11А.29.4:** неизвестный результат restore, ограничение повторного импорта и его HTTP семантика; далее URL/Frame/адаптивность и scheduler/приёмка backups.
|
||||
|
||||
|
||||
## Блок 11А.29.4 — неизвестный результат импорта на backend (2026-10-01)
|
||||
|
||||
- Import fallback /execute разрешён только при RouterOS HTTP 404/405 для /import. Таймаут/обрыв, невалидный JSON, 400/401/500 не запускают второй импорт. После отправки команды любая ошибка маркируется BackupRestoreUnknownError; HTTP 502/outcome unknown не объявляет конфигурацию неизменённой. Ошибка подготовки до импорта остаётся 400/outcome not-applied.
|
||||
- Событие успешного импорта пишется независимо от HTTP receipt: медленный/отказавший журнал не удерживает подтверждённый ответ. Успешный импорт не повторяется helper-функцией.
|
||||
- 3 restore fault unit (сети в них нет), весь backend test:backups с HTTP outcome 502/400, backend production build прошли. Профильный lint новых/helper/service/routes файлов прошёл. В mikrotik.ts остались две исходные prefer-const ошибки (req/entry); наличие обеих подтверждено lint версии HEAD до изменения, новых lint ошибок нет.
|
||||
- Реальный RouterOS не проверен; /execute receipt подтверждает ответ команды, не завершение всех изменений конфигурации. Backend durable restore/idempotency repository пока отсутствует; клиентский запрет слепого повтора нужен следующим блоком.
|
||||
- **Следующий блок 11А.29.5:** checkpoint restore до POST, неизвестный результат/после reload и явная проверка роутера перед новым импортом; затем URL/Frame/адаптивность, scheduler и приёмка backups.
|
||||
|
||||
|
||||
## Блок 11А.29.5 — отметка неизвестного restore до POST (2026-10-01)
|
||||
|
||||
- До POST записывается immutable backupId/serverId/filename/имя/время в sessionStorage по backend URL. Отказ записи не отправляет импорт. Синхронный guard и общий operation lock защищают повтор; hydration/corrupt checkpoint не допускают начало.
|
||||
- Обрыв, deadline, чужой receipt, backend unknown и legacy 400 без outcome сохраняют отметку. Reload/возврат не запускает POST и блокирует restore. Известный 400 not-applied/403/404/405 или подтверждённый receipt очищает отметку. Отказ очистки сохраняет блокировку, но не отменяет toast подтверждённого импорта.
|
||||
- Новый импорт требует явного checkbox «Я проверил состояние роутера…» и отдельного действия «Разрешить новое восстановление». Оно только снимает отметку, не отправляет запрос и не объявляет конфигурацию проверенной приложением. Read-only/занятость запрещают снятие; после unknown диалог закрывается кнопкой «Закрыть», это не отмена server operation.
|
||||
- 2 checkpoint/classification unit, 12 operations E2E, все 28 context E2E, TypeScript/профильный ESLint и production frontend прошли. Тесты уточнены: review выполняется после закрытия modal, checkpoint same-origin привязан к location.origin.
|
||||
- Durable backend restore repository отсутствует: отметка действует в текущей вкладке/sessionStorage, не синхронизирует разные браузеры/вкладки и не доказывает результат RouterOS. Реальные RouterOS/PostgreSQL/S3 не проверены; ручная проверка устройства остаётся внешним действием.
|
||||
- **Следующий блок 11А.30:** URL контекст истории/табов/Filters, затем Frame и визуальная адаптивная приёмка, unknown статус устройств, scheduler cleanup и локальная приёмка backups.
|
||||
|
||||
|
||||
## Блок 11А.30 — URL контекст истории и ReUI Filters (2026-10-01)
|
||||
|
||||
- Поиск q, kind и вкладка tab читаются из URL. Полный FilterQuery сохраняется как versioned filters после завершения значений; draft остаётся локальным до завершения. Back/Forward сбрасывает локальный draft и восстанавливает контекст. Search использует replace, вкладка/тип/Filters — push; чужие параметры и hash сохраняются.
|
||||
- Validator ограничивает размер 8192 bytes/50 узлов/4 уровня, уникальные IDs, известные поля/operator/value, text/select наборы. Некорректная/повторяющаяся ссылка показывает постоянную ошибку со сбросом контекста; история не подменяется unfiltered списком. Сброс удаляет только собственные ключи.
|
||||
- 2 URL validator unit, 5 URL E2E + 2 исходных table/Filters E2E, 12 operations E2E, TypeScript/профильный ESLint и production frontend прошли. Первый URL E2E уточнён по фактическому имени вкладки «История бэкапов»; повтор прошёл.
|
||||
- Создание/restore checkpoints остаются привязаны к источнику, URL не запускает операции. Реальные RouterOS/PostgreSQL/S3 не проверены.
|
||||
- **Следующий блок 11А.31:** ReUI Frame, desktop/390/320, визуальные состояния истории/настроек/форм/ошибок, nullable статус устройств; затем scheduler cleanup и приёмка backups.
|
||||
|
||||
|
||||
## Блок 11А.31.1 — Frame и первые адаптивные экраны резервных копий (2026-10-01)
|
||||
|
||||
- История/настройки объединены существующим ReUI Frame/FramePanel, добавлены h1/краткая подпись, min-width и адаптивные отступы. Refresh и элементы настроек переносятся. Null status API становится «Неизвестно», а не offline/«недоступен».
|
||||
- Длинное имя файла имеет увеличенную колонку, перенос и title. На 320 px screenshot обнаружил скрытую кнопку «Ежемесячно», несмотря на отсутствие body overflow: SegmentedControl/время/дни теперь переносятся; E2E проверяет границы каждой кнопки частоты.
|
||||
- 9 PNG истории/настроек/create сохранены; desktop/390/320 просмотрены по ключевым состояниям. 3 keyboard/layout + 9 settings + 5 URL E2E, полный TypeScript/профильный ESLint прошли. Production frontend повторно прошёл после удаления повреждённого generated .next/dev/types/validator.ts; исходники этой ошибки не содержали.
|
||||
- S3/error/delete/restore/partial job визуальная приёмка ещё не завершена; backup scheduler cleanup и итоговая профильная регрессия впереди. Реальный RouterOS/PostgreSQL/S3 не проверен.
|
||||
- **Следующий блок 11А.31.2:** адаптивные состояния ошибок/диалогов и S3, затем scheduler cleanup/приёмка backups. Весь 11А ещё не принят.
|
||||
|
||||
| Экран | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| История | [PNG](ux-ui/screens/backups-history-desktop.png) | [390](ux-ui/screens/backups-history-mobile.png), [320](ux-ui/screens/backups-history-narrow.png) |
|
||||
| Настройки | [PNG](ux-ui/screens/backups-settings-desktop.png) | [390](ux-ui/screens/backups-settings-mobile.png), [320](ux-ui/screens/backups-settings-narrow.png) |
|
||||
| Создание | [PNG](ux-ui/screens/backups-create-desktop.png) | [390](ux-ui/screens/backups-create-mobile.png), [320](ux-ui/screens/backups-create-narrow.png) |
|
||||
|
||||
Референсы: [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp), [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp), [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp). Схема: источник → сводка → история/настройки → immutable цель → подтверждение API/неизвестный результат.
|
||||
|
||||
|
||||
## Блок 11А.31.2.1 — ошибки и подтверждения в узких диалогах (2026-10-01)
|
||||
|
||||
- Delete/restore описания переносят непрерывное имя файла. Предупреждение изменения рабочей конфигурации не обрезается line-clamp на 320 px. Ошибка удаления сохраняет цель; unknown restore оставляет disabled import/«Закрыть», Escape не объявляет отмену RouterOS.
|
||||
- 3 keyboard/dialog layout E2E прошли повторно после снятия clamp; профильный ESLint прошёл. 6 PNG ПК/390/320 сохранены, узкий restore просмотрен. Проверены границы диалога по ширине/высоте и отсутствие его внутреннего горизонтального overflow. Production frontend прошёл в 11А.31.1; в этом блоке только CSS отображения и layout тесты, полная сборка не повторялась.
|
||||
- **Следующий блок 11А.31.2.2:** S3/partial job/initial resource error визуальные состояния, затем backup scheduler cleanup (lock при setup/event сбоях, отделение результата от event/prune) и профильная приёмка. Backup scheduler обнаруженные дефекты пока не исправлены, весь backups/11А не принят. Реальные RouterOS/PostgreSQL/S3 остаются внешней приёмкой.
|
||||
|
||||
| Экран | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| Ошибка удаления | [PNG](ux-ui/screens/backups-delete-error-desktop.png) | [390](ux-ui/screens/backups-delete-error-mobile.png), [320](ux-ui/screens/backups-delete-error-narrow.png) |
|
||||
| Неизвестный импорт | [PNG](ux-ui/screens/backups-restore-unknown-desktop.png) | [390](ux-ui/screens/backups-restore-unknown-mobile.png), [320](ux-ui/screens/backups-restore-unknown-narrow.png) |
|
||||
|
||||
|
||||
## Блок 11А.31.2.2 — визуальные состояния S3, partial job и initial error (2026-10-01)
|
||||
|
||||
- Проверены ПК/390/320: S3 отказ доступа с актуальным backend receipt, partial upload при созданной локальной копии, первоначальный отказ истории. Unknown не превращается в empty/нулевые KPI, старая проверка S3 не остаётся успешной после подтверждённой ошибки. Добавлены 9 PNG.
|
||||
- Просмотр partial job выявил скрытую под Sheet ошибку. Ошибка и «Завершена с ограничениями» теперь показаны внутри формы; общий parent-owned scroll оставляет footer доступным. Результат после reload восстанавливается из terminal checkpoint, не зависит от прежнего состояния hook error. Locked запрос говорит о выбранной цели, не обещает будущее сохранение в текущую конфигурацию хранилища.
|
||||
- 9 states + 9 job E2E (повтор с reload partial), 3 layout регрессии предыдущим прогоном, 6 polling/result unit, TypeScript/профильный ESLint и production frontend прошли. ReUI audit checklist получен; установленная композиция/semantic tokens/typed API сохранены, клавиатура/scroll/ошибки проверены в профиле. Реальная DB/RouterOS/S3 остаётся внешней приёмкой.
|
||||
- **Следующий блок 11А.32:** backup scheduler cleanup — lock на всех выходах/setup failure, независимость журнала от подтверждённых файлов, отдельные prune/metadata сбои. Затем 11А.33 профильная локальная приёмка backups; весь 11А ещё не принят.
|
||||
|
||||
| Экран | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| S3 ошибка | [PNG](ux-ui/screens/backups-s3-error-desktop.png) | [390](ux-ui/screens/backups-s3-error-mobile.png), [320](ux-ui/screens/backups-s3-error-narrow.png) |
|
||||
| Partial job | [PNG](ux-ui/screens/backups-partial-job-desktop.png) | [390](ux-ui/screens/backups-partial-job-mobile.png), [320](ux-ui/screens/backups-partial-job-narrow.png) |
|
||||
| Initial error | [PNG](ux-ui/screens/backups-initial-error-desktop.png) | [390](ux-ui/screens/backups-initial-error-mobile.png), [320](ux-ui/screens/backups-initial-error-narrow.png) |
|
||||
|
||||
|
||||
|
||||
## Блок 11А.32 — достоверность плановых резервных копий (2026-10-01)
|
||||
|
||||
- Lock берётся до чтения настроек и освобождается через finally при любом выходе. Ошибка настроек/каталога не блокирует последующие запуски; параллельный вызов не повторяет настройку и создание.
|
||||
- Подтверждённые created/pruned сохраняются при ошибках журнала, S3, очистки и метаданных. Upload/prune/event/metadata ошибки раздельны. Очистка считает только подтверждённые удаления, сохраняет частичный счётчик при остановке.
|
||||
- При отказе записи lastRunAt повтор в том же слоте подавляется в текущем процессе. Это не межпроцессная/долговечная идемпотентность: рестарт и несколько экземпляров требуют отдельного решения. Зависший внешний запрос не ограничен новым timeout.
|
||||
- 8 новых scheduler/prune unit, весь backend test:backups, backend/contracts build и ESLint изменённых файлов прошли. Реальные PostgreSQL/RouterOS/S3 не проверены.
|
||||
- Обнаружено отдельное ограничение общего scheduler dispatcher: возвращённый snapshot с ошибками пока записывается как status=ok, отказ общего журнала может переобозначить запуск. Исправление общего журнала/статуса входит в 11Б; локальная приёмка backups не доказывает достоверность этого общего экрана.
|
||||
- **Следующий блок 11А.33:** общая профильная регрессия резервных копий и локальная приёмка 11А с явными внешними ограничениями.
|
||||
|
||||
|
||||
## Блок 11А.33 — локальная приёмка резервных копий и этапа 11А (2026-10-01)
|
||||
|
||||
- Общая регрессия backups: 69 основных + 2 исходных table/Filters + 28 source/context E2E, 27 frontend unit, весь backend test:backups прошли. Полный frontend TypeScript и production frontend/contracts build прошли; backend build и профильный ESLint прошли в 11А.32.
|
||||
- Проверены данные/unknown/partial, независимые зависимости, права, черновики расписания/S3, immutable job/checkpoint, serial polling, удаление/restore/download, URL/Filters, клавиатура и ПК/390/320. 24 PNG сохранены, узкий partial job повторно просмотрен; обновлённые снимки от последней регрессии включены в коммит.
|
||||
- Резервные копии приняты в границах локального UI/API/DI профиля. Пользователи приняты в 11А.8, контейнеры в 11А.13, сертификаты в 11А.24. Этап 11А завершён локально; общая регрессия всех разделов приложения относится к этапу 12.
|
||||
- Внешняя приёмка: PostgreSQL/Portal/JWT/RouterOS/ACME/S3, физическое восстановление и versioned S3 deletion не доказаны фикстурами. Jobs/checkpoints и scheduler lock не обеспечивают долговечность/межпроцессную идемпотентность. Исторические S3 bucket/endpoint не хранятся. PEM/private key import/export не реализованы. Эти ограничения не скрыты локальными результатами.
|
||||
- Общий scheduler dispatcher пока может записать snapshot с ошибками как ok; это явный долг этапа 11Б, а не подтверждённая успешность планового запуска на общем экране.
|
||||
- **Следующий блок 11Б.1:** карта оставшихся разделов и достоверность общего scheduler runner: collector результат отдельно от журнала/событий, без второй записи и ложного ok.
|
||||
@@ -0,0 +1,355 @@
|
||||
# Этап 11Б: сбор данных, оповещения и настройки
|
||||
|
||||
ReUI PRO/base-nova; существующие Frame, Data Grid v9, KpiStatGrid, Sheet. Последовательные блоки, локальные коммиты без push. Этап 11А принят локально в 11А.33.
|
||||
|
||||
| Область | Референс | Схема и результат |
|
||||
| --- | --- | --- |
|
||||
| Сбор данных / scheduler | [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp), [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Источник → свежесть → настройки/журнал → подтверждённый запуск |
|
||||
| Оповещения | [Stats 12](https://reui.io/preview/base/stats-12?ref=mcp), [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp) | Правило → фактическое состояние → адресат → подтверждённая отправка |
|
||||
| Интеграции / настройки | [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp) | Секция → сохранённое состояние/черновик → проверка соединения → результат |
|
||||
| Релизы | [List 9](https://reui.io/preview/base/list-9?ref=mcp) | Текущая сборка → доступные сведения → понятный переход |
|
||||
|
||||
[Источник / права] → [Независимые подтверждённые данные]
|
||||
↓
|
||||
[Черновик настроек] → [Действие] → [API receipt]
|
||||
↓ ↓
|
||||
[Ошибка/unknown] [Снимок результата]
|
||||
└──────→ [Отдельное обновление]
|
||||
|
||||
| Порядок | Раздел / исходные файлы | Выявленная проблема | Точка завершения |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | backend scheduler.ts / routes/scheduler.ts | Безусловный ok и повторная запись после journal failure | Один collector/одна запись, partial/fatal явно сохранены (11Б.1) |
|
||||
| 2 | lib/scheduler-run-snapshot.ts, data-collection/page.tsx | PostgreSQL JSONB объект обрабатывается как строка | Object и legacy JSON отображаются без падения |
|
||||
| 3 | data-collection/page.tsx | Общий Promise.allSettled задерживает быстрые зависимости; refresh сбрасывает drafts; числа нормализуются; run-now receipt игнорируется | Strict API, независимые known/error/time, сохранённые формы, lock/права/контекст |
|
||||
| 4 | alerts/page.tsx / routes/alerts.ts | Зависимости/CRUD/отправка требуют профильного аудита | Правило/получатель/частичный результат/без повторной отправки при неизвестности |
|
||||
| 5 | settings/page.tsx, Evolution/NetFlow интеграции | Секреты, сохранение, test/refresh и сообщения требуют аудита | Проверка сохранённой конфигурации, черновик и подтверждённый результат раздельны |
|
||||
| 6 | releases/page.tsx | Проверить фактические сведения сборки/переходы | Семантическая оболочка, пустой/unknown, ПК/390/320 |
|
||||
| 7 | probes расписание, общая приёмка | Осталось после этапа 10 | Настройки расписания/результат, профильная регрессия/снимки/build |
|
||||
|
||||
Границы: данные наблюдения offline/down не заменять ошибкой сборщика; записанные samples и доставка Telegram — разные результаты. Не менять сетевые правила и права. Локальные DI/HTTP фикстуры не доказывают PostgreSQL транзакции, RouterOS, реальную доставку Telegram/Portal и долговечную идемпотентность.
|
||||
|
||||
## Блок 11Б.1 — общий scheduler runner и карта оставшихся разделов (2026-10-01)
|
||||
|
||||
- Collector вызывается один раз, результат записывается одной попыткой. Fatal/errors snapshot даёт status=error с сохранёнными счётчиками/снимком; partial отмечается текстом «Завершено с ограничениями». Наблюдаемое down/offline само по себе не является ошибкой выполнения коллектора. Skipped/not-due не порождают событие о выполненной работе.
|
||||
- Ошибки event/hook отделены от результата. Отказ run journal не создаёт вторую запись; выдаётся явная ошибка подтверждения журнала с предупреждением о повторных операциях. Ручной API возвращает ok=false/result для partial и отдельный statusError при отказе чтения статуса после подтверждённого запуска.
|
||||
- 9 runner + 4 HTTP теста, backend/contracts build и ESLint изменённых файлов прошли. Общий npm --prefix backend test завершился с кодом 0; DB-зависимые тесты пропущены из-за недоступного PostgreSQL, это не проверка транзакций с реальной DB.
|
||||
- Карта/референсы/схема оставшегося этапа сохранены в ux-ui-stage-11b.md. UI сбора данных пока не читает новый receipt строго; JSONB resultJson ошибочно ожидается строкой (raw.trim может выбросить ошибку). Следующий небольшой блок исправляет совместимость JSONB/legacy JSON; полные reader/state/операции — после него.
|
||||
- **Следующий блок 11Б.2:** отображение object/legacy snapshot в общем журнале без падения, затем 11Б.3 строгие API и независимые состояния/черновики сбора данных. Этап 11Б/12 не принят, реальные DB/RouterOS/Telegram/Portal остаются внешней приёмкой.
|
||||
|
||||
|
||||
## Блок 11Б.2 — JSONB и legacy snapshot общего журнала (2026-10-01)
|
||||
|
||||
- resultJson читается как unknown: PostgreSQL JSONB объект и старый строковый JSON проходят общий decoder. Больше нет raw.trim на объекте. Проверены версия/известная задача/время/обязательные поля верхнего уровня; backup counts и новые diagnostics валидируются без подстановки нулей.
|
||||
- Снимок другого job не отображается в выбранной записи. Некорректный/неподдерживаемый снимок показывает Alert «Снимок недоступен», отсутствие снимка остаётся отдельным состоянием. Полная валидация вложенных строк остальных коллекций ещё относится к строгому API следующего блока.
|
||||
- 4 unit, 4 E2E object/legacy/invalid/foreign, TypeScript и production frontend/contracts build прошли. ESLint parser/DTO/tests прошёл. На общей странице остаются 2 исходные set-state-in-effect ошибки и 2 warnings: отдельный lint HEAD через stdin подтвердил ту же исходную базу; их исправление входит в reader/context блока 11Б.3.
|
||||
- Первый E2E прогон использовал неполную GeoIP фикстуру и падал в старом GeoipSettingsSection. Фикстура уточнена; NetFlow зависимость вынесена в явный HTTP 503 вместо неверного success DTO. Повторные 4 E2E прошли без pageerror. Строгий GeoIP reader/guard также необходим в 11Б, реальная интеграция не принята.
|
||||
- ReUI audit checklist получен; существующий Alert/вариант warning, текстовый рендер и структура сохранены. Весь раздел сбора данных ещё не прошёл визуальную/доступностную приёмку.
|
||||
- **Следующий блок 11Б.3:** строгие scheduler/collector API, независимые reader states, dirty drafts и контекст/права; новый run-now receipt пока не обрабатывается страницей строго.
|
||||
|
||||
|
||||
## Блок 11Б.3.1 — строгий API-клиент планировщика (2026-10-01)
|
||||
|
||||
- Добавлен shared/api/scheduler.ts: status/runs/run-now/refresh проверяют DTO, известные ключи, дубли, обязательные false/zero/null, время PostgreSQL и согласованность receipt. Фильтр журнала отклоняет записи чужой задачи. Snapshot остаётся unknown в каталоге до отдельного декодирования.
|
||||
- Manual POST принимает только receipt выбранной задачи; успешный status с fatal/partial snapshot отклоняется. Partial files, eventError и statusError остаются отдельными подтверждёнными полями. Потерянный/неверный ответ не вызывает повторный POST. Caller cancellation и 30s срок сохранены; timeout POST не доказывает отмену backend.
|
||||
- 5 новых API unit + 4 snapshot unit, полный TypeScript и ESLint новых файлов прошли. Frontend build прошёл в 11Б.2; этот блок добавляет пока не подключённый API-модуль, UI/backend не менялись.
|
||||
- Клиент ещё не подключён к странице: её старые settings/receipts/locks/context/lint ограничения сохраняются. Это основа миграции, не приёмка операций сборщика. Вложенные коллекции остальных snapshot ещё требуют строгого decoder.
|
||||
- **Следующий блок 11Б.3.2:** GeoIP strict API/receipt против выявленного malformed crash; затем 11Б.3.3 подключение scheduler и независимые reader/context/dirty states.
|
||||
|
||||
|
||||
## Блок 11Б.3.2 — строгий GeoIP API против malformed crash (2026-10-01)
|
||||
|
||||
- Существующие GeoIP schemas подключены к GET/PUT/update; неполный status не попадает в UI state. Ответ проверяет ready/loaded и время, PUT подтверждает отправленные поля, update сверяет ok с partial/fatal/errors и счётчиками. False/null/zero не заменяются defaults, partial download остаётся фактом.
|
||||
- Выходная ошибка понятна пользователю, без сырого Zod JSON. Запросы имеют caller cancellation/30s срок; неверный/потерянный POST не повторяется автоматически. Timeout не доказывает отмену backend.
|
||||
- 4 GeoIP API unit + 5 scheduler API unit, 6 E2E GeoIP/snapshot, профильный ESLint и production frontend/contracts build прошли. E2E fixture GeoIP приведена к полному существующему DTO. Первую проверку toast уточнили для двух dev StrictMode вызовов; повтор прошёл без pageerror.
|
||||
- UI GeoIP/NetFlow пока сохраняет прежние defaults/dirty/context/mutation ограничения и требует отдельной приёмки; strict reader исправляет конкретное падение, не доказывает реальные загрузки mmdb или готовность интеграции.
|
||||
- **Следующий блок 11Б.3.3.1:** изоляция контекста страницы сбора и исходные lint ошибки; затем подключение strict scheduler/settings readers, независимые состояния и черновики.
|
||||
|
||||
|
||||
## Блок 11Б.3.3.1 — контекст и гонки чтения общего журнала (2026-10-01)
|
||||
|
||||
- Страница ждёт hydration источника; mode/backend задают ключ нового содержимого. При размонтировании читатель становится inactive, старые запросы отменяются и их callbacks не обновляют UI/не запускают последующее чтение.
|
||||
- Каждая загрузка отменяет предыдущую и имеет revision/30s deadline; все шесть GET используют общий AbortSignal. Поздний success/error после смены фильтра не заменяет актуальные строки/ошибки/busy. Promise.allSettled пока сохраняется: независимое появление быстрых зависимостей и dirty drafts ещё не реализованы.
|
||||
- Сброс раскрытых строк перенесён в обработчик фильтра; эффектные synchronous setState и ненужный stats useMemo устранены. ESLint страницы и нового теста прошёл без прежних 2 errors/2 warnings.
|
||||
- 2 новых filter-race + 6 GeoIP/snapshot E2E, production frontend/contracts build со встроенным TypeScript прошли. Отдельные E2E смены backend/mode и поздних мутаций ещё нужны в следующем блоке. Старые mutations не получили новой идемпотентности/lock; их приёмка не заявлена.
|
||||
- **Следующий блок 11Б.3.3.2:** подключение strict scheduler runs и known/error/time журнала; затем независимые settings/status readers, dirty drafts, действия/права и source E2E. GeoIP/NetFlow формы и вся 11Б ещё не приняты.
|
||||
|
||||
|
||||
## Блок 11Б.3.3.2 — подтверждённая история и свежесть журнала (2026-10-01)
|
||||
|
||||
- Strict listSchedulerRuns подключён к странице. Missing/duplicate/foreign/invalid DTO не становится пустой историей; первоначальная ошибка даёт unknown/KPI —, подтверждённое empty даёт 0. Ответные ошибки API теперь понятные, без сырого Zod JSON.
|
||||
- Фоновый сбой сохраняет строки и прежнее время получения; Alert объясняет необходимость обновления. Смена job filter сбрасывает только историю/раскрытие/свежесть предыдущего среза: старые строки не выдаются за новый фильтр. Browser receivedAt явно подписан временем получения истории, не временем выполнения job.
|
||||
- Добавлены 5 history E2E: initial API/malformed, background error, known empty, смена среза. Общие 13 data-collection E2E, 5 scheduler API unit, ESLint страницы/API/теста и production frontend/contracts build прошли. Первые проверки KPI уточнены по реальной вложенности установленного KpiStatGrid; повтор прошёл.
|
||||
- Remaining: быстрый журнал пока ждёт остальных пяти зависимостей; status KPI ещё использует uptime/default drafts. Их независимость/known состояния — следующий блок. Forms/mutations/права/весь 11Б не приняты.
|
||||
- **Следующий блок 11Б.3.3.3:** независимое получение scheduler status/runs и достоверные status KPI; затем strict settings readers, dirty drafts и операции.
|
||||
|
||||
|
||||
## Блок 11Б.3.3.3 — независимые scheduler status/runs и достоверные KPI (2026-10-01)
|
||||
|
||||
- Strict getSchedulerStatus подключён как отдельный источник. Status/runs публикуются сразу по своим ответам, до завершения пяти settings зависимостей; медленный/ошибочный uptime не задерживает подтверждённую сводку и историю.
|
||||
- KPI enabled/running считает подтверждённые jobs, не переключатели/default drafts. Unknown показывает —; backend zero/false сохраняется. Фоновая ошибка оставляет последний статус и прежнее browser receivedAt с Alert обновления. Таблица получает metadata из отдельного status; это не атомарный снимок всех настроек.
|
||||
- 13 общих data-collection E2E и 4 status E2E (повтор после уточнения fixture), ESLint страницы/теста и production frontend/contracts build со встроенным TypeScript прошли. Проверен быстрый status/history при задержанном uptime, initial API/malformed, background failure.
|
||||
- Первый status fixture по ошибке включал все интеграции generic enabled=true, выявив старый malformed Evolution snapshot crash в sidebar. Fixture ограничена выключенной интеграцией; этот отдельный дефект Evolution reader включён в оставшийся scope 11Б, исправление не заявлено.
|
||||
- Остальные settings всё ещё обрабатываются общим Promise.allSettled и могут сбрасывать drafts; strict settings readers/dirty state и операции впереди. GeoIP/NetFlow/общий UI ещё не принят, реальные DB/RouterOS/Portal остаются внешней приёмкой.
|
||||
- **Следующий блок 11Б.3.3.4:** strict collector settings API с реальными различиями DTO; затем подключение независимых settings readers и dirty drafts, mutation/RBAC/source проверки.
|
||||
|
||||
|
||||
## Блок 11Б.3.3.4 — строгие readers настроек сборщиков (2026-10-01)
|
||||
|
||||
- Добавлен shared/api/collector-settings.ts: traffic/REST ping/uptime/internet path читаются по своим реальным GET DTO. False/zero/null сохраняются, missing/invalid не нормализуется defaults; PostgreSQL время приводится к тому же ISO instant.
|
||||
- REST ping не получает выдуманный retentionDays. Traffic/internet path требуют фактический retention; uptime требует отдельные resources/ping/speed и интервалы. Вложенная scheduler metadata uptime не используется: status уже получает отдельный строгий reader. Сертификаты имеют существующий strict getCertificateRenewSettings, его следует переиспользовать.
|
||||
- 10 новых API unit, полный TypeScript и ESLint новых файлов прошли. Production frontend прошёл в 11Б.3.3.3; этот блок добавляет пока не подключённый модуль, UI/backend не менялись.
|
||||
- Current UI всё ещё использует старые settings calls. Нельзя считать формы подтверждёнными или защищёнными от default submit по этим unit: подключение readers/known/error/time/dirty states, synchronous locks, RBAC и unknown mutation receipt ещё впереди. Generic CollectorSettingsDto на странице ошибочно требует retention у REST ping; при подключении исправить типы по отдельным DTO.
|
||||
- **Следующий блок 11Б.3.3.5:** подключить четыре strict settings reader и существующий certificate reader, независимые состояния/свежесть и dirty drafts; затем операции/права/source E2E. Evolution malformed snapshot crash и GeoIP/NetFlow формы остаются в scope 11Б.
|
||||
- На контрольной точке недельный лимит использован на 99%, пятичасовой на 36%. Проверенные блоки сохранены; для продолжения читать текущую квоту и этот журнал.
|
||||
|
||||
|
||||
## Блок 11Б.3.3.4.1 — проверка каталога Evolution (2026-10-01)
|
||||
|
||||
- Каталог Evolution проверяется до записи в состояние: обязательные коллекции, поля строк, дата снимка, числовые счётчики и уникальность идентификаторов. Неполный HTTP 200 больше не обрушает боковую навигацию; в настройках EvoBGP отображается понятная ошибка.
|
||||
- Подтверждённые пустые коллекции, false и zero сохраняются. Decoder совместим с DTO backend; неизвестные значения backend не переосмыслены. Последний снимок при ошибке пока не сохраняется: независимые состояния, свежесть и защита от гонок Evolution остаются в объёме этапа.
|
||||
- Прошли 3 unit, 1 браузерный тест через обычные API-пути с подменой HTTP, ESLint изменённых файлов и production frontend/contracts build со встроенным TypeScript. В браузере проверены доступность журнала, переход в настройки EvoBGP и отсутствие pageerror при malformed каталоге. Реальный Evolution Portal не проверен.
|
||||
- Следующий основной блок остаётся 11Б.3.3.5: подключение strict settings readers, независимые known/error/time и dirty drafts. Также выявлено: Evolution testConnection пока принимает любой успешный HTTP вместо подтверждения ok=true; исправление и профильная проверка ещё впереди.
|
||||
- На завершении пятичасовой лимит использован на 42%, недельный показывает 100%. Новый блок не начат; изменения сохранены локально без push.
|
||||
|
||||
## Блок 11Б.3.3.4.2 — подтверждение проверки EvoBGP (2026-10-01)
|
||||
|
||||
- testConnection проверяет явное ok=true: HTTP 200 с false, пустым или некорректным receipt не становится сообщением об установленном соединении. Ошибка возвращается существующей форме, без повторного POST.
|
||||
- Прошли unit для true/false/missing/null/неверных типов, ESLint изменённых файлов и полный TypeScript. Два профильных браузерных теста прошли; после расширения новый тест повторно проверил false → ручная повторная проверка → true и ровно один запрос на каждое нажатие. HTTP-подмена не доказывает соединение с реальным Portal.
|
||||
- Полная production сборка прошла в предыдущем блоке 11Б.3.3.4.1; текущая маленькая правка проверена TypeScript и браузером. Общие settings/RBAC/dirty/context и сохранение последнего каталога остаются впереди. Основная точка продолжения — 11Б.3.3.5.
|
||||
- Блок сохранён отдельным локальным коммитом без push. Процент недельной квоты округлён до 100%, ordinaryUsageAllowed при начале блока оставался true.
|
||||
|
||||
## Блок 11Б.3.3.5 — независимые настройки и черновики (2026-10-03)
|
||||
|
||||
- Подключены четыре строгих settings reader и существующий certificate reader. У каждого источника независимые known/error/browser receivedAt; медленный uptime не задерживает остальные настройки. Ошибка сохраняет последние подтверждённые данные и время, неполный DTO не подменяется defaults.
|
||||
- Изменённые пользователем интервалы и дополнительные поля сохраняются при обновлении. Состояние источника сбрасывается существующим remount; abort/revision защищают поздние ответы. Uptime scheduler metadata больше не переписывает чужие переключатели. REST ping использует собственный DTO без выдуманного retention.
|
||||
- Неизвестные настройки показывают —/пустые отключённые поля, доступность записи пока консервативно зависит от всех пяти подтверждённых источников. GeoIP расписание отмечено внешне управляемым через NetFlow. Формат/композиция установленной Data Grid сохранены; async metadata объявляется role=status.
|
||||
- Прошли 15 профильных E2E (4 новых settings + история/status/race), ESLint, полный TypeScript и production frontend/contracts build. ReUI audit checklist получен; изменения затрагивают данные/состояния, vendor props и тема не менялись. Реальные DB/RouterOS/ACME не проверены.
|
||||
- Следующий блок 11Б.3.3.6: строгие mutation receipts/проверка ввода, точечные PUT вместо записи всех настроек переключателем, синхронные locks/права и сброс dirty только по подтверждённому результату. Полная приёмка 11Б ещё впереди.
|
||||
|
||||
## Блок 11Б.3.3.6.1 — строгие PUT настроек (2026-10-03)
|
||||
|
||||
- Четыре settings PUT проверяют минимумы/целые числа до запроса и реальные backend receipt ok=true/settings после него. Каждый переданный параметр обязан совпасть с подтверждённым. Пустой patch/unknown fields/неверные числа отклоняются; timeout/ошибка/неверный receipt не вызывают повтор.
|
||||
- Прошли 14 GET/PUT unit, ESLint и полный TypeScript. Первоначальный unit assertion уточнён под две формулировки подтверждения; повтор прошёл. Новый API пока не подключён к операциям страницы; certificate PUT переиспользуется с отдельной проверкой echo на следующем шаге.
|
||||
- Далее 11Б.3.3.6.2: точечная запись dirty полей и выбранного переключателя, locks/права, сброс dirty по подтверждению и профильные E2E.
|
||||
|
||||
## Блок 11Б.3.3.6.2 — точечное сохранение и права (2026-10-03)
|
||||
|
||||
- Переключатель отправляет только флаг выбранного сборщика; сохранение отправляет только dirty поля. Все числовые поля выбранного плана проверяются до первой записи без parseInt/default/clamp. Неполные данные других источников не мешают точечной операции.
|
||||
- Строгие receipts подключены; certificate PUT дополнительно сверяет echo. Подтверждённая часть очищает dirty и обновляет сохранённые данные, отказ/403/неизвестный receipt сохраняют draft. Частичный успех показан отдельно и при ручном повторе не отправляется снова.
|
||||
- Синхронный lock предотвращает повтор; pending GET инвалидируется перед записью, поздний ответ не отменяет подтверждённый переключатель. Изменение источника/unmount прекращает публикацию и последующие записи batch, но не гарантирует отмену уже полученной backend операции. Права соответствуют существующим backend permissions каждого endpoint.
|
||||
- Прошли 26 E2E (15 settings + 11 history/status/race), ESLint и production frontend/contracts build. Проверены malformed/mismatched receipts, selective PUT, partial failure, dirty, fractional/no HTTP, lock, old GET, HTTP 403 и read-only claims. Реальный JWT/DB/RouterOS/ACME не проверен.
|
||||
- Далее 11Б.3.3.6.3: подключить строгие run-now/refresh receipts, общий lock и права для POST, отдельно показать skipped/partial/event/status failures; затем source E2E/визуальная приёмка страницы. Этап 11Б не завершён.
|
||||
|
||||
## Блок 11Б.3.3.6.3 — подтверждённые ручные запуски (2026-10-03)
|
||||
|
||||
- Строгие scheduler run-now/refresh подключены вместо raw POST. Показаны подтверждённый запуск, skipped/not-due и partial; event/status failure отделены от результата задачи. Неверный/чужой receipt не становится успехом и не повторяет POST, сообщает неизвестность результата и необходимость обновить журнал.
|
||||
- Run-now/refresh используют общий синхронный lock с PUT, права mm:settings:admin и сохранённые настройки без отправки dirty draft. Неизвестная/running задача не запускается из UI. Поздние callbacks после unmount/source change не публикуются; backend применение уже начатой операции не отменяется.
|
||||
- Прошли 26 E2E (10 operations + 16 settings), ESLint и production frontend/contracts build. Проверены partial/event/status, false receipt/foreign snapshot, lock и mode change; смена режима также прекращает оставшийся batch PUT. Предыдущие 11 status/history/race прошли в 11Б.3.3.6.2; новый блок не меняет readers.
|
||||
- Далее 11Б.3.3.7: backend source E2E и визуальная/адаптивная приёмка scheduler. GeoIP/NetFlow формы и Evolution provider, alerts/releases/probe scheduling остаются в объёме этапа 11Б; их общий интерфейс пока не принят.
|
||||
|
||||
## Блок 11Б.3.3.7 — локальная приёмка scheduler (2026-10-03)
|
||||
|
||||
- Проверены обычные HTTP-пути со сменой backend: 6 source E2E для позднего GET/PUT/run-now, успех и отказ старого источника не меняют новый. Source тесты вынесены в отдельную конфигурацию :3101/local; общий профиль остаётся :3100/same-origin.
|
||||
- 46 основных профильных E2E проверены: 39 прошли сразу, 7 KPI assertions требовали обновления селектора после переноса подписей; 9 history/status повторно прошли с устойчивой привязкой к установленному FramePanel. Отдельно 6 source E2E прошли. Новая структура не меняет unknown/zero значения.
|
||||
- ПК/390/320 проходят без горизонтального переполнения body; сохранены 6 снимков docs/ux-ui/screens/data-collection*.png, визуально просмотрены 320 и ПК. KPI тексты переносятся, unknown сбор не помечается зелёным успехом. Кнопка «Сохранить изменения» помещается на 320, доступное имя сохранено. Удалена техническая ссылка Preview из текста NetFlow.
|
||||
- ESLint новых/изменённых файлов и production frontend/contracts build прошли; две последние правки текста дополнительно проверены 3 responsive E2E с обновлением снимков. ReUI композиция/тема сохранены, labels и async объявления есть. Это приёмка scheduler/settings/history, а не всей страницы интеграций.
|
||||
- Следующий блок 11Б.3.4: GeoIP/NetFlow формы — known/error/dirty/source/partial и операции. Evolution provider, alerts/releases/probe scheduling и итоговая приёмка 11Б остаются впереди. PostgreSQL, RouterOS, Portal, MaxMind download и JWT не доказаны HTTP-фикстурами.
|
||||
|
||||
## Блок 11Б.3.4.1 — права GeoIP (2026-10-03)
|
||||
|
||||
- Выявлен и устранён fallback GeoIP в mm:dashboard:read: GET /api/geoip требует mm:traffic:read, PUT /api/geoip и POST /api/geoip/update — mm:traffic:write, как соседние NetFlow настройки. Catch-all и права сетевых операций не менялись.
|
||||
- Это целевое ужесточение: пользователя с одним dashboard:read больше недостаточно для чтения/изменения GeoIP. Traffic write/admin наследуют read; settings:admin не даёт произвольных traffic прав по существующей модели. AUTH_REQUIRED=false сохраняет локальный режим.
|
||||
- Подписанные JWT/Fastify inject проверяют GET/PUT/POST с пятью наборами прав: reader не вызывает mutation handler, traffic writer/admin допускаются, без JWT 401. Первоначальное ожидание глобальных прав settings:admin исправлено по реальному hasPermission; повтор прошёл. Проверка добавлена в backend test:geoip.
|
||||
- Backend permissions unit, JWT gate, ESLint и backend build прошли. Нет БД/скачивания MaxMind/производственного Portal в этих тестах. UI ещё использует старую форму; далее 11Б.3.4.2 — known/error/dirty/права и partial outcome GeoIP.
|
||||
|
||||
## Блок 11Б.3.4.2 — достоверная форма GeoIP (2026-10-03)
|
||||
|
||||
- GeoIP вынесен из NetFlow в отдельный раздел с backend key/remount, abort/revision и active guards. Независимые read/operation ошибки, browser receivedAt и последние данные сохраняются. Unknown не выдаётся за отсутствующие базы; формы/действия до подтверждения или без traffic write отключены.
|
||||
- Dirty сохраняется при GET и после ручного обновления; PUT принимает фактический интервал с точностью до секунды без rounding/default/clamp, receipt очищает dirty только после подтверждения. Синхронный lock блокирует PUT/POST/refresh во время операции и инвалидирует pending GET.
|
||||
- Частичный update показывает скачанное/без изменений/bytes вместе с ошибками, не сообщает полного успеха. Skipped отдельно. Неизвестный POST не повторяется; новое обновление требует явного действия после проверки журнала/баз. Guard живёт в текущем разделе, не является durable backend идемпотентностью.
|
||||
- Прошли 10 новых GeoIP E2E, 2 ранее существовавших malformed tests, ESLint и production frontend/contracts build. После добавления explicit unknown guard профильный POST тест повторно прошёл. Проверены fractional interval, invalid/no HTTP, false/unknown, partial, dirty, lock и reader claims; signed JWT gate принят в 11Б.3.4.1.
|
||||
- NetFlow сохраняет собственные известные ограничения; его synchronous-effect lint исправлен очередью microtask, не считать это защитой от поздних ответов. Далее 11Б.3.4.3 — GeoIP source/визуальная приёмка, затем strict NetFlow API/форма. Реальная загрузка mmdb/DB/Portal не проверена.
|
||||
|
||||
## Блок 11Б.3.4.3 — локальная приёмка GeoIP (2026-10-03)
|
||||
|
||||
- 6 backend source E2E проверили поздние GET/PUT/POST, success/error старого адреса не меняют новый раздел. POST assertions уточнены для сообщения с фактическими счётчиками; оба POST source теста повторно прошли.
|
||||
- 13 основных GeoIP E2E (10 сценариев + ПК/390/320) прошли, сохранены 3 снимка docs/ux-ui/screens/geoip*.png. На телефоне бейджи перенесены из headerRight в переносимую строку: заголовок больше не сжимается и не скрывается. Кнопка разрешения нового POST имеет короткую подпись и полное доступное имя.
|
||||
- Первоначальный overflow assertion выявлял также штатную отрицательную границу Frame (+1px); допуск ограничен 2px, body не переполняется. Снимок 320 просмотрен и обнаруженное фактическое сжатие заголовка исправлено, тесты повторены. Это не утверждение о всей NetFlow панели.
|
||||
- ESLint и production frontend/contracts build прошли. Backend JWT gate/permissions/build приняты в 11Б.3.4.1; реальные Portal/DB/mmdb не проверены. Unknown guard текущего раздела не долговечен между reload/navigation.
|
||||
- Далее 11Б.3.4.4: строгие NetFlow settings/keys/export/purge API и backend эффекты. Выявлены создание ключей в GET host-files, выдача конфигов с private key по traffic read и маскировка успешного purge ошибкой события; также требуется проверка атомарности purge. UI NetFlow ещё не принят.
|
||||
|
||||
|
||||
Продолжение 2026-10-03: завершён 11Б.3.4.4.1 (строгие NetFlow API, 5 unit и 3 collector/probes E2E, typecheck/ESLint). Следующий блок — 11Б.3.4.4.2: backend экспорт/права и подтверждение сохранения отдельно от запуска listener. Purge и форма ещё требуют доработки.
|
||||
|
||||
Завершён 11Б.3.4.4.2: private export требует traffic write, GET не создаёт ключи, PUT отделяет сохранение от ошибки запуска listener. HTTP/JWT, backend build, lint и permissions прошли. Далее 11Б.3.4.4.3: конкурентное создание ключей/выборочные patch; purge и UI ещё не приняты.
|
||||
|
||||
Завершён 11Б.3.4.4.3: выборочная запись NetFlow patch и условная установка host keys, свежая подтверждённая пара; DI гонка/HTTP/JWT/build/lint прошли. Реальная PG гонка не проверена. Далее 11Б.3.4.4.4 — атомарность purge и частичные результаты.
|
||||
|
||||
Завершён 11Б.3.4.4.4: 6 таблиц/counters purge в общей транзакции, отдельные partition/listener/event warnings и nullable размер файлов. DI/HTTP/API/typecheck/build/lint прошли; реальный PG purge не запускался. Следующий шаг 11Б.3.4.4.5 — форма NetFlow и подтверждённые/частичные/неизвестные операции.
|
||||
|
||||
Завершён 11Б.3.4.4.5: форма NetFlow known/dirty/rights/lock, selective PUT, partial outcomes и review после unknown POST; 12 E2E/form unit/typecheck/lint/production build прошли. Далее 11Б.3.4.4.6 — source/adaptive приёмка, затем общий контракт IP/CIDR/DNS.
|
||||
|
||||
Завершён 11Б.3.4.4.6: 10 NetFlow backend source E2E, 3 responsive, 6 снимков (320 и ПК просмотрены), регрессия GeoIP/collector прошли. Далее 11Б.3.4.4.7: общий IP/CIDR/DNS ввод/фактический порт и отказ конкурентному purge вместо очереди. Затем приёмка NetFlow и Evolution.
|
||||
|
||||
Завершён 11Б.3.4.4.7.1: конкурентный purge получает 409 до удаления, неподтверждённый session lock соединения исключается из пула; DI/backend/build/lint/conflict E2E прошли. Реальный PG overlap не проверен. Далее 11Б.3.4.4.7.2 — общий IP/CIDR/DNS контракт и фактические порты.
|
||||
|
||||
Завершён 11Б.3.4.4.7.2: общий NetFlow IP/CIDR/DNS/ports patch, draft и backend проверяют его; инструкция использует фактический порт. 14 E2E, unit/HTTP/JWT, lint и оба builds прошли. Далее 11Б.3.4.4.7.3 — согласованный host export/маска, затем приёмка NetFlow и Evolution.
|
||||
|
||||
Завершён 11Б.3.4.4.7.3: host export из одного снимка, фактические mask/WG/IPFIX ports, strict keys/peers и безопасные однострочные комментарии. Builder/key/HTTP/JWT/build/lint прошли без запуска host/RouterOS. Далее 11Б.3.4.4.8 — приёмка NetFlow; затем 11Б.3.5 Evolution. Нестандартные prefix allocator не приняты.
|
||||
|
||||
Локальная приёмка NetFlow 11Б.3.4.4.8: 19 основных и 10 source E2E, backend JWT с purge, backend/frontend builds и API tests прошли в описанных блоках. Дублирующий purge Settings заменён переходом к единой панели (link E2E/typecheck). Исходные lint ошибки Settings остаются до его блока. Внешние PG/WG/RouterOS/Portal/нестандартный IPv4 prefix не приняты. Далее 11Б.3.5.1 — строгие Evolution settings/save/test API и затем provider/форма.
|
||||
|
||||
Завершён 11Б.3.5.1 — contracts/Evolution strict settings/save/test API: 3 unit, contracts build/typecheck/lint прошли. Новый PUT helper пока не подключён (backend старый receipt). Далее 11Б.3.5.2 backend selective save/подтверждение, затем provider и форма.
|
||||
|
||||
Завершён 11Б.3.5.2: Evolution backend selective RETURNING save/public receipt и проверка items upstream/test; DI HTTP/JWT, backend build/lint прошли. Старый provider совместим с публичными полями, ещё не мигрирован. Далее 11Б.3.5.3 — provider known/error/time/source; затем форма и upstream catalog validation.
|
||||
|
||||
Завершён 11Б.3.5.3.1: Evolution provider known/error/time/readers/source/strict receipts, статус Settings; 8 provider (один selector повторён), 2 прежних и 6 source E2E, lint/typecheck/production build прошли. Форма/consumer mocks ещё не приняты. Далее 11Б.3.5.3.2 — upstream catalog strict/unknown counts; затем 11Б.3.5.4 форма/consumers.
|
||||
|
||||
Завершён 11Б.3.5.3.2: strict upstream catalog, nullable ASN/community counts, unknown «—» вместо 0. Parser/aggregation/HTTP/JWT/build/typecheck/lint и provider/counts E2E прошли; locator inline details исправлен. Реальный Evolution/PG не принят. Далее 11Б.3.5.4.1 — форма Evolution dirty/rights/lock/key clear/source.
|
||||
|
||||
Завершён 11Б.3.5.4.1: отдельная форма Evolution dirty/rights/lock/clear confirmation/source; 17 основных, 8 source и 3 responsive E2E, typecheck/lint/build прошли. 6 снимков, 320/ПК/clear просмотрены. Общие Settings и live consumer mocks ещё не приняты. Далее 11Б.3.5.4.2 — consumers/sidebar unknown/disabled/no fallback.
|
||||
|
||||
| Блок | Референс | Реализованная схема |
|
||||
| --- | --- | --- |
|
||||
| 11Б.3.5.4.1 Evolution | [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp) | Статус и свежесть → поля → сохранить / проверить → подтверждённый результат; удаление ключа → подтверждение → результат |
|
||||
|
||||
Завершён 11Б.3.5.4.2: live catalog consumers/sidebar/Filters без demo fallback, unknown/disabled/last snapshot и current details; 25 E2E, typecheck/профильный lint/build прошли. 3 community screenshots, 320/ПК просмотрены. Sidebar sync-effect baseline error и Filters unused warnings описаны в журнале. Далее 11Б.3.5.5 — HTTP/JWT catalog и приёмка Evolution.
|
||||
|
||||
Завершён 11Б.3.5.5: Evolution catalog DI HTTP/JWT, один settings snapshot, backend test/build/lint прошли. Evolution принят локально в границах предыдущих form/provider/source/consumer/adaptive проверок; реальный upstream/PG/Portal/RouterOS не принят. Далее 11Б.3.6.1 — достоверные общие Settings без фиктивных сохранений/API keys/MFA; затем system DB, Alerts/Releases/probes.
|
||||
|
||||
Завершён 11Б.3.6.1: общие Settings без фиктивных сохранений/demo keys/MFA, реальная тема/source URL, переходы к инструментам; 32 E2E с одним исправленным locator, 3 source с исправленным alert locator, 8 Evolution source, typecheck/lint/build прошли. 6 screenshots, 320 просмотрены. System DB ещё не принят. Далее 11Б.3.6.1.2 health/source guards; затем 11Б.3.6.2 DB operations.
|
||||
|
||||
Завершён 11Б.3.6.1.2: DataSource health token/revision/abort/ABA, explicit checking и validated health body. 2 unit, 10 source/health, 16 Settings/Evo provider и 8 Evo source E2E, typecheck/lint/build прошли; два test setup уточнены. System monitor остаётся отдельным reader. Далее 11Б.3.6.2.1 — system DB API/credentials in events; затем backend outcomes и UI.
|
||||
|
||||
Завершён 11Б.3.6.2.1: system DB export PGDMP/leaf filename и restore strict receipt/limits/abort без повтора; DATABASE_URL удалён из новых event payload. 3 unit группы/typecheck/lint/backend и frontend builds прошли. UI/backend partial/restore transaction не приняты. Далее 11Б.3.6.2.2 — backend transaction/outcomes/DI HTTP/JWT, затем 11Б.3.6.2.3 форма.
|
||||
|
||||
Завершён 11Б.3.6.2.2.1: DI restore executor/--single-transaction/cleanup warning, file choose без фиктивного success, confirmation до receipt. 4 DI/3 API/2 browser tests, backend/frontend builds/typecheck/lint прошли; реальный PG restore не запускался. System DB не принят полностью. Следующий точный шаг 11Б.3.6.2.2.2 — backend core/restart/event partial outcomes + DI HTTP/JWT/concurrency; затем 11Б.3.6.2.3 source/lock/unknown UI.
|
||||
|
||||
Завершён 11Б.3.6.2.2.2: core/restart/event outcomes, nonqueued lock/409, DI HTTP/JWT/concurrency/API и browser checks прошли; реальная БД не запускалась. Далее 11Б.3.6.2.3 — отдельная DB форма с source/active/admin/sync lock/unknown review.
|
||||
|
||||
Завершён 11Б.3.6.2.3.1: DB form/rights/source lifetime/sync lock/persisted unknown review; 10 E2E/5 API/proxy unit/typecheck/lint/build прошли. 3 confirmation screenshots, 320 просмотрен. Далее 11Б.3.6.2.3.2 source/ABA/unmount и Settings регрессия.
|
||||
|
||||
| Блок | Референс | Схема |
|
||||
| --- | --- | --- |
|
||||
| 11Б.3.6.2.3.1 База приложения | [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp) | Источник и доступ → скачать / выбрать файл → подтверждение → результат + warnings; неизвестный результат → проверка данных → разрешение нового запроса |
|
||||
|
||||
Завершён 11Б.3.6.2.3.2: 6 source/ABA/reload и 18 General/DB E2E прошли, DB принят локально. Реальный PG/UDP worker/Portal не принят. Далее 11Б.4.1 — strict Alerts contracts/API, затем backend/UI.
|
||||
|
||||
Завершён 11Б.4.1: строгие Alerts output/API/receipt сверки, 5 unit/contracts/backend build/typecheck/lint прошли. UI/backend пока прежние. Далее 11Б.4.2.1 — atomic selective Telegram save/RETURNING и DI HTTP/JWT/test results; затем rules/UI.
|
||||
|
||||
Завершён 11Б.4.2.1.1: selective Telegram UPDATE RETURNING/partial concurrent patches, singleton conflict-safe и strict bounded send receipt; 7 tests/build/lint прошли. Groups/evaluate regression прошла, confirm-stability skip без PG. Далее 11Б.4.2.1.2 — Alerts real HTTP/JWT/save/test и согласованный источник; UI прежний.
|
||||
|
||||
Завершён 11Б.4.2.1.2: Alerts HTTP/JWT read/write gates и один Telegram snapshot; профильные tests/build/typecheck/lint прошли. Далее 11Б.4.2.2.1 rules/groups normalization/transactional receipt, затем UI.
|
||||
|
||||
Завершён 11Б.4.2.2.1.1: shared rules/groups normalization до delete, 8 unit/HTTP/JWT/builds/typecheck/lint прошли. Router readback остаётся после commit; omitted groups read вне transaction. Далее 11Б.4.2.2.1.2 transactional receipt/context/DI/concurrency; затем UI/outbox.
|
||||
|
||||
Завершён 11Б.4.2.2.1.2: transactional rules/groups receipt/readback и nonblocking replace lock/409; 4 DI + profile/build/typecheck/lint прошли. Real PG и optimistic revision не проверены. Далее 11Б.4.3.1 — Alerts UI source/strict readers/known/error/time; затем drafts/locks/rights/adaptive и GET/outbox audit.
|
||||
|
||||
Завершён 11Б.4.3.1.1: primary Alerts strict reader/unknown/known empty/time/last snapshot без live initial mocks; 3 E2E/lint/typecheck/build прошли. Secondary readers/dirty/forms пока прежние. Далее 11Б.4.3.1.2 — независимые BGP/GRE/last good/source ABA; затем forms/rights/adaptive/GET/revision/outbox audit.
|
||||
|
||||
Завершён 11Б.4.3.1.2.1: strict BGP/server/GRE target readers, partial GRE failures/unknown status; 4 unit/typecheck/lint прошли, module не подключён. BGP endpoint не раскрывает failures. Далее 11Б.4.3.1.2.2 — independent readers/status/last good/source ABA; затем forms и audit.
|
||||
|
||||
|
||||
### 11Б.4.3.1.2.2 — каталоги Alerts (2026-10-03)
|
||||
|
||||
Primary и три вторичных reader независимы, partial GRE сохраняет last good, unknown status не down. OpsPanel/Frame показывает права, ошибки, время и отдельный retry. 9 browser сценариев, typecheck/lint/audit пройдены; реальные сетевые опросы не проверены. Следующий шаг 11Б.4.3.2: Telegram dirty draft/selective save/test/rights/unknown review/source; затем правила, GET/revision/outbox audit и оставшиеся 11Б/12.
|
||||
|
||||
|
||||
### 11Б.4.3.2 — Telegram (2026-10-03)
|
||||
|
||||
Dirty/selective save, strict receipt, общий lock, bounded source lifetime, unknown checkpoint без секретов и права alerts:write. 10 профильных browser сценариев + 4 source ABA, регрессия readers, lint/typecheck; форма 320px просмотрена. API acceptance не означает доставку. Rule preview и реальные Telegram/PG пока не приняты. Далее 11Б.4.3.3: правила и группы — strict receipt, права, общий замок, сохранение формы при ошибках и unknown review; затем GET/revision/outbox audit, общий dashboard permission reader, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
|
||||
### 11Б.4.3.3 — правила и группы (2026-10-03)
|
||||
|
||||
Strict receipt вместо optimistic overwrite, draft editor/group формы, права/common lock/source/unknown, подтверждение delete и сохранение recovery policy. 8 browser + 2 source, Telegram regression, typecheck/lint/build пройдены. Preview Telegram временно disabled; picker и backend consistency ещё не приняты. Далее 11Б.4.3.3.1: защищённый тест Telegram из редактора правила с общим checkpoint и замком; затем согласованность GET/revision/outbox, общий dashboard permission reader, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
|
||||
### 11Б.4.3.3.1 — Telegram preview (2026-10-03)
|
||||
|
||||
Strict preview и общий checkpoint карточки/editor без секретов, common lock/source/rights, inline API acceptance. 3 browser + 2 source, Telegram regression, typecheck/lint прошли. Доставка и реальные PG/Telegram не приняты. Далее 11Б.4.4.1: согласованный read-only GET Alerts и достоверные metadata/history; затем optimistic revision/outbox audit, общий dashboard permission reader, адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
|
||||
### 11Б.4.4.1 — GET Alerts (2026-10-03)
|
||||
|
||||
Read-only repeatable read/единый context без pool escape, strict snapshot/no-store, только реальные probe metadata и отдельный source истории без ложной доставки. 2 DI + backend HTTP/JWT/profile, history browser, backend build/root typecheck/lint прошли. Реальная PG isolation не доказана. Далее 11Б.4.4.2: optimistic revision/If-Match правил и групп, чтобы старый клиент не перезаписывал новый snapshot; затем outbox unknown audit, общий dashboard permission reader, адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
|
||||
### 11Б.4.4.2 — revision/If-Match (2026-10-03)
|
||||
|
||||
Canonical configuration hash, обязательный If-Match HTTP, locked stale check до write, 412/428 без optimistic overwrite; draft refresh сохраняет concurrent rules. Hash/stale DI, HTTP/JWT, API/browser/source, builds/typecheck/lint прошли; real PG конкуренция не доказана. Обновлять frontend/contracts/backend вместе; no push. Далее 11Б.4.4.3: outbox audit — неизвестный результат отправки/повторы/зависшие sending и согласованность журнала; затем общий dashboard permission reader, адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
|
||||
### 11Б.4.4.3.1 — delivery outcome (2026-10-03)
|
||||
|
||||
Bot API rejected/unknown, единый stored snapshot/strict thread, no secret/no retry в helper. 3 delivery + 4 send DI, Alerts profile/backend build/lint прошли; dispatcher ещё не мигрирован, PG/Telegram не проверены. Далее 11Б.4.4.3.2: миграция статусов outbox, atomic claim перед POST и unknown hold без автоматического resend; затем согласованный receipt/history и UI очереди, общий dashboard permission reader, адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
|
||||
### 11Б.4.4.3.2 — outbox orchestration (2026-10-03)
|
||||
|
||||
Conditional atomic claim, unknown/processing hold, transactional status/history receipt, atomic dedupe enqueue и migration 0008. 7 DI/profile/build/lint прошли; engine groups/eval прошли, PG stability skipped. Реальные migration/lock/rollback/Telegram и UI/operator resolution ещё не приняты. Далее 11Б.4.4.3.3: показать known очередь/processing/unknown в GET/UI и сохранить состояние при сбое; затем контролируемое разрешение held entries, общий dashboard permission reader, адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.4.4.3.3
|
||||
|
||||
GET/UI очереди принят локально: независимый strict snapshot, known/unknown, сохранение при сбое и ABA; 32 browser + 12 context, API/DI/HTTP/JWT/build/typecheck/lint прошли. Реальный PG/Telegram и ручное разрешение held не приняты. Следующий блок 11Б.4.4.3.4: контролируемый повтор только unknown после явной проверки оператором и защиты от конкуренции; processing удерживать до отдельной проверки остановки отправителя. Затем общий dashboard permission reader, адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.4.4.3.4
|
||||
|
||||
Backend manual unknown retry принят локально: acknowledged risk + atomic version CAS, transaction receipt, no send/history; DI/HTTP/JWT/build/typecheck/lint/queue browser прошли. Реальный PG/0009 и UI действия не приняты. Следующий блок 11Б.4.4.3.5: подключить UI ручного повтора unknown с подтверждением риска дубликата, общим checkpoint при неизвестном POST и сохранением формы/источника; затем общий dashboard permission reader, адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.4.4.3.5
|
||||
|
||||
UI manual unknown retry принят локально: explicit duplicate risk, common lock, strict pending receipt, unknown checkpoint across reload/ABA. API 2, browser 6 + mobile 1, context14, typecheck/lint прошли. Processing recovery и внешняя доставка не приняты. Источник global GRE — AppSidebar, dashboard hook только на dashboard page. Следующий блок 11Б.4.4.3.6: исправить права общих sidebar/dashboard readers (источник фонового GRE оказался AppSidebar), затем адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12. Processing остаётся без повтора до отдельного сценария подтверждённой остановки отправителя.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.4.4.3.6
|
||||
|
||||
Общие Sidebar/SystemMonitor readers проверяют auth/права, unknown counts не становятся нулями, health независим от summary; API unit/browser9/typecheck/lint прошли. Дополнительная links/dashboard регрессия107 ещё выполняется. Backend count helpers с catch→0 требуют отдельного исправления. Следующий блок 11Б.4.4.3.7: применить права backend к каждому запросу dashboard reader и проверить ограниченный JWT; затем адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12. Processing recovery требует отдельного сценария остановки отправителя.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.4.4.3.7
|
||||
|
||||
Dashboard per-request permissions принят локально: mapper parity13paths, limited JWT2, browser18/typecheck/lint прошли. Предыдущая regression107 завершилась успешно. Legacy dashboard DTO/fallback не переприняты. Следующий блок 11Б.4.4.3.8: убрать timeout/partial/error→0 в backend sidebar counts через полные каталоги; затем адаптивность/pickers, Releases/probe scheduling и приёмка 11Б/12. Processing recovery требует отдельного сценария остановки отправителя.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.4.4.3.8
|
||||
|
||||
Backend sidebar optional counts не выдают timeout/partial/error как0, используют complete typed catalogs; helper2/HTTP/build/containers/live-maps/lint/browser7 прошли. Сетевой опрос после deadline не отменяется; PG/RouterOS внешняя приёмка нужна. Следующий блок 11Б.4.4.3.9: исправить семантику выбора объектов/условий и один scroll owner в Alerts Sheet; затем обозначить неподдерживаемое BGP-prefix событие, Releases/probe scheduling и приёмка 11Б/12. Processing recovery требует сценария остановки отправителя.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.4.4.3.9
|
||||
|
||||
Picker keyboard semantics/one parent scroll/initial objects accepted locally; browser21/typecheck/lint/ReUI audit passed, 320px screenshot reviewed. Общий Alerts экран не принят. Следующий блок 11Б.4.4.3.10: явно обозначить неподдерживаемый BGP-prefix evaluator в live UI, затем production build накопленных изменений. Далее processing recovery, компактность основной Alerts страницы, Releases/probe scheduling и приёмка 11Б/12.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.4.4.3.10
|
||||
|
||||
Live BGP-prefix честно помечен unsupported, legacy записи не удалены; browser12/typecheck/lint и production frontend/contracts/backend build прошли. Финальный Alerts/backend sidebar профиль прошёл. Основной Alerts экран/processing recovery/внешняя PG и Telegram приёмка остаются. Следующий блок 11Б.4.4.3.11: компактность основной Alerts страницы и профильная приёмка ПК/320px; processing recovery проектировать отдельно с доказуемой остановкой всех отправителей. Затем Releases/probe scheduling и приёмка 11Б/12. Внешняя PG/Telegram приёмка обязательна перед выпуском.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.4.4.3.11
|
||||
|
||||
Приоритет правил, доступные фильтры/поиск и мобильная строка приняты локально: browser35 + повтор12, typecheck/lint/ReUI audit, screenshot320. Readers/формы/guards сохранены. Следующий блок 11Б.5: проверить достоверность release manifest, безопасные ссылки и локальное/неизвестное состояние Releases, затем probe scheduling и приёмка 11Б/12. Processing recovery остаётся отдельной задачей с доказуемой остановкой всех отправителей; внешняя PG/Telegram приёмка обязательна перед выпуском.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.5
|
||||
|
||||
Releases strict metadata/unknown/local/безопасные ссылки и current-production announcement приняты локально. Unit3/browser3/typecheck/lint/final production build прошли, screenshot320 просмотрен; публикация CI/Gitea не проверена. Следующий блок 11Б.6: достоверное чтение live speed-test в расписании диагностики, права uptime:read, повтор/последние данные и неизвестный RX без нуля; затем source/адаптивная приёмка и сводная приёмка 11Б/12. Processing recovery требует отдельного доказательства остановки всех отправителей.
|
||||
|
||||
### Продолжение 2026-10-03 — 11Б.6
|
||||
|
||||
Live probe schedule strict read/own permissions/last good/retry/deadline/source и unknown TX/RX принят локально; demo tunnel selection исправлен. Unit2/browser36+8/context8/typecheck/lint/ReUI audit прошли, screenshot320 просмотрен. Реальный collector/legacy backend normalization не переприняты. Следующий блок 11Б.7: сводная локальная регрессия оповещений, scheduler/integrations/settings/DB/releases/probe schedule, итоговый список внешних ограничений и production build; затем начать этап 12. Processing recovery без доказуемой остановки всех отправителей остаётся недоступен.
|
||||
|
||||
## Сводная локальная приёмка — 11Б.7 (2026-10-03)
|
||||
|
||||
| Группа | Локальный результат | Осталось вне этой проверки |
|
||||
| --- | --- | --- |
|
||||
| Scheduler / сбор данных | Независимые known/error/time, dirty/selective save, общий lock, receipt partial/fatal, source isolation | Реальное выполнение collectors, PG journal/rollback и UDP lifecycle |
|
||||
| GeoIP / NetFlow / Evolution | Reader/permissions, формы и секреты, unknown checkpoints, подтверждённый результат | MaxMind/RIPE, IPFIX/WireGuard export, Portal и upstream provider |
|
||||
| System DB | Выбор файла отделён от restore, backup bytes/metadata, один запрос, предупреждения и неизвестный результат | Реальные pg_dump/pg_restore, rollback и остановка всех workers |
|
||||
| Alerts | Rules/groups revision/If-Match, форма/права, независимые каталоги/очередь, Telegram API acceptance, CAS retry только unknown | PG migrations 0008/0009, isolation/CAS/rollback, реальные Telegram; processing recovery и BGP-prefix не реализованы |
|
||||
| Releases | Strict manifest, unknown/local/mismatch, безопасные ссылки, только current production announcement | Реальная публикация CI/Gitea |
|
||||
| Probe schedule | Strict read, uptime:read, retry/time/source, nullable TX/RX | Реальное выполнение uptime speed worker; backend legacy normalization не перепринята |
|
||||
|
||||
Схема финального Alerts: сводка → правила → очередь → каталоги; справа Telegram/журнал, затем пресеты/подсказки. На телефоне очередь идёт перед Telegram; независимые readers остаются смонтированы при unknown → known основной загрузки.
|
||||
|
||||
| Экран | ПК | Телефон | Референс |
|
||||
| --- | --- | --- | --- |
|
||||
| Alerts | [Экран](ux-ui/screens/alerts-overview-1440.png) | [Экран](ux-ui/screens/alerts-overview-320.png) | [List 9](https://reui.io/preview/base/list-9?ref=mcp), [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp) |
|
||||
| Releases | [Экран](ux-ui/screens/releases-local-1440.png) | [Экран](ux-ui/screens/releases-local-320.png) | [List 9](https://reui.io/preview/base/list-9?ref=mcp) |
|
||||
| Probe schedule | [Экран](ux-ui/screens/probes-speed-schedule-1440.png) | [Экран](ux-ui/screens/probes-speed-schedule-320.png) | [Data Grid](https://reui.io/components/data-grid?ref=mcp) |
|
||||
|
||||
Сводная регрессия: 189 browser, 68 source/context, 61 unit/contracts/API и 7 named backend profiles прошли. После заключительной компоновки Alerts дополнительные16 reader/targets/queue,25 forms/layout/preview,14 source и финальная production build прошли. Backend build тоже прошла.39 снимков сохранены в репозитории; итог фиксируется в начале журнала. Браузерные тесты подменяют HTTP; backend DI/HTTP используют тестовые зависимости. Это не доказательство работы внешних систем или полного соответствия WCAG. SQL миграции локально не применялись, push/deploy не выполнялись.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,56 @@
|
||||
# Этап 6: общая оболочка и дашборд
|
||||
|
||||
Рабочая схема от 2026-09-20. Основа — ui-design-contract.md: ReUI PRO, base-nova, Frame, Sidebar 240 px. Поиск вызывается Ctrl+K/⌘K, тема остаётся в NavUser. Этап завершён в границах локальной приёмки; ограничения указаны ниже.
|
||||
|
||||
| Область | Референс | Результат |
|
||||
| --- | --- | --- |
|
||||
| Оболочка | [App Shell 12](https://reui.io/preview/base/app-shell-12?ref=mcp) | Контекст страницы, доступные действия, меню и поиск с клавиатуры |
|
||||
| Сводка | [Stats 12](https://reui.io/preview/base/stats-12?ref=mcp) | KpiStatGrid/IconTile во Frame, предметные подписи, неизвестное значение — «—» |
|
||||
| Очередь проблем | [List 9](https://reui.io/preview/base/list-9?ref=mcp) | Проблема → объект → доступное действие |
|
||||
|
||||
## ПК
|
||||
|
||||
```text
|
||||
┌ Навигация 240 px ┬ Путь страницы · Действия · Приложения · Монитор ┐
|
||||
│ Обзор ├ Свежесть / ошибки источников / обновить │
|
||||
│ Данные ├ Сводка: серверы · туннели · BGP · проверки │
|
||||
│ Управление ├ Очередь проблем → сервер / профильный раздел │
|
||||
│ Инструменты ├ Измерения и события │
|
||||
│ Система │ Быстрые переходы │
|
||||
└─────────────────┴─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Телефон
|
||||
|
||||
```text
|
||||
┌ Меню · Текущая страница ┐
|
||||
│ Действия с переносом · Приложения · Монитор │
|
||||
├ Свежесть / ошибки источников ┤
|
||||
│ Сводка в адаптивной сетке │
|
||||
│ Очередь проблем → объект │
|
||||
│ Измерения → события → быстрые переходы │
|
||||
└────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
На страницах без действий служебные кнопки остаются рядом с заголовком. При наличии действий и ширине менее 1280 px выделяется дополнительная строка с переносом кнопок. DOM-порядок совпадает с визуальным и клавиатурным, текущий заголовок не скрывается многоточием. На ПК сохраняется компактная строка, при нехватке места шапка растёт по высоте.
|
||||
|
||||
## Блоки и приёмка
|
||||
|
||||
1. **Шапка.** Убрать фиксированную высоту и обрезку; текущая страница видна на телефоне; корректный список Breadcrumb. Проверить 320/390/1024/1440 px, клавиатуру и Escape.
|
||||
2. **Навигация.** Общий источник названий, адресов и поисковых синонимов для Sidebar и CommandPalette. Использовать установленные Command/Dialog для фокуса, поиска, клавиатуры и семантических цветов. Закрывать мобильное меню после перехода. Сверить маршруты с существующими страницами.
|
||||
3. **Дашборд.** Уточнить подписи «Флот», «Оверлей», «BGP Rx», «Здоровье». Поднять очередь проблем после сводки, дать контекст и переходы к объектам. Сохранить состояния источников этапа 5; отсутствие данных не считать отсутствием проблем. Быстрые переходы не должны вытеснять проблемы за первый экран.
|
||||
4. **Приёмка.** Просмотреть ПК/телефон, проверить переходы, пустое состояние, частичный сбой и клавиатуру; профильные тесты, TypeScript, lint и production build общей оболочки.
|
||||
|
||||
HTTP-моки проверяют интерфейс и запросы. Реальные данные, права и RouterOS требуют тестового окружения. Формы и полный URL-контекст сервера относятся к этапу 7; сетевые операции в этапе 6 не менять.
|
||||
|
||||
## Состояние реализации
|
||||
|
||||
Шапка, навигация, иерархия дашборда и переходы ко всем типам объектов очереди завершены. Итоговая приёмка этапа: 68 E2E-сценариев passed; production build и TypeScript успешны. Проверены клавиатура, светлая/тёмная навигация, ширины шапки 320/390/1024/1440, контекст туннелей на ПК/телефоне, ошибки HTTP и возврат. Подробнее — ux-ui-progress.md.
|
||||
|
||||
### Переходы к объектам
|
||||
|
||||
Готовы и проверены: /servers?server=<id>, /uptime?probe=<id>, /gre?server=<serverId>&tunnel=<id>, /wireguard?server=<serverId>&interface=<id>, /vxlan?server=<serverId>&tunnel=<id>. Идентификаторы кодируются encodeURIComponent, целевые страницы выбирают точный ID (для туннелей — пару сервер/объект) и сообщают об отсутствии/ошибке загрузки. Снятие выбора сохраняет остальные query-параметры. GRE, WireGuard и VXLAN используют preserveSelection серверной панели, чтобы не сбрасывать URL при загрузке/отсутствии устройства. При отсутствии VXLAN сообщение не делает вывода об удалении: backend скрывает ошибки отдельных опросов. Исправление этого API и достоверность сетевых KPI — этап 9.
|
||||
|
||||
### Границы приёмки
|
||||
|
||||
HTTP-моки подтверждают UI и запросы; RouterOS и реальные права требуют отдельного окружения. Полная адаптивность профильных таблиц/форм не входит в эту приёмку: известная обрезка строк Ping-проб — этап 7, сетевые формы и действия — этап 9. Прежние lint-замечания общих компонентов перечислены в журнале; чистый lint всего проекта не заявляется. ReUI Frame/base-nova, установленные Alert, DataGrid, Command/Dialog и ServerRail сохранены; новых зависимостей и изменений vendored-компонентов нет.
|
||||
@@ -0,0 +1,74 @@
|
||||
# Этап 7: серверы и мониторинг
|
||||
|
||||
Подготовка 2026-09-20 по текущему коду после этапа 6. Блоки 7.1 и 7.2 реализованы 2026-09-21; далее права действий, блок 7.3. Основа: ReUI PRO, base-nova, Frame; переиспользовать установленные Filters/DataGrid, ServerFilters, PageHeader и Sheet. Не менять vendored-компоненты и правила сетевых операций.
|
||||
|
||||
## Инвентаризация
|
||||
|
||||
| Область | Подтверждено в коде | Следующая доработка |
|
||||
| --- | --- | --- |
|
||||
| Серверы | `app/(main)/servers/page.tsx`: URL читает только `server`; search/typeFilter/advancedFilters — локальный useState | Восстановление фильтров из URL без сброса выбранного сервера |
|
||||
| Filters | `server-filter-fields.ts`: country/status/type; `apply-filter-query.ts` сохраняет AND/OR, вложенность, negated и черновики | Ограниченный валидируемый codec дерева, без уплощения |
|
||||
| Формы сервера | Уже есть сохранение формы при ошибке, блокировка повторов, загрузка деталей, разделение результатов опроса и обновления списка | Проверить UX шагов и доступность, сохранить существующие гарантии |
|
||||
| Мониторинг | `/uptime?probe=...` выбирает проверку; отдельные вкладки и фильтры пока не имеют полного URL-контракта | Отдельный блок URL после серверов; не распространять probe на несвязанные ресурсы/speed |
|
||||
| Телефон | Ping-пробы: фиксированная сетка из 11 колонок, FramePanel с overflow-hidden | Доступные имя/цель/состояние и действия на 320/390 px без обрезки |
|
||||
| Права | `lib/auth.ts`: can/hasPermission; страницы servers/uptime не используют их для разрешений действий | UI-доступность по фактической политике backend, с повторной обработкой 403 |
|
||||
|
||||
## Референсы и схема
|
||||
|
||||
| Блок | Референс | Схема доработки |
|
||||
| --- | --- | --- |
|
||||
| Список серверов | [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Контекст → поиск/тип/Filters → результат → детали |
|
||||
| Детали и формы | [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp) | Объект → доступное действие → форма → подтверждённый API-результат |
|
||||
| Проверки на телефоне | [List 9](https://reui.io/preview/base/list-9?ref=mcp) | Имя и цель → состояние → измерение → действия |
|
||||
|
||||
```text
|
||||
ПК: [Контекст сервера / проверки · снять выбор]
|
||||
[Поиск] [Тип] [Filters] [Доступные действия]
|
||||
[Таблица → детали → форма → результат]
|
||||
URL ↔ фильтры; Back/reload возвращают контекст
|
||||
|
||||
Телефон: [Имя проверки Состояние]
|
||||
[Источник → цель]
|
||||
[RTT / потери] [Действия]
|
||||
[Раскрыть дополнительные сведения]
|
||||
```
|
||||
|
||||
Это схема иерархии, а не разрешение переписать таблицы или блоки вручную. Конкретную композицию мобильного списка выбрать из установленных компонентов после проверки текущих действий строки.
|
||||
|
||||
## Блок 7.1 — URL серверов
|
||||
|
||||
Реализованный контракт:
|
||||
|
||||
| Параметр | Значение | Правило |
|
||||
| --- | --- | --- |
|
||||
| `server` | Точный ID из этапа 6 | Сохранять при изменении фильтров; отсутствие объекта не подменять другим |
|
||||
| `q` | Строка поиска | Пустое значение удалять; ввод обновлять сразу через native replaceState, без новых записей истории и повторных запросов API |
|
||||
| `type` | jump-host / exit-node / home-router | «Все» — отсутствие параметра; дискретный выбор добавляет запись истории |
|
||||
| `filters` | JSON `{v:1, query: FilterQuery}` | URLSearchParams кодирует значение; сохранить AND/OR и структуру групп |
|
||||
|
||||
Сначала реализовать чистый codec в `lib/data-filters/server-url-state.ts` и профильные unit-тесты. Валидировать до передачи в Filters/evaluator: версию, тип узла, уникальные ID, поля из SERVER_FILTER_FIELDS, допустимые для select операторы/значения. Ограничить размер JSON 8 KiB, количество узлов 50, глубину 4. Эти числа — рабочие пределы нового контракта, не существующие ограничения ReUI. Окончательный список операторов сверить с установленной конфигурацией select.
|
||||
|
||||
Черновик незавершённого условия оставить локальным; не публиковать частично собранное дерево и не превращать OR в AND. При восстановлении неверного filters/type показать понятное сообщение и действие сброса; до сброса не расширять результат до всех серверов молча. Не помещать в URL пароли, ключи и поля форм.
|
||||
|
||||
URL — источник сохранённого состояния. Back/Forward/reload восстанавливают контролы и строки без циклов синхронизации, автозаписи и повторного открытия форм. При быстрых изменениях разных контролов читать актуальные параметры, чтобы поздняя запись поиска не затёрла type/filters/server. Сброс фильтров удаляет q/type/filters, сохраняя server и чужие параметры; «Все серверы» снимает только server.
|
||||
|
||||
Приёмка: прямой URL; reload; Back/Forward; смена type после ввода поиска; AND/OR; черновик; повреждённый/слишком большой JSON; неизвестное поле/оператор; сброс с сохранением server; пустой результат; отсутствие POST/PATCH/DELETE от навигации. Прогнать codec unit-тесты, servers.spec.ts, профильные URL E2E, lint/TypeScript и production build. Затем журнал и локальный коммит без push.
|
||||
|
||||
## Блоки после 7.1
|
||||
|
||||
1. **7.2 — мобильные проверки (выполнено).** Устранить обрезку Ping-проб, сохранив выбор строк, раскрытие, запуск и меню. Проверить 320/390/1440 px, клавиатуру/Escape, отсутствие скрытых обязательных действий и горизонтального скролла всей страницы.
|
||||
2. **7.3 — права действий.** Источник политики — `backend/src/lib/permissions.ts`, применение — `backend/src/plugins/auth.ts`. GET `/api/servers*` требует `mm:servers:read`, запись — `mm:servers:write`; GET `/api/uptime*` — `mm:uptime:read`, запись — `mm:uptime:write`. Учитывать наследование write/admin через существующий hasPermission и режим auth disabled. Проверить конкретные маршруты опроса/теста соединения, не считать их чтением только по названию. UI не заменяет backend-проверку: серверный 403 сохраняет форму и сообщает отказ. Не выдавать доступ только по is_admin без подтверждения текущей политики.
|
||||
3. **7.4 — формы, детали и полный контекст мониторинга.** Восстановление вкладки/фильтров из URL, понятные единицы и подписи, возврат к списку после действия. Не дублировать сохранённые исправления этапа 1; проверить загрузку, отмену, 400/403/500, timeout и повторное нажатие.
|
||||
4. **7.5 — приёмка этапа.** Сценарий «проблема → сервер/проверка → действие → возврат» с сохранением контекста; профильные E2E, права в HTTP-моках, TypeScript, lint и build. Реальные JWT/RouterOS отдельно в тестовом окружении.
|
||||
|
||||
Локальная приёмка этапа 7 завершена 2026-09-23: 94 профильных E2E и 2 проверки смены backend. Полные границы и внешние ограничения — в docs/ux-ui-progress.md. Следующий этап — 8, трафик и статистика.
|
||||
|
||||
## Решение по синхронизации URL (7.1)
|
||||
|
||||
Поиск использует native replaceState без debounce: установленный Next App Router синхронизирует useSearchParams, не запрашивая серверные данные. Браузерный тест подтвердил быстрый посимвольный ввод и неизменное количество GET /api/servers. Это устраняет отложенную запись, способную затереть последующий выбор type/filters. Дискретные изменения используют pushState, читая актуальный window.location.search. Черновик Filters привязан к сохранённому filters и сбрасывается при popstate. Неверные type/filters блокируют выдачу до исправления/сброса; server и чужие параметры сохраняются.
|
||||
|
||||
## Реализация адаптивных строк (7.2)
|
||||
|
||||
Один DOM и прежние обработчики Ping-проб сохранены. Frame задаёт контейнер ширины; локальный CSS module перестраивает существующую строку в две колонки с подписями при ширине контейнера менее 1100 px. При достаточной ширине возвращается сетка 11 колонок. Имена, цель, интерфейс и фильтр переносятся; состояние подписано на узком экране. Переключатель получил доступное имя через label, кнопки — aria-label, серверный заголовок — aria-expanded. Используются прежние FormToggle/Button/Collapsible/Sparkline; ReUI и общая тема не изменены.
|
||||
|
||||
11 профильных E2E прошли, в том числе длинные подписи на 320/390/1440 px, видимость действий, Enter для раскрытия графика, редактирование/Escape, запрос звезды и включение пробы. Скриншоты 320/1440 просмотрены, обрезка строки устранена. Проверка не означает адаптивность всех вкладок uptime: Resources/Speed и их формы остаются отдельными частями плана.
|
||||
@@ -0,0 +1,76 @@
|
||||
# Этап 8: трафик и статистика
|
||||
|
||||
Статус: завершён 2026-09-28 в границах локальной приёмки. Итоговая матрица 8.13 ниже уточняет и заменяет промежуточные точки продолжения.
|
||||
|
||||
Основа: установленные ReUI PRO/base-nova, Frame, KpiStatGrid, DataGrid, Filters и DateSelector. Каждый законченный блок — профильные проверки, журнал и локальный коммит без push.
|
||||
|
||||
| Блок | Результат | Приёмка |
|
||||
| --- | --- | --- |
|
||||
| 8.1 | Данные статистики привязаны к периоду/срезу; ошибка не равна нулю; повтор запроса | Задержка нового периода, 403/500, успешный пустой ответ, поздний ответ |
|
||||
| 8.2 | Валидные периоды, URL-контекст, единицы | Ошибочные даты, история, срезы и pivot |
|
||||
| 8.3 | Разделение live и истории трафика; состояния потока и polling | Разрыв SSE, смена интерфейса/периода, неизвестные значения и гонки |
|
||||
| 8.4 | Связь графиков/таблиц и мобильная приёмка | Общий период/объект, пустые состояния, 320/390/1440 px |
|
||||
|
||||
| Область | Референс | Схема |
|
||||
| --- | --- | --- |
|
||||
| Фильтры и таблицы | [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Период → срез → график → строки того же запроса |
|
||||
| Сводка | [Stats 12](https://reui.io/preview/base/stats-12?ref=mcp) | Контекст → подтверждённые метрики → детали |
|
||||
|
||||
```text
|
||||
[Период] [Срезы] [История / live]
|
||||
↓ один контекст запроса
|
||||
[Загрузка / Ошибка + повтор / Подтверждённые данные]
|
||||
[Метрики] → [График] → [Таблица] → [Уточнить срез]
|
||||
```
|
||||
|
||||
Исходные наблюдения 2026-09-23:
|
||||
- Statistics оставляет прежний data/pivot до ответа нового запроса; catch подставляет EMPTY, совмещая ошибку с нулями и «Нет данных куба».
|
||||
- readRange сравнивает строки без строгой проверки даты; parseYmd нормализует несуществующие дни через JavaScript Date. Проверить в 8.2.
|
||||
- useTrafficLive требует отдельной проверки завершения SSE и позднего ответа после abort в 8.3; это пока риск, а не доказанный дефект UI.
|
||||
- Реальный IPFIX/RouterOS недоступен локально. HTTP/SSE-моки не доказывают сбор и точность сетевой телеметрии.
|
||||
|
||||
## Промежуточная приёмка 2026-09-28 (блок 8.5)
|
||||
|
||||
| Проверка | Результат и границы |
|
||||
| --- | --- |
|
||||
| Периоды, URL и срезы статистики | 12 браузерных и 10 модульных проверок прошли; ошибки и некорректные параметры не становятся пустым/расширенным отчётом |
|
||||
| Трафик: REST, SSE, гонки и время получения | 41 браузерный сценарий прошёл: детали, списки, flow, разрывы графиков, поздние ответы, ошибки, временные подписи |
|
||||
| Смена backend | 3 сценария отдельной конфигурации прошли (трафик и два Ping); переход через настройки размонтирует экран |
|
||||
| ReUI и адаптивность | Сохранены Frame/KpiStatGrid/DataGrid; профильные проверки 320/390/1440 проходят; осмотрен месячный flow на 390px. Полный аудит клавиатуры/скринридера ещё не выполнен |
|
||||
| Недостоверная сводка flow | Убрана подстановка общих метрик коллектора вместо выбранного среза при ошибке/загрузке. Она также неверно переводила bytesPerMin в бит/с без деления на 60. Теперь три метрики среза показывают «—», доступное количество экспортёров сохраняется |
|
||||
| Действия и подписи | Неработающая кнопка «Экспорт» удалена. RX/TX больше не называются «сейчас», поскольку данные могут быть историческими; источник и временные отметки остаются рядом |
|
||||
|
||||
Этап 8 пока не закрыт. Следующий блок — обработка молчащего открытого SSE: после прекращения валидных sample нельзя бесконечно показывать live; сохранить последнее значение/время, обозначить отсутствие обновлений, проверить возобновление и смену контекста. Порог определить по фактической частоте backend и проверить управляемыми часами.
|
||||
|
||||
После этого требуется итоговое решение по месячному отчёту: текущий список экспортёров охватывает только 24 часа, архивные серверы и прошлые месяцы недоступны. Экспорт трафика не реализован. Проверку CRLF/heartbeat и единичной точки основного графика включить в оставшийся аудит, затем закончить ReUI/accessibility checklist. Реальные RouterOS, JWT и IPFIX не проверены локальными HTTP/SSE-моками.
|
||||
|
||||
|
||||
Обновление 8.6 (2026-09-28): молчащий SSE обработан в обоих hook — 15 секунд без валидного sample снимают live, сохраняя данные; следующий sample восстанавливает live. 24 прежних и 2 новых сценария прошли, как и lint/build. Следующий шаг — оставшийся аудит CRLF/heartbeat, первого sample, единичной точки графика и месячных ограничений; этап пока открыт.
|
||||
|
||||
Обновление 8.7 (2026-09-28): LF/CRLF и комментарий перед event поддержаны в обоих hook. Два потоковых сценария проверяют разделитель между chunk и heartbeat, не продлевающий свежесть. Все 26 профильных E2E прошли; далее одиночная точка графика и остальные ограничения, перечисленные выше.
|
||||
|
||||
Обновление 8.8 (2026-09-28): одиночные точки RX/TX, включая нули между пропусками, получили маркеры. Итоговые 10 тестов деталей и build/lint прошли; перед финальным подключением TX проверены 38 сценариев потребителей. Далее — первый SSE sample и оставшаяся приёмка.
|
||||
|
||||
Обновление 8.9 (2026-09-28): проверено ожидание первого sample в открытом SSE для flow и сервера, heartbeat без sample, таймаут и переход с истории на live. 28 профильных E2E, lint/TypeScript прошли; production-код не менялся. Далее — решение по месячному отчёту и доступность.
|
||||
|
||||
Обновление 8.10 (2026-09-28): добавлен выбор прошлого/текущего месяца UTC; валидация не отправляет пустые/будущие значения, ключ запроса защищает от позднего отчёта. 23 прежних и 1 новый flow-E2E прошли, lint/build чистые. Ограничение списка серверов по активности 24 часа остаётся следующим шагом; полный аудит доступности ещё не завершён.
|
||||
|
||||
Обновление 8.11 (2026-09-28): месячный режим выбирает сервер из каталога независимо от активности за 24 часа. 25 flow-E2E и дополнительная проверка пустого списка экспортёров прошли, как и lint/build. Удалённые из каталога серверы не перечисляются; далее доступность и итоговая регрессия этапа 8.
|
||||
|
||||
Обновление 8.12: получен checklist ReUI; имена поиска и aria-pressed исправлены. Клавиатурный E2E Enter/Space, lint/build прошли. Полный аудит Tab/фокуса/слоёв/статистики и итоговая регрессия ещё нужны; этап не закрыт.
|
||||
|
||||
## Итоговая локальная приёмка — блок 8.13 (2026-09-28)
|
||||
|
||||
| Проверка | Результат и границы |
|
||||
| --- | --- |
|
||||
| Профильная регрессия | 63 E2E в общем запуске; затем 15 сценариев статистики с 2 новыми проверками повреждённого HTTP 200. Всего 65 различных сценариев трафика/статистики проверены, включая 320/390/1440 px |
|
||||
| Смена backend и контекст | Отдельно прошли 3 backend-switch E2E и 10 unit-тестов периодов, контекста и фильтров |
|
||||
| Клавиатура и слои | Проверены Enter/Space, список измерений через стрелку, Escape, Tab внутри панели jump-host, возврат фокуса и сброс формы при повторном открытии без записи |
|
||||
| Доступные состояния | Поиск, измерения и поля панели имеют имена; SegmentedControl и выборы трафика — aria-pressed; ошибка flow — role=alert |
|
||||
| Достоверность статистики | Основной и pivot-ответы проверяются схемами contracts; повреждённый ответ даёт ошибку с повтором без падения и фиктивных KPI |
|
||||
| ReUI checklist | Используются существующие Frame/DataGrid/Filters и base-nova; новые зависимости, копии registry-компонентов и изменения сетевых правил не добавлены. Профильная доступность проверена, полный аудит остаётся этапом 12 |
|
||||
| Проверки кода | Production build/TypeScript: 34 страницы; lint изменённых файлов и diff-check прошли. После изменения сброса формы повторён E2E панели |
|
||||
|
||||
Границы приёмки: HTTP/SSE-моки не подтверждают реальную работу RouterOS/IPFIX/JWT. Серверы, удалённые из каталога, недоступны в месячном выборе; экспорт не реализован. После закрытия SSE автоматическое переподключение отсутствует; поддержаны LF/CRLF, одиночный CR не поддержан. Временные отметки получения не подменяют время измерения на устройстве. Полный аудит скринридером, контраста, производительности и сквозная регрессия предусмотрены этапом 12.
|
||||
|
||||
Следующий этап — 9: VPN и сетевые операции. Исторические записи выше сохраняются как журнал промежуточных решений.
|
||||
@@ -0,0 +1,380 @@
|
||||
# Этап 9: VPN и сетевые операции
|
||||
|
||||
Статус: локальная приёмка завершена 2026-09-30, выполнены блоки 9.1–9.64. Внешние ограничения и проверки — в блоке 9.64. Основа — существующие ReUI PRO/base-nova, Frame, ServerTileRail, DataGrid и формы. Правила применения сетевой конфигурации не меняем.
|
||||
|
||||
## Схема и референсы принятого плана
|
||||
|
||||
| Область | Референс | Схема доработки |
|
||||
| --- | --- | --- |
|
||||
| Устройство и объект | [List 9](https://reui.io/preview/base/list-9?ref=mcp) | Устройство → список → точный объект |
|
||||
| Формы | [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp) | Контекст → ввод → ожидание → результат / ошибка с сохранением ввода |
|
||||
| Таблицы | [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | Фильтры → таблица устройства → действие |
|
||||
|
||||
Референсы сохранены из общего плана; новые registry-компоненты не устанавливались.
|
||||
|
||||
```text
|
||||
[Устройство / URL] → [Объект и состояние данных]
|
||||
↓
|
||||
[Форма / подтверждение]
|
||||
↓
|
||||
[Один запрос · ожидание ответа]
|
||||
↙ ↘
|
||||
[Ошибка + повтор] [Подтверждение API]
|
||||
контекст сохранён ↓ обновить список
|
||||
```
|
||||
|
||||
## Карта работ
|
||||
|
||||
| Раздел | Точки интеграции | Следующая проверка |
|
||||
| --- | --- | --- |
|
||||
| WireGuard | app/(main)/wireguard/page.tsx, components/wireguard, shared/api/wireguard.ts; URL server/interface | Создание, импорт, пиры, переключение и экспорт: ввод, повтор, ответ и права |
|
||||
| IPsec | app/(main)/ipsec/page.tsx, components/ipsec, shared/api/ipsec.ts | Выбор устройства, инициализация, сертификаты/пользователи и ошибки |
|
||||
| GRE | app/(main)/gre/page.tsx; /api/gre/tunnels, revisions; URL-контекст | Запись/удаление и восстановление, повторные нажатия |
|
||||
| VXLAN | app/(main)/vxlan/page.tsx; /api/vxlan; URL server/tunnel | Загрузка/сбой/повтор, контекст и существующие действия |
|
||||
| Firewall | app/(main)/firewall/page.tsx; правила, адреса, перемещение и история | Достоверность записи, права и контекст устройства |
|
||||
| Filters | app/(main)/filters/page.tsx; /api/filters/rules, revisions, gre-tunnels, recursive-routes | Сохранение/применение, ошибки зависимостей и устройство |
|
||||
|
||||
Инвентаризация определяет точки следующего аудита; перечисление не означает проверки всех обработчиков.
|
||||
|
||||
## Блок 9.1 — удаление WireGuard
|
||||
|
||||
- Диалог удаления интерфейса/пира блокирует повтор и закрытие до ответа. Ожидание — role=status, ошибка — role=alert; при ошибке сохраняются объект и диалог для повтора.
|
||||
- Успех требует ok=true по контракту backend. HTTP 200 с ok=false не закрывает диалог и не показывает успех.
|
||||
- При различии ID строки и RouterOS ID для пира используется rosId. Прежний ID остаётся запасным вариантом при отсутствии rosId.
|
||||
- Прошли 13 E2E WireGuard: таблицы, URL/устройство, ошибки загрузки и оба удаления с задержкой, 403, неподтверждённым ответом и успешным повтором. Проверяются сервер и ID в DELETE. Lint, TypeScript и diff-check прошли.
|
||||
- Сохранён установленный AlertDialog/Base UI, без изменения темы/registry. Получен ReUI audit checklist; изменены поведение и доступные состояния.
|
||||
|
||||
Далее: создание/импорт/добавление пира WireGuard — сохранение формы, повторные операции, различие dry-run и применения. Затем остальные разделы по карте. Реальные RouterOS/JWT и сетевые последствия требуют отдельного окружения. Этап 9 не завершён.
|
||||
|
||||
## Блок 9.2 — достоверность ответа импорта
|
||||
|
||||
Ответ проверяется схемой contracts: режим dryRun соответствует запросу, применение подтверждается applied. Ошибка сохраняет текст и сервер. Один E2E с пятью последовательными ответами (403, dry-run, отсутствие applied, повреждённый ответ, успех), lint и TypeScript прошли. Серверный dry-run не добавлен в UI; предпросмотр остаётся локальным. Далее — создание/пиры, защита повторов и закрытия формы импорта во время запроса. Реальные сетевые операции не проверены.
|
||||
|
||||
## Блок 9.3 — ожидание импорта (2026-09-29)
|
||||
|
||||
Повторная отправка, закрытие и редактирование формы блокируются до ответа. Ошибка остаётся в форме, ожидание объявляется; добавлены доступные имена полей. Все 15 профильных E2E прошли, включая двойное нажатие, Escape/внешний клик, сохранение данных после 500 и повтор. Далее — создание интерфейса/пира и подтверждение их операций. Полный аудит сетевых разделов ещё не выполнен.
|
||||
|
||||
## Блок 9.4 — создание интерфейса и пира (2026-09-29)
|
||||
|
||||
Формы блокируют повтор/закрытие/изменение до ответа и сохраняют ввод при ошибке. Проверяются оба backend-ответа создания интерфейса (DTO либо ok/name) и ok=true создания пира. Поля и переключатели получили доступные имена; повторное открытие пира сбрасывает ввод. Все 18 E2E прошли, три новых повторены после уточнения переключателей; lint и TypeScript прошли. Итог сборки — в журнале. Следующие проверки: переключение интерфейса и экспорт с защитой контекста. Реальный RouterOS/JWT и транзакционность составной операции не подтверждены локальными моками.
|
||||
|
||||
## Блок 9.5 — переключение интерфейса (2026-09-29)
|
||||
|
||||
Повторы блокируются до PATCH и обновления списка; успех требует ok=true. Ожидание и ошибка с именами интерфейса/сервера объявляются через status/alert. Все 19 E2E, lint, TypeScript и diff-check прошли. Следующий блок — экспорт, включая поздние ответы и смену контекста. Реальное изменение RouterOS не проверено.
|
||||
|
||||
## Блок 9.6 — контекст экспорта (2026-09-29)
|
||||
|
||||
Результат, ошибка и завершение запроса привязаны к открытию панели; закрытие/новое открытие/размонтирование инвалидируют прежний ответ. Повтор защищён замком. Схема ответа и запрошенный формат проверяются. Три новых E2E, lint и TypeScript прошли; итог общего набора — в журнале. Далее: точный выбор пира, затем история/восстановление. Реальный экспорт ключей не проверен; сетевой запрос после закрытия не отменяется.
|
||||
|
||||
## Блок 9.7 — точный пир (2026-09-29)
|
||||
|
||||
Явный неизвестный ID не заменяется первым пиром; локальный и серверный экспорт используют общую функцию выбора по id/rosId. В API передаётся RouterOS ID выбранного пира. Прошли 4 E2E экспорта, 2 unit-теста, lint и TypeScript; неизвестный ID проверен на уровне функции. Далее — история и восстановление WireGuard. Реальное устройство не проверено.
|
||||
|
||||
## Блок 9.8 — подтверждение восстановления (2026-09-29)
|
||||
|
||||
Один POST до завершения операции; успех требует ok=true. Новый E2E проверил повторное нажатие, ok=false и успешный повтор. Далее — ConfigHistorySheet: исправить вложение div в p и сохранение подтверждения при ошибке, проверить всех потребителей. Предупреждение HTML воспроизведено; реальная операция RouterOS не проверена.
|
||||
|
||||
## Блок 9.9 — общий диалог восстановления (2026-09-29)
|
||||
|
||||
Исправлена HTML-разметка предупреждения; ошибка сохраняет выбранную ревизию и подтверждение для повтора. Общий замок блокирует повтор и закрытие до завершения Promise. Ошибки всех шести потребителей передаются в диалог; IPsec возвращает Promise. Все 40 профильных E2E прошли, включая 6 новых сценариев истории. Общий компонент и тесты lint-чистые; 7 исходных ошибок и 31 предупреждение в страницах подтверждены сравнением с HEAD и не изменились. Сборка — в журнале. Далее — ошибки/гонки загрузки истории, затем подтверждение восстановления остальных разделов. Реальные устройства не проверены.
|
||||
|
||||
## Блок 9.10 — загрузка истории WireGuard (2026-09-29)
|
||||
|
||||
Ошибка отделена от пустого списка и имеет повтор; ревизии проверяются по схеме и выбранному серверу. Закрытие/размонтирование и новое поколение запроса исключают поздние результат/ошибку/finally. Три новых E2E, lint и TypeScript прошли; итог регрессии в журнале. Остальные страницы пока не подключены к новым loadError/onRetry. Далее — подтверждение восстановления остальных разделов и их состояния истории.
|
||||
|
||||
## Блок 9.11 — подтверждение восстановления остальных разделов (2026-09-29)
|
||||
|
||||
IPsec/GRE/Firewall/Filters/рекурсивные маршруты требуют ok=true до применения ответа в UI; WireGuard уже проверял подтверждение. 6 расширенных сценариев истории прошли (403, ok=false, пустой ответ, успех), как и TypeScript/lint теста/diff-check. Исходные ошибки lint страниц не изменились. Далее — ошибка/повтор/поздние ответы загрузки истории этих пяти разделов. Полная валидация rules/routes и реальная операция RouterOS остаются вне этого блока.
|
||||
|
||||
## Блок 9.12 — загрузка истории IPsec (2026-09-29)
|
||||
|
||||
Ошибка и повтор подключены к общей панели; поздние ответы закрытого/сменившего контекст запроса игнорируются. Проверяется наличие массива revisions, без полной валидации записей. Все 7 E2E истории прошли. Далее — GRE/Firewall/Filters/рекурсивные маршруты и общая схема ревизий. Реальные устройства не проверены.
|
||||
|
||||
## Блок 9.13 — история всех разделов (2026-09-29)
|
||||
|
||||
Ошибка/повтор и защита поздних ответов подключены к GRE/Firewall/Filters/рекурсивным маршрутам. Общая схема проверяет записи, сервер и раздел во всех шести потребителях, включая IPsec. Все 36 E2E истории/WireGuard и TypeScript прошли; исходный lint страниц не изменился, новые общие файлы и тест чистые. Результат build — в журнале. Далее — форма инициализации IPsec (handleInit): подтверждение, сохранение ввода и повторные нажатия. Реальные устройства и payload восстановления rules/routes остаются вне проверки этого блока.
|
||||
|
||||
## Блок 9.14 — инициализация IPsec (2026-09-29)
|
||||
|
||||
Проверяются схема сводки, serverId и initialized=true. Ошибка остаётся в форме с введёнными значениями; замок блокирует повтор, редактирование и закрытие во время запроса. Исправлен ввод IPv4, добавлены доступные имена. Новый E2E и 3 теста таблиц прошли, lint/TypeScript чистые. Далее — создание/редактирование пользователей IPsec. Реальные устройства и транзакционность сетевой операции не проверены; последний build — 9.13.
|
||||
|
||||
## Блок 9.15 — пользователи IPsec (2026-09-29)
|
||||
|
||||
Создание проверяет схему клиента, сервер, имя и метод; редактирование требует ok=true. Форма сохраняет ввод и ошибку, блокирует повторы/закрытие/поля до ответа; добавлены доступные имена, сброс peer при смене сервера и проверка нового PSK. Все 7 E2E, lint и TypeScript прошли. Далее — загрузка/повторный экспорт сертификатов и контекст запросов. Реальные устройства и выпуск сертификатов не проверены; последний build — 9.13.
|
||||
|
||||
## Блок 9.16 — сертификаты IPsec (2026-09-29)
|
||||
|
||||
Экспорт по identity/имени проверяет бандл, пароль и Base64; закрытая панель не принимает поздние ответы. Ошибка сохраняет панель для повтора; прежний архив сохраняет свой пароль при ошибке нового экспорта. Пароль только для чтения, скачивание заблокировано при запросе. Все 6 E2E, lint и TypeScript прошли; build — в журнале. Далее — удаление объектов IPsec. Реальный PKCS#12/RouterOS не проверен, сетевой запрос после закрытия не отменяется.
|
||||
|
||||
## Блок 9.17 — удаление IPsec (2026-09-29)
|
||||
|
||||
Удаление клиента/сервера/peer/сертификата требует ok=true; диалог сохраняется при ошибке, блокирует повтор и закрытие до ответа. Принудительное удаление после 409 перенесено из toast в тот же диалог с общей защитой. Все 4 E2E прошли; lint/TypeScript — в журнале. Далее — редактирование peer IPsec. Реальные сетевые последствия не проверены, последний build — 9.16.
|
||||
|
||||
## Блок 9.18 — peer IPsec (2026-09-29)
|
||||
|
||||
Сохранение требует ok=true; ошибка остаётся в форме вместе с вводом. Поля/переключатели, повторы и закрытие блокируются до ответа. Новый E2E, lint и TypeScript прошли. Далее — создание/изменение/удаление GRE. Загрузка данных IPsec и реальная сетевая приёмка остаются открытыми; последний build — 9.16.
|
||||
|
||||
## Блок 9.19 — удаление GRE (2026-09-30)
|
||||
|
||||
Удаление требует ok=true; диалог сохраняет объект/ошибку, блокирует повторы и закрытие во время запроса. Проверки — в журнале. Далее — создание/изменение и переключение GRE. Реальное устройство не проверено, последний build — 9.16.
|
||||
|
||||
## Блок 9.20 — переключение GRE (2026-09-30)
|
||||
|
||||
PATCH требует ok=true; замок блокирует повтор, ожидание и ошибка содержат имя туннеля. Все 3 E2E прошли, новых замечаний lint нет; TypeScript — в журнале. Далее — создание/редактирование GRE. Реальное устройство не проверено, последний build — 9.16.
|
||||
|
||||
## Блок 9.21 — формы GRE (2026-09-30)
|
||||
|
||||
Создание проверяет ok/name либо поля подтверждённого объекта, PATCH требует ok=true. Ошибка сохраняет ввод, поля/повторы/закрытие заблокированы до ответа. Все 6 E2E прошли, остальные проверки — в журнале. Далее — VXLAN: загрузка, ошибка, повтор и URL-контекст. Полная схема GreTunnel, доступность остальных полей и реальные сетевые операции ещё требуют проверки.
|
||||
|
||||
## Блок 9.22 — загрузка VXLAN (2026-09-30)
|
||||
|
||||
Повреждённый контейнер не превращается в пустой список; KPI до успеха неизвестны, ошибка обновления сохраняет данные. Добавлена защита поколением запроса. Прошли 11 E2E в двух прогонах, lint/TypeScript чистые. Далее — частичные сбои опроса VXLAN на backend и сохранение данных по устройству. Полная схема туннеля, отдельные тесты гонок и реальный RouterOS ещё не проверены; последний build — 9.21.
|
||||
|
||||
## Блок 9.23 — частичный сбой VXLAN (2026-09-30)
|
||||
|
||||
API возвращает failures, одиночный endpoint — 502 при сбое; VTEP не маскируется пустым списком. UI сохраняет последние туннели устройства, показывает неизвестное состояние и повтор. Проверены серверная агрегация и 13 E2E, frontend/backend TypeScript и frontend lint прошли. Далее — схема payload и гонки загрузки VXLAN. Счётчик countVxlanTunnels всё ещё возвращает ноль при ошибке, timestamp и запись VXLAN не реализованы; реальные устройства не проверены.
|
||||
|
||||
## Блок 9.24 — проверка данных VXLAN (2026-09-30)
|
||||
|
||||
Схемы отклоняют повреждённые записи/серверы/failures и дубли пары serverId/id. Все 16 E2E, lint и TypeScript прошли, включая поздний успех/ошибку при смене устройства. Далее — операции Firewall, затем Filters. Счётчик ошибок, timestamp и запись VXLAN остаются открытыми, последний build — 9.21; реальные устройства не проверены.
|
||||
|
||||
## Блок 9.25 — переключение Firewall (2026-09-30)
|
||||
|
||||
PATCH правила требует ok=true, замок предотвращает повтор до обновления таблицы; статус/ошибка содержат контекст правила. Все 7 E2E и TypeScript прошли. Grid/тест lint-чистые, исходные замечания страницы сохранены. Далее — address-list и остальные мутации Firewall, общий замок ещё не распространён на них. Реальные устройства не проверены; последний build — 9.21.
|
||||
|
||||
## Блок 9.26 — переключение address-list Firewall (2026-09-30)
|
||||
|
||||
PATCH требует ok=true, общий замок переключений предотвращает повтор до обновления. Ошибка сохраняет состояние записи и содержит адрес/список. Все 9 E2E и TypeScript прошли, новых замечаний lint нет. Далее — сохранение/удаление и перемещение Firewall; единая блокировка всех мутаций пока не внедрена. Реальные устройства не проверены; последний build — 9.21.
|
||||
|
||||
## Блок 9.27 — удаление Firewall (2026-09-30)
|
||||
|
||||
Правила/address-list удаляются через общий диалог с контекстом устройства. DELETE требует ok=true; ошибка сохраняет диалог, повтор и закрытие блокируются до ответа. Все 13 E2E и TypeScript прошли, новых замечаний lint нет. Далее — формы и перемещение Firewall; остальные мутации и гонки загрузки ещё открыты. Реальные устройства не проверены; последний build — 9.21.
|
||||
|
||||
## Блок 9.28 — формы Firewall (2026-09-30)
|
||||
|
||||
POST/PUT правил и address-list требуют ok=true. Ошибка сохраняет форму/ввод, повтор и закрытие блокируются во время запроса. Все 21 E2E и TypeScript прошли, новых замечаний lint нет. Далее — перемещение Firewall; восстановление истории, перемещение и гонки загрузки ещё требуют общей защиты. Реальные устройства не проверены; последний build — 9.21.
|
||||
|
||||
## Блок 9.29 — перемещение Firewall (2026-09-30)
|
||||
|
||||
POST требует ok=true, ошибка возвращает исходный порядок. Общий mutationLock предотвращает конфликтующие операции до обновления списка. Все 23 E2E и TypeScript прошли, новых замечаний lint нет. Далее — общий замок восстановления истории и схема/гонки загрузки Firewall, затем Filters. Реальные устройства не проверены; последний build — 9.21.
|
||||
|
||||
## Блок 9.30 — общий замок истории Firewall (2026-09-30)
|
||||
|
||||
Восстановление удерживает mutationLock до чтения правил и истории, ошибка освобождает замок. История/ручное обновление недоступны во время записи. Прошли 26 разных E2E в двух прогонах, TypeScript и lint тестов; исходные замечания страницы сохранены. Далее — схема/гонки загрузки Firewall, затем Filters. Реальные устройства не проверены; последний build — 9.21.
|
||||
|
||||
## Блок 9.31 — данные Firewall (2026-09-30)
|
||||
|
||||
Схемы отклоняют повреждённые ответы и дубли. Ошибка сохраняет последний список, первоначальные KPI неизвестны. Поколение запросов отменяет старое чтение при начале записи. Все 32 E2E, TypeScript и build (34 страницы) прошли; новых замечаний lint нет. Далее — частичные сбои опроса backend: safeGet/listFirewallAll всё ещё маскируют ошибку пустым списком. Свежесть, дополнительные гонки backend/режима/мутации и реальные устройства ещё не проверены.
|
||||
|
||||
## Блок 9.32 — частичные сбои Firewall (2026-09-30)
|
||||
|
||||
Backend сообщает failures по срезу, неполный snapshot отклоняется и не записывается как observed. UI сохраняет недоступные срезы, показывает неизвестную сводку и блокирует изменения до повторного успеха. Серверный тест, 35 разных E2E в двух прогонах, TypeScript frontend/backend и backend build прошли; новых frontend lint замечаний нет. Далее — свежесть/гонки контекста Firewall, затем Filters. Реальные RouterOS/БД и последствия ошибки снимка после записи ещё требуют приёмки; последний frontend build — 9.31.
|
||||
|
||||
## Блок 9.33 — смена источника Firewall (2026-09-30)
|
||||
|
||||
Состояние пересоздаётся по backend/режиму, старое завершение записи не уведомляет новый экран и не запускает чтение. Прошли 39 E2E в двух прогонах, TypeScript и lint новых файлов; исходные замечания страницы сохранены. Контекстные тесты запускаются отдельно через playwright.firewall-context.config.ts. Далее — свежесть данных Firewall, затем Filters. Реальные устройства не проверены; frontend build — 9.31, backend — 9.32.
|
||||
|
||||
## Блок 9.34 — свежесть Firewall (2026-09-30)
|
||||
|
||||
Время получения сохраняется по срезам: успешные получают новое время, недоступные сохраняют прежнее или остаются неизвестными. Экран показывает диапазон, неизвестные срезы и время данных в предупреждении. Это время браузерного получения, не измерения RouterOS. Все 37 E2E и TypeScript прошли, два профильных теста диапазона повторены; новых замечаний lint нет. Далее — операции Filters. Реальные устройства не проверены; frontend build — 9.31, backend — 9.32.
|
||||
|
||||
## Блок 9.35 — сохранение Filters (2026-09-30)
|
||||
|
||||
Создание и редактирование ожидают ok=true, ошибки сохраняют форму и прежние строки. Блокируются повторы/закрытие, есть inline-ошибка и статус ожидания. Повторное открытие начинает новую форму. Пять профильных E2E, TypeScript и lint новых файлов прошли; исходные замечания страницы сохранены. Далее — CopyRulesSheet: убрать преждевременный done, дождаться применения и сохранить выбор при ошибке. Загрузка/схемы/гонки Filters и реальные устройства ещё не проверены; frontend build — 9.31, backend — 9.32.
|
||||
|
||||
## Блок 9.36 — копирование Filters (2026-09-30)
|
||||
|
||||
Копирование append/replace ожидает подтверждения API; ошибка сохраняет правила, цель и режим. Повторы и закрытие заблокированы до ответа, преждевременный done/таймер удалены. Пять E2E, TypeScript и lint нового теста прошли; исходные замечания страницы сохранены. Далее — подтверждение удаления Filters, затем перемещение и общий замок. Гонки/схемы/загрузка целевого ruleset и реальный маппинг шлюзов остаются открытыми; frontend build — 9.31, backend — 9.32.
|
||||
|
||||
## Блок 9.37 — удаление Filters (2026-09-30)
|
||||
|
||||
Удаление перенесено в AlertDialog с Community/устройством. Ошибка сохраняет подтверждение и строку, повторы/отмена/закрытие заблокированы до ответа, удаление применяется только после ok=true. Семь E2E и TypeScript прошли; новых lint замечаний нет. Далее — перемещение, затем общий замок восстановления/обновления и достоверность загрузки. Реальные устройства не проверены; frontend build — 9.31, backend — 9.32.
|
||||
|
||||
## Блок 9.38 — перемещение Filters (2026-09-30)
|
||||
|
||||
Перемещение по ID ждёт подтверждения и сохраняет порядок/ошибку при отказе. Приоритет и границы поиска берутся из полного списка. Действия таблицы блокируются при операции, повторы защищены синхронным замком. Девять E2E и TypeScript прошли; новых lint замечаний нет. Далее — общий замок восстановления/обновления, затем схемы/гонки/достоверность загрузки. Реальные устройства не проверены; frontend build — 9.31, backend — 9.32.
|
||||
|
||||
## Блок 9.39 — общий замок Filters (2026-09-30)
|
||||
|
||||
Обновление/восстановление используют applyLock, восстановление держит его до чтения правил/истории. Ошибка чтения сохраняет подтверждение и последние строки; чужой ruleset и stale отклоняются. 15 разных E2E в нескольких прогонах и TypeScript прошли; новых lint замечаний нет. Далее — схемы/первоначальная загрузка без моковой подмены, затем гонки и свежесть. Реальные устройства не проверены; frontend build — 9.31, backend — 9.32.
|
||||
|
||||
## Блок 9.40 — загрузка Filters (2026-09-30)
|
||||
|
||||
Схемы валидируют правила/наборы/подтверждения, live-ошибка больше не подставляет моки, есть первоначальная ошибка/повтор и сохранение последних правил. 18 E2E, TypeScript и frontend build (34 страницы) прошли; новых lint замечаний нет. Далее — поколения чтения/изоляция контекста и блокировка записи до свежего чтения выбранного устройства. Начальный GET отдаёт backend-кэш; GRE/recursive payload и ошибки ещё не приняты. Реальные устройства не проверены; backend build — 9.32.
|
||||
|
||||
## Блок 9.41 — гонки чтения выбранного устройства Filters (2026-09-30)
|
||||
|
||||
Запись выбранного устройства требует успешного чтения live=true; кэш остаётся readonly до ответа. Поколение запросов отменяет старый успех/ошибку при переключении, применении и cleanup. 20 E2E и TypeScript прошли, шесть профильных сценариев повторены после уточнения live; новых lint замечаний нет. Далее — изоляция состояния backend/режима и старых мутаций, затем актуальное чтение цели копирования. GRE/recursive и свежесть ещё открыты. Остаток пятичасовой квоты 25%; новый блок не начат. Frontend build — 9.40, backend — 9.32.
|
||||
|
||||
## Блок 9.42 — источник Filters (2026-09-30)
|
||||
|
||||
Состояние пересоздаётся по backend/режиму, старые записи не уведомляют новый экран и не запускают чтение. 26 E2E в двух финальных прогонах и TypeScript прошли; новых lint замечаний нет. Контекстные тесты — playwright.filters-context.config.ts. Далее — актуальный целевой ruleset копирования, затем шлюзы/свежесть. Пользователь разрешил продолжение за резерв 25%. Frontend build — 9.40, backend — 9.32.
|
||||
|
||||
## Блок 9.43 — цель копирования Filters (2026-09-30)
|
||||
|
||||
Live-копирование читает актуальный целевой ruleset под общим замком до PUT. Ошибка/чужой/stale/повреждённый ответ сохраняют форму и не отправляют запись. Десять E2E и TypeScript прошли; новых lint замечаний нет. Далее — схемы/ошибки каталогов шлюзов, затем свежесть. Frontend build — 9.40, backend — 9.32.
|
||||
|
||||
## Блок 9.44 — каталоги шлюзов Filters (2026-09-30)
|
||||
|
||||
Схемы и readiness GRE/recursive сохраняют данные при отказе и блокируют route-сохранение/несопоставленное копирование до повтора. Выборный GRE backend GET возвращает 503 вместо пустого успеха. 12 E2E, повтор двух профильных, TypeScript frontend/backend и оба build прошли. Frontend lint: 0 ошибок/13 прежних предупреждений. Общий GRE GET/реальная БД/RouterOS не приняты. Далее — свежесть и профильная приёмка Filters.
|
||||
|
||||
## Блок 9.45 — свежесть Filters (2026-09-30)
|
||||
|
||||
По устройству показано клиентское время получения правил/GRE/recursive и отдельное подтверждение записи. Ошибка сохраняет время; неизвестный первоначальный срез не получает ложную дату. Десять E2E и TypeScript прошли; новых lint замечаний нет. Далее — клавиатура/телефон и проверенные экраны Filters. Build frontend/backend — 9.44.
|
||||
|
||||
## Блок 9.46 — клавиатура и экраны Filters (2026-09-30)
|
||||
|
||||
- Community использует установленный Base UI Combobox: фильтрация по коду/названию, выбор стрелками/Enter и свободный ввод. Поле связано с подписью, действие отмечено aria-pressed, ошибка объявляется alert; ввод блокируется при сохранении. Tab закрывает подсказки и возвращает доступ к остальным полям формы. При открытом popup Base UI временно ограничивает дерево доступности; тесты проверяют переход Tab, а не обходят его.
|
||||
- Два новых E2E проверяют ПК 1440×1000 и телефон 390×844: отсутствие переполнения документа, выбор устройства на телефоне, валидацию, клавиатурный выбор/ручной ввод и единственный PUT в правильное устройство. Четыре PNG сохранены и просмотрены. Таблица на телефоне использует внутреннюю прокрутку; это не полная приёмка контраста, screen reader или всех форм шлюзов.
|
||||
- 13 E2E прошли: layout/сохранение (4), копирование/актуальная цель/удаление/порядок/свежесть (9). TypeScript прошёл; lint 0 ошибок/13 прежних предупреждений страницы, тесты без замечаний. Build не повторялся, последние frontend/backend — 9.44. Моки HTTP проверяют live-путь; реальные RouterOS/JWT/БД не проверены.
|
||||
- Далее — оставшиеся ограничения этапа 9: первоначальные/частичные сбои IPsec, свежесть VXLAN и ошибки общего GRE-каталога. Этап 9 открыт. Перед новым блоком проверить квоту и журнал; этапы 10–12 не начаты.
|
||||
- Квота после профильных проверок: 96% пятичасовой/15% недельной. Пользователь разрешил работу до конца лимитов. Локальный коммит без push.
|
||||
|
||||
| Образец | Проверенный экран | Применённая композиция |
|
||||
| --- | --- | --- |
|
||||
| ReUI Data Grid Filtering 2 | [Filters ПК](ux-ui/screens/filters-desktop.png), [телефон](ux-ui/screens/filters-mobile.png) | Устройство → свежесть → правила → действие |
|
||||
| ReUI Sheet 8 | [Форма ПК](ux-ui/screens/filters-rule-desktop.png), [телефон](ux-ui/screens/filters-rule-mobile.png) | Community → действие → пояснение → подтверждение API |
|
||||
|
||||
## Блок 9.47 — общая регрессия Filters (2026-09-30)
|
||||
|
||||
- После блоков 9.35–9.46 последовательно прошли 27 E2E стандартной конфигурации и 6 E2E изоляции источника: данные/схемы, ошибки и повтор, каталоги, копирование и актуальная цель, удаление/порядок, история и общий замок, свежесть, гонки выбранного устройства, смена backend/mode, клавиатура и ПК/телефон.
|
||||
- Production build frontend прошёл: контракты, TypeScript, 34 страницы. Последний backend build — 9.44, после него backend не менялся. Lint блока 9.46: 0 ошибок/13 прежних предупреждений. Исходный код в этом блоке не менялся.
|
||||
- Это профильная локальная регрессия Filters по HTTP-фикстурам, не полная регрессия приложения и не приёмка RouterOS/JWT/БД. Этап 9 остаётся открыт; этапы 10–12 не начаты.
|
||||
- Следующий шаг: проверить остаток квоты и последние файлы, разобрать первоначальные/частичные сбои IPsec; затем ограничения VXLAN и общего GRE-каталога. Пользователь разрешил продолжать до конца лимитов; после 33 E2E использовано 98% пятичасовой/15% недельной квоты. Результат сохраняется локальным коммитом без push.
|
||||
|
||||
## Блок 9.48 — состояния чтения IPsec (2026-09-30)
|
||||
|
||||
- listIpsec проверяет контракт, уникальность серверов/клиентов/отказов, конфликт успешного и неответившего устройства и контекст выборного ответа. Повреждённый ответ не меняет данные. IPsec и inventory загружаются независимо через allSettled; список устройств тоже проверяется схемой.
|
||||
- Ошибка всего IPsec сохраняет последние строки; частичный отказ обновляет успешные устройства и сохраняет предыдущие строки/сводки неответивших. Новый подтверждённый пустой ответ удаляет прошлые строки. Постоянный alert даёт повтор; первоначальный отказ не изображает пустую таблицу, KPI неизвестного среза показаны «—»/«неизвестно».
|
||||
- Поколение чтения игнорирует устаревшие ответы; смена mode/backend монтирует отдельное состояние. Поздние записи и доступность действий на сохранённых данных будут проверены следующим блоком, ещё не приняты.
|
||||
- 17 E2E прошли: шесть новых сценариев чтения и 11 прежних операций. Ранее прошли три теста таблиц IPsec/GRE (два новых теста сперва требовали уточнения alert-локатора из-за Next route-announcer, исправлены). TypeScript и lint четырёх файлов чистые. Backend не менялся; последние build frontend — 9.47, backend — 9.44.
|
||||
- Далее — readiness действий, свежесть и гонки IPsec; затем VXLAN/общий GRE. Реальные RouterOS/JWT/БД не проверены. Квота: 0% использования в начале, 4% пятичасовой/16% недельной после проверок. Локальный коммит без push.
|
||||
|
||||
## Блок 9.49 — readiness действий IPsec (2026-09-30)
|
||||
|
||||
- Кнопки клиентов и серверов используют readiness конкретного serverId: требуется успешное чтение, доступный inventory, включённое устройство, отсутствие его failure и текущей загрузки/операции. Сохранённые строки не превращаются в разрешение редактировать/удалять. Успешное устройство остаётся доступным при частичном отказе другого.
|
||||
- Формы создания получают только доступные устройства, уже выполняемый запрос сохраняет список. Submit и удаление дополнительно проверяют readiness перед API. Первоначальный/полный отказ блокирует создание. Refresh во время изменения/восстановления отключён. Серверные операции с неответившим устройством недоступны; просмотр истории не является разрешением восстановления.
|
||||
- Новый E2E проверяет начальный отказ, частичный отказ двух устройств, общий отказ и восстановление с нулём write-запросов; вместе с прежними операциями/таблицами прошло 15 E2E. TypeScript и lint чистые. Табличная IPsec-фикстура теперь содержит реальный inventory устройства вместо пустого списка.
|
||||
- Следующий блок: общий замок/контекст поздних операций, restore/export readiness и свежесть. Backend не менялся; последние build frontend — 9.47, backend — 9.44. Реальные RouterOS/JWT/БД не проверены. Локальный коммит без push.
|
||||
|
||||
## Блок 9.50 — замок и контекст операций IPsec (2026-09-30)
|
||||
|
||||
- Общий синхронный operationLock охватывает инициализацию, создание/редактирование клиентов/peer, удаление и восстановление до последующего чтения. Начало записи инвалидирует предыдущий опрос; внешний refresh при записи не отправляется. Восстановление и экспорт проверяют readiness устройства, ошибки остаются в своих панелях.
|
||||
- Mounted-guard отсекает поздние успехи записи после смены источника: нет старого toast, повторного чтения или открытия сертификата. Ошибка удаления после размонтирования также игнорируется. Уже отправленная операция RouterOS не отменяется и может завершиться на прежнем backend — отмена UI не является отменой сетевой операции.
|
||||
- Успешное удаление закрывает подтверждение даже при отказе последующего опроса; таблица сохраняет последние строки с явной ошибкой чтения и отключёнными действиями до повтора. Проверки не выдают это за неуспешное удаление.
|
||||
- 30 E2E прошли: 6 отдельных тестов backend/mode контекста, 23 регрессии IPsec/истории (включая GRE smoke) и новый сценарий замка/ошибки чтения. TypeScript и lint чистые. Отдельная конфигурация ipsec-context исключена из обычной и использует порт 3101 последовательно.
|
||||
- Далее — клиентская свежесть IPsec и профильные ПК/телефон экраны; затем оставшиеся VXLAN/GRE. Последние build frontend — 9.47, backend — 9.44. Реальные RouterOS/JWT/БД не проверены. Локальный коммит без push.
|
||||
|
||||
## Блок 9.51 — свежесть IPsec (2026-09-30)
|
||||
|
||||
- По выбранному устройству показано клиентское время получения успешного ответа; по всем устройствам — время последнего валидного ответа IPsec, которое не означает успешный опрос каждого роутера. Частичный отказ сохраняет прошлое время неответившего устройства, полный отказ не меняет ни одну дату. До первого успешного результата время неизвестно; время отмечается только для устройств, присутствующих в успешных сводках/клиентах.
|
||||
- Подтверждённые изменения/восстановление показывают отдельный timestamp API с serverId. Он не заменяет последующий опрос. ISO доступен через time.dateTime, title поясняет клиентские часы; даты не сохраняются между перезагрузками, возраст не обновляется таймером.
|
||||
- 8 E2E прошли: данные/схемы, новый тест управляемых часов с выбором устройства и расширенный замок удаления/ошибка опроса с подтверждением записи. TypeScript и lint чистые. Backend не менялся, build пока не повторялся.
|
||||
- Далее — профильная клавиатурная и адаптивная приёмка IPsec, проверенные экраны в плане; затем оставшиеся VXLAN/GRE. Реальные RouterOS/JWT/БД не проверены. Локальный коммит без push.
|
||||
|
||||
## Блок 9.52 — клавиатура и экраны IPsec (2026-09-30)
|
||||
|
||||
- Два E2E проверили ПК 1440×1000 и телефон 390×844: выбор устройства на телефоне, открытие клиента клавиатурой, сохранение через Enter с единственным PATCH в правильный serverId, отсутствие горизонтального переполнения документа, границы формы и серверные действия. Шесть PNG сохранены и просмотрены. Имена клиентов получают title для обрезанного текста.
|
||||
- Первые прогоны уточнили существующее имя поля и дождались штатной анимации Sheet; оба исправленных сценария прошли. Снимок сервера телефона показывает прокрученный контент с кнопками; таблица имеет внутреннюю горизонтальную прокрутку. Это профильная проверка PSK-редактирования, не вся приёмка screen reader/контраста/всех полей.
|
||||
- Production build frontend прошёл (контракты/TypeScript, 34 страницы), lint изменённого компонента/теста чистый. Backend не менялся, последний build — 9.44. Снимки используют HTTP-фикстуры, реальные RouterOS/JWT/БД не проверены.
|
||||
- Далее — оставшиеся ограничения VXLAN: достоверность после общего сбоя, свежесть, режим просмотра и источник; затем ошибки общего GRE-каталога. Этап 9 открыт. Локальный коммит без push.
|
||||
|
||||
| Референс | ПК | Телефон |
|
||||
| --- | --- | --- |
|
||||
| [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | [Клиенты](ux-ui/screens/ipsec-desktop.png) | [Клиенты](ux-ui/screens/ipsec-mobile.png) |
|
||||
| [Sheet 8](https://reui.io/preview/base/sheet-8?ref=mcp) | [Форма клиента](ux-ui/screens/ipsec-client-desktop.png) | [Форма клиента](ux-ui/screens/ipsec-client-mobile.png) |
|
||||
| [List 9](https://reui.io/preview/base/list-9?ref=mcp) | [Серверы](ux-ui/screens/ipsec-servers-desktop.png) | [Сервер](ux-ui/screens/ipsec-servers-mobile.png) |
|
||||
|
||||
## Блок 9.53 — достоверность VXLAN и режим просмотра (2026-09-30)
|
||||
|
||||
- Backend VXLAN предоставляет GET; удалены активные кнопки без обработчиков (создание/редактирование/включение/удаление). Экран явно отмечен «Только просмотр»; доступны опрос и экспорт .rsc. Новые сетевые write-операции в этом блоке не вводились.
|
||||
- При полном отказе сохранённые строки получают неизвестный статус, KPI не выдают старый UP за актуальное значение. Первоначальная ошибка не показывает ложную пустую таблицу. Ошибка сохраняется до успешного повтора, время успешного чтения — по устройствам; частичный отказ не обновляет дату неответившего устройства. Даты клиентские, общий ответ не гарантирует успешный опрос каждого устройства.
|
||||
- Экспорт фиксирует строку, metadata сервера, дату и признак неизвестной актуальности на момент открытия; обновление таблицы не меняет открытый код. Mock-экспорт подписан отдельно. Смена backend/mode отделяет состояние, панели и даты; URL-контекст сохранён.
|
||||
- После последних изменений прошли 17 обычных E2E VXLAN и 4 отдельных E2E смены источника. TypeScript и lint чистые. Backend не менялся; последний frontend build — 9.52, backend — 9.44.
|
||||
- Далее — точность/экранирование .rsc VXLAN и валидация согласованности ответа, затем ошибки общего GRE-каталога и общая регрессия этапа 9. Реальная RouterOS-приёмка/полные права/DB/JWT не выполнены. Локальный коммит без push.
|
||||
|
||||
## Блок 9.54 — корректный фрагмент .rsc VXLAN (2026-09-30)
|
||||
|
||||
- Генератор вынесен в lib/vxlan-export.ts. Строки RouterOS заключены в кавычки; кавычка/обратный слеш/dollar и управляющие символы экранируются. Заголовки не содержат переводов строки из имени/metadata. Числовые параметры идут из валидированной модели.
|
||||
- По документации MikroTik используются port, learning, arp и доступный local-address. Удалены неподдерживаемые vtep-mac-address/arp-proxy/mac-learning, read-only l2mtu и выдуманная команда привязки к bridge. Это фрагмент интерфейса/статических VTEP; bridge/FDB/прочие параметры, которых нет в API, не включены. Импорт на RouterOS ещё не проверен.
|
||||
- Backend возвращает точный arpMode, обычный arp=enabled больше не означает proxy ARP. Обрабатывается learning=no. Точный arp приоритетен над legacy arp-proxy. Новое поле optional на frontend для совместимости прежних ответов; при его отсутствии старый boolean может описать только proxy-arp/обычный enabled.
|
||||
- Unit генератора проверяет сложные строки и отсутствие посторонних команд/недоступных параметров; backend unit проверяет все ARP modes и частичный опрос. TypeScript frontend/backend, frontend lint, 2 E2E экспорта/свежести и backend build прошли. Последний frontend build — 9.52.
|
||||
- Источники: [VXLAN](https://help.mikrotik.com/docs/spaces/ROS/pages/100007937/VXLAN), [строковые литералы RouterOS](https://help.mikrotik.com/docs/spaces/ROS/pages/47579229/Scripting). Далее — согласованность ответа VXLAN, экраны и общая проверка, затем GRE-каталог. Локальный коммит без push.
|
||||
|
||||
## Блок 9.55 — согласованность ответов IPsec/VXLAN (2026-09-30)
|
||||
|
||||
- IPsec дополнительно отклоняет чужой serverId вложенных peer/pool/shared-mode-config, повторные peer/сертификаты и отказ с пустым serverId. VXLAN отклоняет повторные failures, одновременные tunnel/failure одного устройства, несогласованные arpMode/arpProxy и повторные ID inventory. Прежние схемы payload и контекст выборного IPsec ответа сохранены.
|
||||
- Противоречивый ответ целиком считается ошибкой чтения и не заменяет последние подтверждённые строки; вложенный объект не переносится под другой сервер. Старые ответы без arpMode совместимы.
|
||||
- 24 E2E прошли: расширенные повреждённые/чужие payload IPsec и регрессия ссылок/сбоев/гонок VXLAN. TypeScript и lint четырёх файлов чистые. Backend в этом блоке не менялся; последний backend build — 9.54, frontend — 9.52.
|
||||
- Далее — ошибки общего GRE-каталога и его потребители, затем экраны VXLAN/сводная регрессия этапа 9. Реальные RouterOS/JWT/БД не проверены. Локальный коммит без push.
|
||||
|
||||
## Блок 9.56 — ошибки общего GRE-каталога (2026-09-30)
|
||||
|
||||
- Общий GET /filters/gre-tunnels больше не превращает ошибку устройства в пустой успешный каталог: возвращает tunnels успешных устройств и failures с serverId/name/error. Опрос вынесен в тестируемый pollGreCatalog; чужой контекст строки считается отказом исходного устройства. Выборный успешный/503 путь сохранён.
|
||||
- Явный невалидный serverId получает HTTP 400 до БД и не переключает запрос на все устройства. Нет изменений сетевого применения. Дополнительное поле failures совместимо с прежними потребителями, но карта сети/оповещения пока его игнорируют — их состояния входят в этапы 10/11 и не приняты этим блоком.
|
||||
- Unit опроса проверил mixed/empty/all-failed/foreign/нет устройств; Fastify inject с production Zod compiler проверил четыре невалидных ID без запросов DB/RouterOS. TypeScript/backend build и lint новых файлов прошли. Тесты добавлены в test:live-maps. HTTP успех/503 с настоящей БД остаются внешней приёмкой.
|
||||
- Далее — состояния/схемы/частичные отказы экрана GRE (он использует /gre/tunnels, уже имеющий failures), затем его readiness и контекст. Этап 9 открыт; локальный коммит без push.
|
||||
|
||||
## Блок 9.57 — устройства без снимка мониторинга (2026-09-30)
|
||||
|
||||
- IPsec/VXLAN принимают законный status: null из /servers до первого опроса, а также прежний ответ без status. В rail такой статус обозначен «Статус неизвестен»; он не выдаётся за online/offline и не делает успешный VPN-опрос ошибкой. Внутренний совместимый Server DTO сохраняет fallback, но отображение использует отдельный признак monitoringUnknown. Filters/Firewall уже принимают null.
|
||||
- 14 E2E прошли, включая четыре новых HTTP-сценария null/missing и регрессию ошибок/частичных отказов IPsec/VXLAN. TypeScript и lint чистые. Реальные устройства не опрашивались.
|
||||
- Далее — состояния данных GRE, затем readiness, изоляция операций и свежесть. Локальный коммит без push.
|
||||
|
||||
|
||||
## Блок 9.58 — достоверность чтения GRE (2026-09-30)
|
||||
|
||||
- Добавлена схема GRE с IPsec/PSK, уникальными составными serverId/id, уникальными failures и запретом одновременного успеха/отказа устройства. Inventory валидируется и принимает null мониторинга; rail показывает неизвестный статус. Ошибочный ответ не заменяет подтверждённые данные.
|
||||
- Частичный отказ сохраняет строки отказавшего включённого устройства, успешный пустой опрос удаляет их. Постоянный alert содержит причину и повтор; начальный отказ не выглядит как отсутствие туннелей. Неполная сводка — неизвестная, отказавшие строки — «Неизвестно», фильтр активных исключает неподтверждённые статусы. Source/URL key и epoch исключают поздний результат чтения другого контекста.
|
||||
- 22 E2E прошли: восемь сценариев данных плюс ссылки/формы/удаление/переключение. TypeScript и lint чистые. Удалены остатки неиспользуемых UI-хелперов; таблица использует стабильный составной ID.
|
||||
- На время частичного отказа изменения пока блокируются для всего GRE. Следующий блок — readiness каждого устройства, общий lock записи и поздние результаты операций. Live-пулы/экспорт требуют дальнейшей проверки. Локальный коммит без push.
|
||||
|
||||
|
||||
## Блок 9.59 — готовность и изоляция операций GRE (2026-09-30)
|
||||
|
||||
- Запись разрешена только после успешного чтения inventory/GRE на включённом устройстве без его failure. Частичный отказ не блокирует исправное устройство; меню и выбор сервера показывают недоступность отказавшего/выключенного. Проверка повторяется непосредственно перед запросом.
|
||||
- Общий синхронный lock объединяет создание/редактирование, переключение, удаление и восстановление до последующего опроса. Ручное обновление заблокировано во время записи; после API-ошибки возможен повтор, после подтверждённого удаления и отказа чтения диалог закрывается, старые строки остаются неизвестными. Позднее завершение старого контекста не вызывает toast/опрос/ошибку в новом. Уже отправленная операция не отменяется сменой страницы.
|
||||
- Проверено 25 различных E2E: 11 истории, три формы, пять readiness/delete/toggle и шесть поздних ответов в отдельной source-конфигурации. TypeScript и lint чистые. Проверки обнаружили и устранили незавершённое освобождение lock в delete/toggle; повтор прошёл.
|
||||
- Далее — временные отметки и экспорт GRE, достоверность live-пулов, desktop/mobile приёмка. JWT/RouterOS остаются внешней приёмкой. Локальный коммит без push.
|
||||
|
||||
|
||||
## Блок 9.60 — свежесть и снимок экспорта GRE (2026-09-30)
|
||||
|
||||
- Успешный ответ каталога и опрос каждого включённого устройства имеют отдельные отметки получения браузером. При failures отметка устройства сохраняется, при глобальной ошибке не обновляется. Подтверждение API записи/восстановления показано отдельно от опроса. Эти отметки не объявляются временем измерения RouterOS.
|
||||
- Экспорт фиксирует туннель, имена устройств, время и актуальность при открытии. Фоновый опрос не меняет уже открытый код/контекст; устаревший статус — неизвестный, mock явно подписан. Source/URL смена закрывает прежний снимок.
|
||||
- 11 E2E прошли: часы/частичный и полный отказ/восстановление/экспорт плюс readiness и данные. TypeScript и lint экрана чистые.
|
||||
- Далее — корректность самого GRE .rsc и параметров формы, реальные возможности live-пулов и desktop/mobile. Локальный коммит без push.
|
||||
|
||||
|
||||
## Блок 9.61 — поддерживаемые параметры GRE/PSK и .rsc (2026-09-30)
|
||||
|
||||
- GRE .rsc вынесен в generateGreRsc: quoted RouterOS strings/PSK, нормализованные комментарии, локальный IP только при наличии, без придуманных удалённых IP/маршрутов и дополнительных manual IPsec peer/policy/proposal поверх автоматического ipsec-secret. Параметры сверены с https://help.mikrotik.com/docs/spaces/ROS/pages/24805531/GRE и правилами Scripting. FastPath в снимке не меняется автоматически; несовместимый IPsec/FastPath подписан в комментарии.
|
||||
- Из формы удалены IKE/алгоритмы/DH/PFS/lifetime, которые API не принимает; доступный PSK и пределы формы объяснены. Отключение IPsec отправляет пустой ipsecSecret, иначе PATCH сохранял старый PSK. Переключатели и показ PSK получили доступные имена; FormToggle поддерживает необязательный ariaLabel. Подсказка FastPath больше не обещает аппаратное ускорение.
|
||||
- Unit экспорта проверил строки/инъекцию новой команды/optional IP/no duplicate IPsec; шесть E2E PSK/create/edit/export прошли. TypeScript/lint чистые. RouterOS применение и реальное снятие PSK остаются внешней приёмкой.
|
||||
- Далее — достоверное отображение live-пулов и возможности API, затем layout и профильная регрессия GRE/VXLAN. Локальный коммит без push.
|
||||
|
||||
|
||||
## Блок 9.62 — возможности API GRE-пулов (2026-09-30)
|
||||
|
||||
- Удалён фиктивный live-каталог из poolId интерфейсов: он не содержит CIDR/ёмкость, но раньше изображал полное заполнение и свободные блоки. Live KPI пулов теперь неизвестен с подписью «нет данных API», раздел объясняет отсутствие каталога/управления. Инвентаризация настоящих /ip/pool и её API не изобретены.
|
||||
- Убраны кнопки создания пула, пустые меню изменения/удаления и selector пула, который не входил в GRE write-body. Mock-каталог остаётся только для просмотра с явной подписью; настройки локального IP остаются доступными. Кнопки разделов получили aria-pressed и имя группы.
|
||||
- Семь E2E прошли: числовая сортировка/поиск 12 туннелей, отсутствие подмены неизвестных пулов пустыми, mock-каталог/no writes и три формы. TypeScript/lint чистые.
|
||||
- Далее — desktop/mobile GRE/VXLAN и профильная регрессия. Расширение backend настоящим управлением адресными пулами — отдельный функциональный объём, текущий UX честно отражает доступные API. Локальный коммит без push.
|
||||
|
||||
|
||||
## Блок 9.63 — приёмка GRE/VXLAN и мобильные панели (2026-09-30)
|
||||
|
||||
- GRE/VXLAN используют компактную сводку в две колонки на телефоне и краткие подписи. GRE KPI теперь относится к выбранному устройству/туннелю, а не глобальному списку. Неизвестная сводка учитывает выбранный срез. Для этого KpiStatGrid получил необязательный gridClassName; существующие потребители сохраняют прежнюю раскладку.
|
||||
- Форма GRE и экспорт имеют ширину телефона; footer больше не обрезает «Копировать». На ПК панели ограничены шириной lg. GRE-поля получили доступные имена, optional IP не помечены обязательными; пустой site не выводит скобки. Убраны устаревшие справочные команды VXLAN arp-proxy/mac-learning и лишний баннер GRE; справка ведёт к MikroTik. VXLAN не обещает шифрование через обычный GRE.
|
||||
- Просмотрены восемь PNG в docs/ux-ui/screens: GRE/VXLAN и формы/экспорт для ПК/телефона. Четыре сценария keyboard/layout проверили точный serverId/VNI, сохранение, отсутствие переполнения, полную мобильную ширину и границы кнопок footer. Общая регрессия этапа 9: 183 E2E прошли (source-конфигурации проверяются отдельно). Production frontend build — 34 страницы; TypeScript/lint/diff-check чистые. Backend test:live-maps, test:config-sync и unit экспортов прошли.
|
||||
- Перегенерированные прежние Filters/IPsec PNG восстановлены к своим закоммиченным вариантам; новых продуктовых изменений там нет. Далее — отдельное исправление serverId GRE API и фиксация границ завершения этапа 9. Реальные RouterOS/JWT/БД не проверены. Локальный коммит без push.
|
||||
|
||||
|
||||
## Блок 9.64 — завершение локальной приёмки этапа 9 (2026-09-30)
|
||||
|
||||
- GET /gre/tunnels отклоняет явный невалидный serverId с HTTP 400 до БД/RouterOS вместо опроса всех устройств. Fastify inject проверил пять ID (включая пустой) для прямого GRE и общего Filters-каталога; TypeScript/backend build/lint прошли. Успешный и реальный выборный опрос требуют внешнего окружения.
|
||||
- После 183 общей E2E регрессии прошли ещё 26 source-сценариев: Firewall 4, Filters 6, IPsec 6, GRE 6, VXLAN 4; отдельные Next-серверы запускались последовательно. Итого 209 сценариев последней приёмки этапа 9. Production frontend build — 34 страницы, backend build и unit каталогов/планов/экспортов чистые.
|
||||
- Этап 9 завершён в границах локальной приёмки: операции показывают подтверждение API, ошибка сохраняет ввод/последние данные, повтор защищён, выбранное устройство не подменяется другим контекстом, unavailable API не выдаёт фиктивные действия/числа. ReUI Frame/base-nova и установленные компоненты сохранены; новые registry-компоненты не устанавливались.
|
||||
- Ограничения: HTTP fixtures не проверяют RouterOS/JWT/БД, сетевое применение и транзакционность составных операций; VXLAN доступен только для чтения/экспорта, live-пулы GRE не представлены API. Эти ограничения явно отображаются/описаны. Общий GRE failures ещё надо использовать в карте сети (этап 10) и оповещениях (11Б). Адаптивность проверена на 390px/1440px, полный accessibility/performance аудит — этап 12.
|
||||
- Следующий шаг — 10.1: карта API/референсы этапа 10, затем достоверный опрос BGP. Выявлено: /bgp/sessions возвращает [] при отказе устройства, /ospf/all скрывает частичные ошибки, карта/оптимизатор превращают отказ каталогов в пустые данные. Полные детали и порядок будут сохранены в docs/ux-ui-stage-10.md. Локальный коммит без push.
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,278 @@
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
"block": "12.5.205",
|
||||
"runtime": {
|
||||
"backend": "ux-lock200",
|
||||
"frontend": "ux-portal199"
|
||||
},
|
||||
"actualPortalJWT": true,
|
||||
"apiMocks": false,
|
||||
"scope": [
|
||||
"#main-content",
|
||||
"[aria-label=\"Основная навигация\"]"
|
||||
],
|
||||
"tags": [
|
||||
"wcag2a",
|
||||
"wcag2aa",
|
||||
"wcag21a",
|
||||
"wcag21aa",
|
||||
"wcag22aa"
|
||||
],
|
||||
"cases": [
|
||||
{
|
||||
"path": "/traffic",
|
||||
"theme": "light",
|
||||
"width": 1440,
|
||||
"passes": 22,
|
||||
"incomplete": 2,
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"nodes": [
|
||||
{
|
||||
"target": [
|
||||
".dark\\:border-input"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 3.65 (foreground color: #7e8083, background color: #f4f6f9, font size: 9.6pt (12.8px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".bg-primary\\/5 > .mt-2.justify-between.gap-2 > .text-\\[11px\\].gap-1:nth-child(1) > .text-emerald-500.font-mono.font-medium"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 2.07 (foreground color: #00bc7d, background color: #e9ebee, font size: 8.3pt (11px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".bg-primary\\/5 > .mt-2.justify-between.gap-2 > .text-\\[11px\\].gap-1:nth-child(2) > .text-blue-500.font-mono.font-medium"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 3.14 (foreground color: #2b7fff, background color: #e9ebee, font size: 8.3pt (11px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".bg-card > .mt-2.justify-between.gap-2 > .text-\\[11px\\].gap-1:nth-child(1) > .text-emerald-500.font-mono.font-medium"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 2.47 (foreground color: #00bc7d, background color: #ffffff, font size: 8.3pt (11px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".bg-card > .mt-2.justify-between.gap-2 > .text-\\[11px\\].gap-1:nth-child(2) > .text-blue-500.font-mono.font-medium"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 3.76 (foreground color: #2b7fff, background color: #ffffff, font size: 8.3pt (11px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/alerts",
|
||||
"theme": "light",
|
||||
"width": 1440,
|
||||
"passes": 23,
|
||||
"incomplete": 1,
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"nodes": [
|
||||
{
|
||||
"target": [
|
||||
".leading-none"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
"summary"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".\\[overflow-wrap\\:anywhere\\]"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
"strong"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: bold). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".\\[\\&_p\\]\\:leading-relaxed > p:nth-child(2)"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".underline"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/backups",
|
||||
"theme": "light",
|
||||
"width": 1440,
|
||||
"passes": 26,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/traffic",
|
||||
"theme": "light",
|
||||
"width": 320,
|
||||
"passes": 22,
|
||||
"incomplete": 1,
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"nodes": [
|
||||
{
|
||||
"target": [
|
||||
".bg-primary\\/5 > .mt-2.justify-between.gap-2 > .text-\\[11px\\].gap-1.items-center:nth-child(1) > .text-emerald-500.font-mono"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 2.07 (foreground color: #00bc7d, background color: #e9ebee, font size: 8.3pt (11px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".bg-primary\\/5 > .mt-2.justify-between.gap-2 > .text-\\[11px\\].gap-1.items-center:nth-child(2) > .text-blue-500.font-mono"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 3.14 (foreground color: #2b7fff, background color: #e9ebee, font size: 8.3pt (11px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".bg-card > .mt-2.justify-between.gap-2 > .text-\\[11px\\].gap-1.items-center:nth-child(1) > .text-emerald-500.font-mono"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 2.47 (foreground color: #00bc7d, background color: #ffffff, font size: 8.3pt (11px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".bg-card > .mt-2.justify-between.gap-2 > .text-\\[11px\\].gap-1.items-center:nth-child(2) > .text-blue-500.font-mono"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 3.76 (foreground color: #2b7fff, background color: #ffffff, font size: 8.3pt (11px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/alerts",
|
||||
"theme": "light",
|
||||
"width": 320,
|
||||
"passes": 23,
|
||||
"incomplete": 0,
|
||||
"violations": [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"nodes": [
|
||||
{
|
||||
"target": [
|
||||
".leading-none"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
"summary"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".\\[overflow-wrap\\:anywhere\\]"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
"strong"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: bold). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".\\[\\&_p\\]\\:leading-relaxed > p:nth-child(2)"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
},
|
||||
{
|
||||
"target": [
|
||||
".underline"
|
||||
],
|
||||
"summary": "Fix any of the following:\n Element has insufficient color contrast of 4.32 (foreground color: #bb4d00, background color: #f5ede0, font size: 10.5pt (14px), font weight: normal). Expected contrast ratio of 4.5:1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/backups",
|
||||
"theme": "light",
|
||||
"width": 320,
|
||||
"passes": 24,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/traffic",
|
||||
"theme": "dark",
|
||||
"width": 1440,
|
||||
"passes": 23,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/alerts",
|
||||
"theme": "dark",
|
||||
"width": 1440,
|
||||
"passes": 23,
|
||||
"incomplete": 1,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/backups",
|
||||
"theme": "dark",
|
||||
"width": 1440,
|
||||
"passes": 26,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/traffic",
|
||||
"theme": "dark",
|
||||
"width": 320,
|
||||
"passes": 22,
|
||||
"incomplete": 1,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/alerts",
|
||||
"theme": "dark",
|
||||
"width": 320,
|
||||
"passes": 23,
|
||||
"incomplete": 0,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/backups",
|
||||
"theme": "dark",
|
||||
"width": 320,
|
||||
"passes": 24,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
}
|
||||
],
|
||||
"passed": false,
|
||||
"bounds": [
|
||||
"Automated tagged DOM audit; not a complete WCAG certification",
|
||||
"Admin only, default visible state; dialogs and native mutation scenarios not covered"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
"block": "12.5.205",
|
||||
"sourceFilesMatched": 527,
|
||||
"productionBuildPassed": true,
|
||||
"frontendImage": "mmapp-test/frontend:ux-accessibility205",
|
||||
"imageId": "sha256:8f1eccf07d4d562a9100397806609a994280c3edf16a8a84b7cee5cbf98466ef8",
|
||||
"backendImage": "mmapp-test/backend:ux-lock200",
|
||||
"rollbackFrontendTag": "ux-portal199",
|
||||
"vendorFilesChanged": 0,
|
||||
"knownUserScreensPreserved": 8
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
"block": "12.5.205",
|
||||
"stats": {
|
||||
"startTime": "2026-10-13T09:43:05.106Z",
|
||||
"duration": 34060.263,
|
||||
"expected": 25,
|
||||
"skipped": 0,
|
||||
"unexpected": 0,
|
||||
"flaky": 0
|
||||
},
|
||||
"errors": [],
|
||||
"scope": "alerts target issues + shell tagged accessibility/keyboard/layers fixtures, not live production"
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
"block": "12.5.205",
|
||||
"runtime": {
|
||||
"backend": "ux-lock200",
|
||||
"frontend": "ux-accessibility205"
|
||||
},
|
||||
"actualPortalJWT": true,
|
||||
"apiMocks": false,
|
||||
"scope": [
|
||||
"#main-content",
|
||||
"[aria-label=\"Основная навигация\"]"
|
||||
],
|
||||
"tags": [
|
||||
"wcag2a",
|
||||
"wcag2aa",
|
||||
"wcag21a",
|
||||
"wcag21aa",
|
||||
"wcag22aa"
|
||||
],
|
||||
"cases": [
|
||||
{
|
||||
"path": "/traffic",
|
||||
"theme": "light",
|
||||
"width": 1440,
|
||||
"passes": 22,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/alerts",
|
||||
"theme": "light",
|
||||
"width": 1440,
|
||||
"passes": 23,
|
||||
"incomplete": 1,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/backups",
|
||||
"theme": "light",
|
||||
"width": 1440,
|
||||
"passes": 26,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/traffic",
|
||||
"theme": "light",
|
||||
"width": 320,
|
||||
"passes": 22,
|
||||
"incomplete": 1,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/alerts",
|
||||
"theme": "light",
|
||||
"width": 320,
|
||||
"passes": 23,
|
||||
"incomplete": 0,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/backups",
|
||||
"theme": "light",
|
||||
"width": 320,
|
||||
"passes": 24,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/traffic",
|
||||
"theme": "dark",
|
||||
"width": 1440,
|
||||
"passes": 22,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/alerts",
|
||||
"theme": "dark",
|
||||
"width": 1440,
|
||||
"passes": 23,
|
||||
"incomplete": 1,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/backups",
|
||||
"theme": "dark",
|
||||
"width": 1440,
|
||||
"passes": 26,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/traffic",
|
||||
"theme": "dark",
|
||||
"width": 320,
|
||||
"passes": 22,
|
||||
"incomplete": 1,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/alerts",
|
||||
"theme": "dark",
|
||||
"width": 320,
|
||||
"passes": 23,
|
||||
"incomplete": 0,
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"path": "/backups",
|
||||
"theme": "dark",
|
||||
"width": 320,
|
||||
"passes": 24,
|
||||
"incomplete": 2,
|
||||
"violations": []
|
||||
}
|
||||
],
|
||||
"passed": true,
|
||||
"bounds": [
|
||||
"Automated tagged DOM audit; not a complete WCAG certification",
|
||||
"Admin only, default visible state; dialogs and native mutation scenarios not covered"
|
||||
],
|
||||
"waitForTrafficRefreshEnabled": true
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.250",
|
||||
"domain": "pngs.top",
|
||||
"checks": [
|
||||
{
|
||||
"endpoint": "/user/tokens/verify",
|
||||
"status": 200,
|
||||
"success": true,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"endpoint": "/zones?name=pngs.top",
|
||||
"status": 200,
|
||||
"success": true,
|
||||
"errors": []
|
||||
}
|
||||
],
|
||||
"tokenActive": true,
|
||||
"zoneActive": true,
|
||||
"accountMatched": true,
|
||||
"nameservers": [
|
||||
"cheryl.ns.cloudflare.com",
|
||||
"doug.ns.cloudflare.com"
|
||||
],
|
||||
"originalFqdnRecords": 0,
|
||||
"originalChallengeRecords": 0,
|
||||
"fqdn": "mmt250-c22a9715.pngs.top",
|
||||
"applicationTxtCleanupConfirmed": true,
|
||||
"ownARecordDeleted": true,
|
||||
"finalFqdnRecords": 0,
|
||||
"finalChallengeRecords": 0
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.250",
|
||||
"fqdn": "mmt250-c22a9715.pngs.top",
|
||||
"certName": "mmt250-c22a9715",
|
||||
"serverId": "2",
|
||||
"realPortalLogin": true,
|
||||
"noMocks": true,
|
||||
"issuePosts": 1,
|
||||
"pageErrors": [],
|
||||
"settings": {
|
||||
"testStatus": 200,
|
||||
"testOk": true,
|
||||
"saveStatus": 200,
|
||||
"tokenConfigured": true,
|
||||
"directoryUrl": "https://acme-v02.api.letsencrypt.org/directory"
|
||||
},
|
||||
"jobId": "8046a992-c5cd-4c1b-b343-6cb4ffd9a597",
|
||||
"accepted": true,
|
||||
"job": {
|
||||
"id": "8046a992-c5cd-4c1b-b343-6cb4ffd9a597",
|
||||
"status": "done",
|
||||
"step": "done"
|
||||
},
|
||||
"uiTerminalConfirmed": true,
|
||||
"postCleanup": {
|
||||
"tokenConfigured": false,
|
||||
"ownJobStatus": 404,
|
||||
"reachableServerIds": [
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"ownCertificateAbsent": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.250",
|
||||
"fqdn": "mmt250-c22a9715.pngs.top",
|
||||
"targetHost": "104.165.244.7",
|
||||
"nativePrivateKeyConfirmedBeforeCleanup": true,
|
||||
"servicesApplied": [
|
||||
"www-ssl",
|
||||
"api-ssl"
|
||||
],
|
||||
"servicesRestored": true,
|
||||
"originalCertificateCollectionMatched": true,
|
||||
"originalFileCollectionMatched": true,
|
||||
"originalNormalizedExportMatched": true,
|
||||
"acmeSettingsRestored": true,
|
||||
"ownIssueJobRemoved": true,
|
||||
"cleanupValidationRepair": "PG Date objects compared after JSON normalization; no device operation replayed",
|
||||
"passwordChanges": 0
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.250",
|
||||
"fqdn": "mmt250-c22a9715.pngs.top",
|
||||
"addresses": [
|
||||
"104.165.244.7"
|
||||
],
|
||||
"tls": {
|
||||
"authorized": true,
|
||||
"protocol": "TLSv1.2",
|
||||
"remoteAddress": "104.165.244.7",
|
||||
"subjectAltName": "DNS:mmt250-c22a9715.pngs.top",
|
||||
"issuer": "YR2",
|
||||
"fingerprint256": "6A:21:31:D7:C7:02:F8:4D:C9:95:23:7F:1A:3C:84:D4:68:C7:7D:A2:D2:7B:C2:E7:09:D3:5D:F8:ED:2D:C9:BE",
|
||||
"validFrom": "Oct 14 11:32:10 2026 GMT",
|
||||
"validUntil": "Jan 12 11:32:09 2027 GMT"
|
||||
},
|
||||
"restHttpsStatus": 200,
|
||||
"passwordChanged": false
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.253",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"serverId": "2",
|
||||
"nativeTarget": "104.165.244.7",
|
||||
"readOnlyPreflight": {
|
||||
"exactDomainRecords": 0,
|
||||
"challengeRecords": 0,
|
||||
"chrRestStatus": [
|
||||
200,
|
||||
200
|
||||
],
|
||||
"writes": 0
|
||||
},
|
||||
"comparator": {
|
||||
"positive": 1,
|
||||
"negative": 11,
|
||||
"passed": true,
|
||||
"networkCalls": 0
|
||||
},
|
||||
"syntax": "passed",
|
||||
"scopedLint": "passed",
|
||||
"realRenewalExecuted": false,
|
||||
"productionRuntimeChanged": false
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.254",
|
||||
"domain": "pngs.top",
|
||||
"checks": [
|
||||
{
|
||||
"endpoint": "/user/tokens/verify",
|
||||
"status": 200,
|
||||
"success": true,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"endpoint": "/zones?name=pngs.top",
|
||||
"status": 200,
|
||||
"success": true,
|
||||
"errors": []
|
||||
}
|
||||
],
|
||||
"tokenActive": true,
|
||||
"zoneActive": true,
|
||||
"accountMatched": true,
|
||||
"nameservers": [
|
||||
"cheryl.ns.cloudflare.com",
|
||||
"doug.ns.cloudflare.com"
|
||||
],
|
||||
"originalFqdnRecords": 0,
|
||||
"originalChallengeRecords": 0,
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"applicationTxtCleanupConfirmed": true,
|
||||
"ownARecordDeleted": true,
|
||||
"finalFqdnRecords": 0,
|
||||
"finalChallengeRecords": 0
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.254",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"serverId": "2",
|
||||
"realPortalLogin": true,
|
||||
"noMocks": true,
|
||||
"issuePosts": 1,
|
||||
"pageErrors": [],
|
||||
"settings": {
|
||||
"testStatus": 200,
|
||||
"testOk": true,
|
||||
"saveStatus": 200,
|
||||
"tokenConfigured": true,
|
||||
"directoryUrl": "https://acme-v02.api.letsencrypt.org/directory"
|
||||
},
|
||||
"jobId": "9ebd9d18-b746-47fb-b6da-8c887ccda4e0",
|
||||
"accepted": true,
|
||||
"job": {
|
||||
"id": "9ebd9d18-b746-47fb-b6da-8c887ccda4e0",
|
||||
"status": "done",
|
||||
"step": "done"
|
||||
},
|
||||
"uiTerminalConfirmed": true,
|
||||
"postCleanup": {
|
||||
"tokenConfigured": false,
|
||||
"ownJobStatus": 404,
|
||||
"reachableServerIds": [
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"ownCertificateAbsent": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.254",
|
||||
"certificatesBaselineMatched": true,
|
||||
"fileStableMetadataBaselineMatched": true,
|
||||
"flashDirectoryLastModifiedExcluded": true,
|
||||
"configuredServicesBaselineMatched": true,
|
||||
"dynamicServiceConnectionsExcluded": true,
|
||||
"normalizedExportMatched": true,
|
||||
"passwordChanged": false
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.254",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"renewalExecuted": false,
|
||||
"reason": "Native certificate dates have no timezone; canonical state is unknown, renewal guard preserved",
|
||||
"observed": {
|
||||
"status": "unknown",
|
||||
"daysLeft": null,
|
||||
"validFrom": null,
|
||||
"validUntil": null,
|
||||
"rawValidFrom": "2026-10-14 15:37:47",
|
||||
"rawValidUntil": "2027-01-12 15:37:46"
|
||||
},
|
||||
"settingsBaselineRestored": true,
|
||||
"schedulerRefreshed": true,
|
||||
"ownJobRemoved": true,
|
||||
"privateBaselinesRemoved": true,
|
||||
"clockCalibration": {
|
||||
"timeZoneName": "Europe/Warsaw",
|
||||
"gmtOffset": "+02:00",
|
||||
"autoDetect": true,
|
||||
"nativeValidFrom": "2026-10-14 15:37:47",
|
||||
"tlsValidFromUtc": "2026-10-14T13:37:47Z",
|
||||
"nativeValidUntil": "2027-01-12 15:37:46",
|
||||
"tlsValidUntilUtc": "2027-01-12T13:37:46Z",
|
||||
"bothMatchCurrentGmtOffset": true,
|
||||
"warning": "Do not assume UTC or apply the future Warsaw winter offset to certificate display; both native endpoints use observed current +02:00 in this sample"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"sampledAt": "2026-10-14T14:37:23.294Z",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"remoteAddress": "104.165.244.7",
|
||||
"authorized": true,
|
||||
"hostnameMatched": true,
|
||||
"protocol": "TLSv1.2",
|
||||
"fingerprint256": "89:B6:BD:15:85:7A:AA:54:8A:26:13:7F:ED:63:78:AA:27:50:44:05:65:BA:05:16:24:0F:F2:2E:3A:5E:7E:91",
|
||||
"validFrom": "Oct 14 13:37:47 2026 GMT",
|
||||
"validUntil": "Jan 12 13:37:46 2027 GMT",
|
||||
"nativeName": "mmt253-8e62a941",
|
||||
"nativePrivateKey": true,
|
||||
"nativeFingerprint256": "89b6bd15857aaa548a26137fed6378aa2750440565ba0516240ff22e3a5e7e91"
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.256",
|
||||
"domain": "pngs.top",
|
||||
"checks": [
|
||||
{
|
||||
"endpoint": "/user/tokens/verify",
|
||||
"status": 200,
|
||||
"success": true,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"endpoint": "/zones?name=pngs.top",
|
||||
"status": 200,
|
||||
"success": true,
|
||||
"errors": []
|
||||
}
|
||||
],
|
||||
"tokenActive": true,
|
||||
"zoneActive": true,
|
||||
"accountMatched": true,
|
||||
"nameservers": [
|
||||
"cheryl.ns.cloudflare.com",
|
||||
"doug.ns.cloudflare.com"
|
||||
],
|
||||
"originalFqdnRecords": 0,
|
||||
"originalChallengeRecords": 0,
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"applicationTxtCleanupConfirmed": true,
|
||||
"ownARecordDeleted": true,
|
||||
"finalFqdnRecords": 0,
|
||||
"finalChallengeRecords": 0
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
".id": "*7",
|
||||
"name": "mmt253-8e62a941",
|
||||
"common-name": "mmt253-8e62a941.pngs.top",
|
||||
"fingerprint": "342d36bc13c4f4e807add3833f61b6b70aa4791cbf297bcbef1b0026d22b51a3",
|
||||
"private-key": "true"
|
||||
},
|
||||
{
|
||||
".id": "*A",
|
||||
"name": "mmt253-8e62a941",
|
||||
"common-name": "mmt253-8e62a941.pngs.top",
|
||||
"fingerprint": "70b7b9f11a77e5e1d21b43074fd84fa334a04bb7e871315eda1739638e8164be",
|
||||
"private-key": "true"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
[{"id" : "5b0aa78a-375d-4b6f-841f-aa8ff189408f", "source" : "manual", "status" : "done", "step" : "done", "serverId" : 2, "certName" : "mmt253-8e62a941", "error" : null}, {"id" : "2abc385b-3dd7-4ef5-b438-679c94d46e0c", "source" : "scheduler", "status" : "done", "step" : "done", "serverId" : 2, "certName" : "mmt253-8e62a941", "error" : null}]
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.256",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"serverId": "2",
|
||||
"realPortalLogin": true,
|
||||
"noMocks": true,
|
||||
"issuePosts": 1,
|
||||
"pageErrors": [],
|
||||
"settings": {
|
||||
"testStatus": 200,
|
||||
"testOk": true,
|
||||
"saveStatus": 200,
|
||||
"tokenConfigured": true,
|
||||
"directoryUrl": "https://acme-v02.api.letsencrypt.org/directory"
|
||||
},
|
||||
"jobId": "5b0aa78a-375d-4b6f-841f-aa8ff189408f",
|
||||
"accepted": true,
|
||||
"job": {
|
||||
"id": "5b0aa78a-375d-4b6f-841f-aa8ff189408f",
|
||||
"status": "done",
|
||||
"step": "done"
|
||||
},
|
||||
"uiTerminalConfirmed": true,
|
||||
"postCleanup": {
|
||||
"tokenConfigured": false,
|
||||
"ownJobStatus": 404,
|
||||
"reachableServerIds": [
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"ownCertificateAbsent": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"nativePrivateKey": true,
|
||||
"nativeFingerprint256": "342d36bc13c4f4e807add3833f61b6b70aa4791cbf297bcbef1b0026d22b51a3",
|
||||
"rawValidFrom": "2026-10-14 17:51:49",
|
||||
"rawValidUntil": "2027-01-12 17:51:48",
|
||||
"clockOffset": "+02:00",
|
||||
"clockTimeZone": "Europe/Warsaw"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"date": "2026-10-15",
|
||||
"block": "12.5.256",
|
||||
"certificatesBaselineMatched": true,
|
||||
"fileStableMetadataBaselineMatched": true,
|
||||
"directoryLastModifiedExcluded": true,
|
||||
"configuredServicesBaselineMatched": true,
|
||||
"dynamicServiceConnectionsExcluded": true,
|
||||
"normalizedExportMatched": true,
|
||||
"passwordChanged": false,
|
||||
"temporaryBackendPauseForLoginLimit": true,
|
||||
"backendRestartedAfterCleanup": true
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.256",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"enableRequests": 1,
|
||||
"runNowRequests": 0,
|
||||
"run": {
|
||||
"id": "sch-1791996745022-sq19wrmj",
|
||||
"jobKey": "certificates_renew",
|
||||
"startedAt": "2026-10-14 16:52:24.191+00",
|
||||
"finishedAt": "2026-10-14 16:52:25.02+00",
|
||||
"status": "ok",
|
||||
"error": null,
|
||||
"durationMs": 829,
|
||||
"resultJson": {
|
||||
"v": 1,
|
||||
"job": "certificates_renew",
|
||||
"errors": [],
|
||||
"checked": 1,
|
||||
"renewed": 0,
|
||||
"targets": [
|
||||
{
|
||||
"action": "skipped",
|
||||
"message": "Срок или состояние сертификата не подтверждены. Обновление не выполнялось.",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"daysLeft": 90,
|
||||
"serverId": "2"
|
||||
}
|
||||
],
|
||||
"sampledAt": "2026-10-14T16:52:24.191Z",
|
||||
"skippedTargets": 1
|
||||
}
|
||||
},
|
||||
"snapshot": {
|
||||
"v": 1,
|
||||
"job": "certificates_renew",
|
||||
"errors": [],
|
||||
"checked": 1,
|
||||
"renewed": 0,
|
||||
"targets": [
|
||||
{
|
||||
"action": "skipped",
|
||||
"message": "Срок или состояние сертификата не подтверждены. Обновление не выполнялось.",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"daysLeft": 90,
|
||||
"serverId": "2"
|
||||
}
|
||||
],
|
||||
"sampledAt": "2026-10-14T16:52:24.191Z",
|
||||
"skippedTargets": 1
|
||||
},
|
||||
"failure": {
|
||||
"name": "AssertionError",
|
||||
"message": "Expected values to be strictly equal:\n\n0 !== 1\n"
|
||||
},
|
||||
"disabledAfterRun": true
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"date": "2026-10-15",
|
||||
"block": "12.5.256",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"enableRequests": 1,
|
||||
"runNowRequests": 0,
|
||||
"eligibility": {
|
||||
"validFrom": "2026-10-14T15:51:49.000Z",
|
||||
"validUntil": "2027-01-12T15:51:48.000Z",
|
||||
"daysLeft": 90,
|
||||
"revocationStatus": "unknown"
|
||||
},
|
||||
"run": {
|
||||
"id": "sch-1791997029723-ryvhn6y9",
|
||||
"jobKey": "certificates_renew",
|
||||
"startedAt": "2026-10-14 16:56:33.978+00",
|
||||
"finishedAt": "2026-10-14 16:57:09.722+00",
|
||||
"status": "ok",
|
||||
"error": null,
|
||||
"durationMs": 35744,
|
||||
"resultJson": {
|
||||
"v": 1,
|
||||
"job": "certificates_renew",
|
||||
"errors": [],
|
||||
"checked": 1,
|
||||
"renewed": 1,
|
||||
"targets": [
|
||||
{
|
||||
"action": "renewed",
|
||||
"message": "Задача обновления завершена",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"daysLeft": 90,
|
||||
"serverId": "2"
|
||||
}
|
||||
],
|
||||
"sampledAt": "2026-10-14T16:56:33.978Z",
|
||||
"skippedTargets": 0
|
||||
}
|
||||
},
|
||||
"snapshot": {
|
||||
"v": 1,
|
||||
"job": "certificates_renew",
|
||||
"errors": [],
|
||||
"checked": 1,
|
||||
"renewed": 1,
|
||||
"targets": [
|
||||
{
|
||||
"action": "renewed",
|
||||
"message": "Задача обновления завершена",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"daysLeft": 90,
|
||||
"serverId": "2"
|
||||
}
|
||||
],
|
||||
"sampledAt": "2026-10-14T16:56:33.978Z",
|
||||
"skippedTargets": 0
|
||||
},
|
||||
"disabledAfterRun": true,
|
||||
"nativeVerification": {
|
||||
"duplicateLogicalNames": true,
|
||||
"servedLeafChanged": true,
|
||||
"newServedLeafMatchesNative": true,
|
||||
"overallRenewalAccepted": false,
|
||||
"reason": "Duplicate logical names prevent unambiguous subsequent renewal"
|
||||
},
|
||||
"cleanup": {
|
||||
"nativeBaselineMatched": true,
|
||||
"sqlSettingsRestored": true,
|
||||
"ownJobsRemoved": true,
|
||||
"dnsNamesEmpty": true,
|
||||
"backendHealthy": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"sampledAt": "2026-10-14T16:59:24.292Z",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"remoteAddress": "104.165.244.7",
|
||||
"authorized": true,
|
||||
"fingerprint256": "70:B7:B9:F1:1A:77:E5:E1:D2:1B:43:07:4F:D8:4F:A3:34:A0:4B:B7:E8:71:31:5E:DA:17:39:63:8E:81:64:BE",
|
||||
"validFrom": "Oct 14 15:58:34 2026 GMT",
|
||||
"validUntil": "Jan 12 15:58:33 2027 GMT",
|
||||
"changedFromBefore": true
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"sampledAt": "2026-10-14T16:52:16.930Z",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"remoteAddress": "104.165.244.7",
|
||||
"authorized": true,
|
||||
"hostnameMatched": true,
|
||||
"protocol": "TLSv1.2",
|
||||
"fingerprint256": "34:2D:36:BC:13:C4:F4:E8:07:AD:D3:83:3F:61:B6:B7:0A:A4:79:1C:BF:29:7B:CB:EF:1B:00:26:D2:2B:51:A3",
|
||||
"validFrom": "Oct 14 15:51:49 2026 GMT",
|
||||
"validUntil": "Jan 12 15:51:48 2027 GMT",
|
||||
"nativeName": "mmt253-8e62a941",
|
||||
"nativePrivateKey": true,
|
||||
"nativeFingerprint256": "342d36bc13c4f4e807add3833f61b6b70aa4791cbf297bcbef1b0026d22b51a3"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"date": "2026-10-15",
|
||||
"block": "12.5.259",
|
||||
"nativeCertificatesRestored": true,
|
||||
"nativeFilesRestored": true,
|
||||
"sslServicesRestored": true,
|
||||
"normalizedExportRestored": true,
|
||||
"privateSqlSettingsRestored": true,
|
||||
"ownJobs": 0,
|
||||
"exportSha256": "3d7d864c2e8d9e7c2bba3ef59aa64b7d05e2a660d4d307172c36c555184b6066",
|
||||
"passwordsUnchanged": true,
|
||||
"jobs": [
|
||||
{
|
||||
"id": "60f3d7b3-9679-4c4c-9de6-800b8ffd726b",
|
||||
"status": "done",
|
||||
"source": "manual"
|
||||
},
|
||||
{
|
||||
"id": "a344479f-6144-4bb5-b678-a37b27d91860",
|
||||
"status": "done",
|
||||
"source": "scheduler"
|
||||
}
|
||||
],
|
||||
"cloudflareExactNamesEmpty": true,
|
||||
"remotePrivateFilesRemoved": true,
|
||||
"localPrivateFixtureRemoved": true
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"date": "2026-10-15",
|
||||
"block": "12.5.259",
|
||||
"domain": "pngs.top",
|
||||
"checks": [
|
||||
{
|
||||
"endpoint": "/user/tokens/verify",
|
||||
"status": 200,
|
||||
"success": true,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"endpoint": "/zones?name=pngs.top",
|
||||
"status": 200,
|
||||
"success": true,
|
||||
"errors": []
|
||||
}
|
||||
],
|
||||
"tokenActive": true,
|
||||
"zoneActive": true,
|
||||
"accountMatched": true,
|
||||
"nameservers": [
|
||||
"cheryl.ns.cloudflare.com",
|
||||
"doug.ns.cloudflare.com"
|
||||
],
|
||||
"originalFqdnRecords": 0,
|
||||
"originalChallengeRecords": 0,
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"applicationTxtCleanupConfirmed": true,
|
||||
"ownARecordDeleted": true,
|
||||
"finalFqdnRecords": 0,
|
||||
"finalChallengeRecords": 0
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"date": "2026-10-15",
|
||||
"block": "12.5.259",
|
||||
"backendImage": "mmapp-test/backend:ux-certificates258",
|
||||
"imageId": "sha256:984684709e619972bae8657208e3150d12f1c4f2b5642fecf5286a5d87e9fe71",
|
||||
"health": "healthy",
|
||||
"frontendImage": "mmapp-test/frontend:ux-certificates251",
|
||||
"preparedImageEvidence": "certificates258-preparation.json",
|
||||
"newProductionCode": false,
|
||||
"firstIssueAndRenewalAccepted": true,
|
||||
"exactFqdn": "mmt253-8e62a941.pngs.top",
|
||||
"target": "104.165.244.7",
|
||||
"control": "194.226.121.150",
|
||||
"controlReachableAfterCleanup": true,
|
||||
"privateCleanupConfirmed": true
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"date": "2026-10-15",
|
||||
"block": "12.5.259",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"serverId": "2",
|
||||
"realPortalLogin": true,
|
||||
"noMocks": true,
|
||||
"issuePosts": 1,
|
||||
"pageErrors": [],
|
||||
"settings": {
|
||||
"testStatus": 200,
|
||||
"testOk": true,
|
||||
"saveStatus": 200,
|
||||
"tokenConfigured": true,
|
||||
"directoryUrl": "https://acme-v02.api.letsencrypt.org/directory"
|
||||
},
|
||||
"jobId": "60f3d7b3-9679-4c4c-9de6-800b8ffd726b",
|
||||
"accepted": true,
|
||||
"job": {
|
||||
"id": "60f3d7b3-9679-4c4c-9de6-800b8ffd726b",
|
||||
"status": "done",
|
||||
"step": "done"
|
||||
},
|
||||
"uiTerminalConfirmed": true,
|
||||
"postCleanup": {
|
||||
"tokenConfigured": false,
|
||||
"ownJobStatus": 404,
|
||||
"reachableServerIds": [
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"ownCertificateAbsent": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"date": "2026-10-15",
|
||||
"block": "12.5.259",
|
||||
"before": {
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"nativePrivateKey": true,
|
||||
"nativeFingerprint256": "4d795d55910379177cb72a10dbaa4715ef1a4eeeca9dffb0db7a15e62593bd0a",
|
||||
"logicalId": "*1",
|
||||
"logicalNames": 1,
|
||||
"archives": [],
|
||||
"services": [
|
||||
{
|
||||
"name": "www-ssl",
|
||||
"certificate": "mmt253-8e62a941",
|
||||
"disabled": "false"
|
||||
},
|
||||
{
|
||||
"name": "api-ssl",
|
||||
"certificate": "mmt253-8e62a941",
|
||||
"disabled": "false"
|
||||
}
|
||||
]
|
||||
},
|
||||
"after": {
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"nativePrivateKey": true,
|
||||
"nativeFingerprint256": "ecd158f17450ca1f8442374cb9d23e9de6c28fce6ff001ec7a6825e577657324",
|
||||
"logicalId": "*4",
|
||||
"logicalNames": 1,
|
||||
"archives": [
|
||||
{
|
||||
"id": "*1",
|
||||
"name": "mmt253-8e62a941_old_db6003fc0c3d",
|
||||
"fingerprint": "4d795d55910379177cb72a10dbaa4715ef1a4eeeca9dffb0db7a15e62593bd0a",
|
||||
"privateKey": "true"
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
{
|
||||
"name": "www-ssl",
|
||||
"certificate": "mmt253-8e62a941",
|
||||
"disabled": "false"
|
||||
},
|
||||
{
|
||||
"name": "api-ssl",
|
||||
"certificate": "mmt253-8e62a941",
|
||||
"disabled": "false"
|
||||
}
|
||||
]
|
||||
},
|
||||
"canonicalDatesMatchX509": true,
|
||||
"canonicalDates": {
|
||||
"validFrom": "2026-10-15T05:41:17.000Z",
|
||||
"validUntil": "2027-01-13T05:41:16.000Z",
|
||||
"daysLeft": 90,
|
||||
"status": "unknown"
|
||||
},
|
||||
"trustedHttpsRestAfterRenewal": 200,
|
||||
"realPortalViews": [
|
||||
{
|
||||
"width": 1440,
|
||||
"overflow": false
|
||||
},
|
||||
{
|
||||
"width": 390,
|
||||
"overflow": false
|
||||
}
|
||||
],
|
||||
"pageErrors": [],
|
||||
"nonAuthApiWrites": 0
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"date": "2026-10-15",
|
||||
"block": "12.5.259",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"enableRequests": 1,
|
||||
"runNowRequests": 0,
|
||||
"eligibility": {
|
||||
"validFrom": "2026-10-15T05:39:27.000Z",
|
||||
"validUntil": "2027-01-13T05:39:26.000Z",
|
||||
"daysLeft": 90,
|
||||
"revocationStatus": "unknown"
|
||||
},
|
||||
"run": {
|
||||
"id": "sch-1792046395326-8ysbwrkl",
|
||||
"jobKey": "certificates_renew",
|
||||
"startedAt": "2026-10-15 06:39:23.838+00",
|
||||
"finishedAt": "2026-10-15 06:39:55.326+00",
|
||||
"status": "ok",
|
||||
"error": null,
|
||||
"durationMs": 31488,
|
||||
"resultJson": {
|
||||
"v": 1,
|
||||
"job": "certificates_renew",
|
||||
"errors": [],
|
||||
"checked": 1,
|
||||
"renewed": 1,
|
||||
"targets": [
|
||||
{
|
||||
"action": "renewed",
|
||||
"message": "Задача обновления завершена",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"daysLeft": 90,
|
||||
"serverId": "2"
|
||||
}
|
||||
],
|
||||
"sampledAt": "2026-10-15T06:39:23.838Z",
|
||||
"skippedTargets": 0
|
||||
}
|
||||
},
|
||||
"snapshot": {
|
||||
"v": 1,
|
||||
"job": "certificates_renew",
|
||||
"errors": [],
|
||||
"checked": 1,
|
||||
"renewed": 1,
|
||||
"targets": [
|
||||
{
|
||||
"action": "renewed",
|
||||
"message": "Задача обновления завершена",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"daysLeft": 90,
|
||||
"serverId": "2"
|
||||
}
|
||||
],
|
||||
"sampledAt": "2026-10-15T06:39:23.838Z",
|
||||
"skippedTargets": 0
|
||||
},
|
||||
"disabledAfterRun": true
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"sampledAt": "2026-10-15T06:40:59.300Z",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"remoteAddress": "104.165.244.7",
|
||||
"authorized": true,
|
||||
"hostnameMatched": true,
|
||||
"protocol": "TLSv1.2",
|
||||
"fingerprint256": "EC:D1:58:F1:74:50:CA:1F:84:42:37:4C:B9:D2:3E:9D:E6:C2:8F:CE:6F:F0:01:EC:7A:68:25:E5:77:65:73:24",
|
||||
"validFrom": "Oct 15 05:41:17 2026 GMT",
|
||||
"validUntil": "Jan 13 05:41:16 2027 GMT",
|
||||
"nativeName": "mmt253-8e62a941",
|
||||
"nativePrivateKey": true,
|
||||
"nativeFingerprint256": "ecd158f17450ca1f8442374cb9d23e9de6c28fce6ff001ec7a6825e577657324"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"sampledAt": "2026-10-15T06:39:13.617Z",
|
||||
"fqdn": "mmt253-8e62a941.pngs.top",
|
||||
"certName": "mmt253-8e62a941",
|
||||
"remoteAddress": "104.165.244.7",
|
||||
"authorized": true,
|
||||
"hostnameMatched": true,
|
||||
"protocol": "TLSv1.2",
|
||||
"fingerprint256": "4D:79:5D:55:91:03:79:17:7C:B7:2A:10:DB:AA:47:15:EF:1A:4E:EE:CA:9D:FF:B0:DB:7A:15:E6:25:93:BD:0A",
|
||||
"validFrom": "Oct 15 05:39:27 2026 GMT",
|
||||
"validUntil": "Jan 13 05:39:26 2027 GMT",
|
||||
"nativeName": "mmt253-8e62a941",
|
||||
"nativePrivateKey": true,
|
||||
"nativeFingerprint256": "4d795d55910379177cb72a10dbaa4715ef1a4eeeca9dffb0db7a15e62593bd0a"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"fingerprintChanged": true,
|
||||
"nativeAndTlsMatch": true,
|
||||
"trustedHostnameMatch": true
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"block": "12.5.169",
|
||||
"date": "2026-10-12",
|
||||
"scope": "local server/traffic identity guards only",
|
||||
"checks": {
|
||||
"identity": "passed",
|
||||
"groups": "passed",
|
||||
"evaluateRule": "passed",
|
||||
"collector": "passed",
|
||||
"history": "passed",
|
||||
"backendBuild": "passed",
|
||||
"eslint": "passed",
|
||||
"sql": "skipped: no owned DB and local PG connect EACCES",
|
||||
"live": "not run",
|
||||
"deploy": "not run"
|
||||
},
|
||||
"runtimeUnchanged": {
|
||||
"backend": "ux-fresh167",
|
||||
"frontend": "ux-bfd158"
|
||||
},
|
||||
"pending": [
|
||||
"source enabled flags",
|
||||
"freshness",
|
||||
"latest error/current known state",
|
||||
"probe identity and individual intervals",
|
||||
"owned PG fixtures",
|
||||
"deployment and live acceptance"
|
||||
],
|
||||
"routerOsWrites": 0,
|
||||
"messagesSent": 0,
|
||||
"push": false
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.168",
|
||||
"readOnlyConnection": true,
|
||||
"settings": {
|
||||
"uptime": {
|
||||
"enabled": true,
|
||||
"resourcesEnabled": true,
|
||||
"pingEnabled": true,
|
||||
"intervalSec": 15,
|
||||
"probeIntervalSec": 15
|
||||
},
|
||||
"traffic": {
|
||||
"enabled": true,
|
||||
"intervalSec": 30
|
||||
},
|
||||
"rest": {
|
||||
"enabled": false,
|
||||
"intervalSec": 120
|
||||
},
|
||||
"activeProbeCount": 0,
|
||||
"customActiveProbeIntervals": []
|
||||
},
|
||||
"signals": {
|
||||
"servers": {
|
||||
"count": 1,
|
||||
"maxAgeSec": 3.197
|
||||
},
|
||||
"probes": {
|
||||
"count": 0,
|
||||
"maxAgeSec": null
|
||||
},
|
||||
"traffic": {
|
||||
"count": 1,
|
||||
"maxAgeSec": 18.24
|
||||
}
|
||||
},
|
||||
"duplicateEnabledServerLabelGroups": 1,
|
||||
"bounds": [
|
||||
"Actual read-only main PostgreSQL metadata; no settings getters that might seed defaults, no bootstrap/write/RouterOS/messages",
|
||||
"Code audit: settings/freshness not currently enforced by non-GRE/BGP alert builder/evaluation; no behavioral fix or controlled stale/disabled runtime fixture claimed",
|
||||
"Age metadata is observed, not a verdict of staleness without effective per-source intervals"
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.171",
|
||||
"runtime": {
|
||||
"backend": "ux-targets171",
|
||||
"frontend": "ux-targets171"
|
||||
},
|
||||
"api200": true,
|
||||
"ambiguousKindCount": 2,
|
||||
"cases": [
|
||||
{
|
||||
"width": 1440,
|
||||
"warningVisible": true,
|
||||
"duplicateGrouped": true,
|
||||
"serverLink": true,
|
||||
"noOverflow": true,
|
||||
"scopedAxeViolations": [],
|
||||
"pageErrors": [],
|
||||
"apiWrites": [],
|
||||
"screenshot": "docs/ux-ui/screens/alerts-target-issues-1440-2026-10-12.png"
|
||||
},
|
||||
{
|
||||
"width": 320,
|
||||
"warningVisible": true,
|
||||
"duplicateGrouped": true,
|
||||
"serverLink": true,
|
||||
"noOverflow": true,
|
||||
"scopedAxeViolations": [],
|
||||
"pageErrors": [],
|
||||
"apiWrites": [],
|
||||
"screenshot": "docs/ux-ui/screens/alerts-target-issues-320-2026-10-12.png"
|
||||
}
|
||||
],
|
||||
"bounds": [
|
||||
"Read-only real duplicate CHR metadata; no rename/native mutation/password change/message",
|
||||
"Scoped axe of new warning is not full WCAG certification",
|
||||
"Disabled configuration covered by owned SQL and API-path UI fixtures; live configuration preserved"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.171",
|
||||
"newFrontend": "ux-targets171",
|
||||
"oldBackend": "ux-sources170",
|
||||
"optionalDiagnosticMissing": true,
|
||||
"readerAccepted": true,
|
||||
"unknownDiagnosticNotInvented": true
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.171",
|
||||
"services": {
|
||||
"backend": {
|
||||
"image": "mmapp-test/backend:ux-targets171",
|
||||
"imageId": "sha256:754b7420ca35657fb566cec97cf37322320787363e1787bb4ce89aa0bfb256ed",
|
||||
"matchedVerifiedImage": true,
|
||||
"state": "running",
|
||||
"health": "healthy"
|
||||
},
|
||||
"frontend": {
|
||||
"image": "mmapp-test/frontend:ux-targets171",
|
||||
"imageId": "sha256:050987e82c1ab5571f4c3dc8692a22f8ba703881f699c802f0168d90ab74652e",
|
||||
"matchedVerifiedImage": true,
|
||||
"state": "running",
|
||||
"health": null
|
||||
}
|
||||
},
|
||||
"rollbackTags": {
|
||||
"MMAPP_IMAGE_TAG": "ux-bfd158",
|
||||
"BACKEND_IMAGE_TAG": "ux-sources170"
|
||||
},
|
||||
"secretEnvCopied": false,
|
||||
"runningContainers": [
|
||||
"mmapp-test-backend",
|
||||
"mmapp-test-frontend",
|
||||
"mmapp-test-postgres"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.171",
|
||||
"matched": {
|
||||
"backend": 434,
|
||||
"frontend": 518
|
||||
},
|
||||
"different": [],
|
||||
"missing": [],
|
||||
"sourceBase": "db7105119d0c9a3b1dee254d8e3d6ac45c97bba0"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.171",
|
||||
"database": "mm_accept_166_1791794042576",
|
||||
"scope": "ephemeral role and precreated owned database; no copied production credentials",
|
||||
"tests": [
|
||||
{
|
||||
"command": "npm --prefix backend run test:alert-engine",
|
||||
"passed": true,
|
||||
"durationMs": 19540,
|
||||
"ownedHistorySqlRows": 8,
|
||||
"ownedSourceSqlCases": 16,
|
||||
"sqlConfirmStabilityPassed": true,
|
||||
"postgresUnavailableSkip": false
|
||||
}
|
||||
],
|
||||
"scopedRoleVerified": true,
|
||||
"passed": true,
|
||||
"databaseRemoved": true,
|
||||
"roleRemoved": true,
|
||||
"testContainerRemoved": true,
|
||||
"metadataSqlAssertionsPassed": true
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.227",
|
||||
"platform": "Android / strongSwan; user says latest version, numeric version not supplied",
|
||||
"humanReported": {
|
||||
"initial": {
|
||||
"sitesOpen": true,
|
||||
"externalIPv4": "194.226.121.150",
|
||||
"privatePing": "198.18.227.1",
|
||||
"privatePingSucceeded": true
|
||||
},
|
||||
"disconnectReconnect": {
|
||||
"sitesOpen": true,
|
||||
"externalIPv4": "194.226.121.150",
|
||||
"privatePingSucceeded": true
|
||||
}
|
||||
},
|
||||
"nativeSnapshot": {
|
||||
"at": "2026-10-14T01:59:05.155Z",
|
||||
"phoneEstablished": 0,
|
||||
"installedSaCount": 0,
|
||||
"alignedWithHumanConnection": false,
|
||||
"packetCounterProof": false
|
||||
},
|
||||
"cleanup": {
|
||||
"removed": 16,
|
||||
"originalFieldCollectionsPreserved": 13,
|
||||
"phoneSessionAbsent": true,
|
||||
"availability": [
|
||||
{
|
||||
"host": "194.226.121.150",
|
||||
"available": true
|
||||
},
|
||||
{
|
||||
"host": "104.165.244.7",
|
||||
"available": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"bounds": [
|
||||
"Human full-tunnel and reconnect accepted; synchronized native session/packet counters not captured (snapshot had zero peers/SAs)",
|
||||
"No long rekey, Wi-Fi/mobile handover, public IPv6 or numerical client OS/app version proof"
|
||||
],
|
||||
"passwordChanges": 0
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"at":"2026-10-14T01:55:15.230Z","checks":[{"path":"/ip/ipsec/identity","originalIdsPreserved":true},{"path":"/ip/ipsec/peer","originalIdsPreserved":true},{"path":"/ip/ipsec/policy","originalIdsPreserved":true},{"path":"/ip/ipsec/policy/group","originalIdsPreserved":true},{"path":"/ip/ipsec/mode-config","originalIdsPreserved":true},{"path":"/ip/pool","originalIdsPreserved":true},{"path":"/ip/ipsec/proposal","originalIdsPreserved":true},{"path":"/ip/ipsec/profile","originalIdsPreserved":true},{"path":"/certificate","originalIdsPreserved":true},{"path":"/file","originalIdsPreserved":true},{"path":"/ip/address","originalIdsPreserved":true},{"path":"/interface/bridge","originalIdsPreserved":true},{"path":"/ip/firewall/nat","originalIdsPreserved":true}],"ownObjects":16,"establishedForPhone":false,"passwordChanges":0}
|
||||
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.227",
|
||||
"name": "mm-phone227",
|
||||
"host": "194.226.121.150",
|
||||
"ready": true,
|
||||
"androidTestPassed": false,
|
||||
"humanTestPending": true,
|
||||
"firstPreparation": {
|
||||
"failed": true,
|
||||
"reason": "Fixture ownership guard rejected its own mm-phone227 address comment; resumed existing objects without replaying creation"
|
||||
},
|
||||
"clientAddress": "198.18.227.250",
|
||||
"pingTarget": "198.18.227.1",
|
||||
"fullTunnelPolicy": true,
|
||||
"natConfigured": true,
|
||||
"dnsServers": [
|
||||
"1.1.1.1"
|
||||
],
|
||||
"serverCertificate": {
|
||||
"name": "ipsec-server",
|
||||
"san": "IP:194.226.121.150",
|
||||
"expires": "2026-10-16 04:49:06"
|
||||
},
|
||||
"created": [
|
||||
{
|
||||
"path": "/ip/ipsec/identity",
|
||||
"id": "*A",
|
||||
"name": null,
|
||||
"comment": "MikrotikManager:ipsec IKEv2 listener"
|
||||
},
|
||||
{
|
||||
"path": "/ip/ipsec/peer",
|
||||
"id": "*1",
|
||||
"name": "ipsec-vpn",
|
||||
"comment": "MikrotikManager:ipsec IKEv2 road-warrior"
|
||||
},
|
||||
{
|
||||
"path": "/ip/ipsec/policy",
|
||||
"id": "*1000000",
|
||||
"name": null,
|
||||
"comment": "MikrotikManager:ipsec IKEv2 road-warrior"
|
||||
},
|
||||
{
|
||||
"path": "/ip/ipsec/policy/group",
|
||||
"id": "*3",
|
||||
"name": "mmapp-ipsec-vpn",
|
||||
"comment": null
|
||||
},
|
||||
{
|
||||
"path": "/ip/ipsec/mode-config",
|
||||
"id": "*2",
|
||||
"name": "ipsec-vpn",
|
||||
"comment": null
|
||||
},
|
||||
{
|
||||
"path": "/ip/pool",
|
||||
"id": "*26",
|
||||
"name": "ipsec-vpn",
|
||||
"comment": "MikrotikManager:ipsec IKEv2 road-warrior"
|
||||
},
|
||||
{
|
||||
"path": "/ip/ipsec/proposal",
|
||||
"id": "*1",
|
||||
"name": "ipsec-vpn",
|
||||
"comment": "MikrotikManager:ipsec IKEv2 road-warrior"
|
||||
},
|
||||
{
|
||||
"path": "/ip/ipsec/profile",
|
||||
"id": "*B",
|
||||
"name": "ipsec-vpn",
|
||||
"comment": null
|
||||
},
|
||||
{
|
||||
"path": "/certificate",
|
||||
"id": "*10C",
|
||||
"name": "ipsec-ca",
|
||||
"comment": null
|
||||
},
|
||||
{
|
||||
"path": "/certificate",
|
||||
"id": "*10D",
|
||||
"name": "ipsec-server",
|
||||
"comment": null
|
||||
},
|
||||
{
|
||||
"path": "/ip/firewall/nat",
|
||||
"id": "*7",
|
||||
"name": null,
|
||||
"comment": "MikrotikManager:ipsec \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c VPN"
|
||||
},
|
||||
{
|
||||
"path": "/ip/ipsec/identity",
|
||||
"id": "*B",
|
||||
"name": null,
|
||||
"comment": "MikrotikManager:ipsec user=mm-phone227"
|
||||
},
|
||||
{
|
||||
"path": "/ip/ipsec/mode-config",
|
||||
"id": "*3",
|
||||
"name": "mc-ipsec-mm-phone227",
|
||||
"comment": null
|
||||
},
|
||||
{
|
||||
"path": "/certificate",
|
||||
"id": "*10E",
|
||||
"name": "ipsec-user-mm-phone227",
|
||||
"comment": null
|
||||
},
|
||||
{
|
||||
"path": "/interface/bridge",
|
||||
"id": "*BC",
|
||||
"name": "mm-phone227",
|
||||
"comment": "mm-phone227"
|
||||
},
|
||||
{
|
||||
"path": "/ip/address",
|
||||
"id": "*9D",
|
||||
"name": null,
|
||||
"comment": "mm-phone227"
|
||||
}
|
||||
],
|
||||
"passwordChanges": 0,
|
||||
"cleanupPending": true,
|
||||
"p12CertificateChainVerified": true,
|
||||
"caExplicitlyPinnedInProfile": true,
|
||||
"p12PrivateKeyInsideEncryptedSafe": true,
|
||||
"p12WrongPasswordRejected": true
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
"block": "12.5.211",
|
||||
"runtime": "ux-gre209",
|
||||
"cases": [
|
||||
{
|
||||
"path": "/api/servers",
|
||||
"status": 401,
|
||||
"anonymous": true,
|
||||
"serverRows": 0,
|
||||
"nonemptyPasswordPresent": false
|
||||
},
|
||||
{
|
||||
"path": "/api/%73ervers",
|
||||
"status": 401,
|
||||
"anonymous": true,
|
||||
"serverRows": 0,
|
||||
"nonemptyPasswordPresent": false
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/servers",
|
||||
"status": 200,
|
||||
"anonymous": true,
|
||||
"serverRows": 2,
|
||||
"nonemptyPasswordPresent": true
|
||||
}
|
||||
],
|
||||
"rawBodyStored": false,
|
||||
"mutationRequests": 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
"block": "12.5.211",
|
||||
"services": {
|
||||
"backend": {
|
||||
"image": "mmapp-test/backend:ux-auth211",
|
||||
"imageId": "sha256:904c844a729465e8cdb48278a1f2829c88fe2764941ae60b4a0d05dc2f2d3b18",
|
||||
"running": true,
|
||||
"health": "healthy"
|
||||
},
|
||||
"frontend": {
|
||||
"image": "mmapp-test/frontend:ux-gre210",
|
||||
"imageId": "sha256:b4b1280f729e89de83b30bd242d37bda831306720b3c78cb9eef6048c3e3178e",
|
||||
"running": true,
|
||||
"health": null
|
||||
}
|
||||
},
|
||||
"rollbackTags": {
|
||||
"backend": "ux-gre210",
|
||||
"frontend": "ux-gre210"
|
||||
},
|
||||
"backendSourceMatched": 477,
|
||||
"compiledMatched": 1048
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
"block": "12.5.211",
|
||||
"backend": "ux-auth211",
|
||||
"frontend": "ux-gre210",
|
||||
"cases": [
|
||||
{
|
||||
"role": "anonymous",
|
||||
"path": "/api/servers",
|
||||
"method": "GET",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"role": "anonymous",
|
||||
"path": "/api/servers",
|
||||
"method": "HEAD",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"role": "anonymous",
|
||||
"path": "/api/%73ervers",
|
||||
"method": "GET",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"role": "anonymous",
|
||||
"path": "/api/%73ervers",
|
||||
"method": "HEAD",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"role": "anonymous",
|
||||
"path": "/%61pi/servers",
|
||||
"method": "GET",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"role": "anonymous",
|
||||
"path": "/%61pi/servers",
|
||||
"method": "HEAD",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"role": "anonymous",
|
||||
"path": "/%61%70%69/servers",
|
||||
"method": "GET",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"role": "anonymous",
|
||||
"path": "/%61%70%69/servers",
|
||||
"method": "HEAD",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"role": "dashboard",
|
||||
"path": "/api/servers",
|
||||
"method": "GET",
|
||||
"status": 403,
|
||||
"privateMaterialAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "dashboard",
|
||||
"path": "/api/%73ervers",
|
||||
"method": "GET",
|
||||
"status": 403,
|
||||
"privateMaterialAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "dashboard",
|
||||
"path": "/%61pi/servers",
|
||||
"method": "GET",
|
||||
"status": 403,
|
||||
"privateMaterialAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "dashboard",
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "GET",
|
||||
"status": 403,
|
||||
"pskAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "dashboard",
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "PATCH",
|
||||
"status": 403,
|
||||
"emptyBody": true,
|
||||
"nativeApplication": false
|
||||
},
|
||||
{
|
||||
"role": "dashboard",
|
||||
"path": "/api/%67re/tunnels",
|
||||
"method": "GET",
|
||||
"status": 403,
|
||||
"pskAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "dashboard",
|
||||
"path": "/api/%67re/tunnels",
|
||||
"method": "PATCH",
|
||||
"status": 403,
|
||||
"emptyBody": true,
|
||||
"nativeApplication": false
|
||||
},
|
||||
{
|
||||
"role": "dashboard",
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "GET",
|
||||
"status": 403,
|
||||
"pskAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "dashboard",
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "PATCH",
|
||||
"status": 403,
|
||||
"emptyBody": true,
|
||||
"nativeApplication": false
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"path": "/api/servers",
|
||||
"method": "GET",
|
||||
"status": 200,
|
||||
"privateMaterialAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"path": "/api/%73ervers",
|
||||
"method": "GET",
|
||||
"status": 200,
|
||||
"privateMaterialAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"path": "/%61pi/servers",
|
||||
"method": "GET",
|
||||
"status": 200,
|
||||
"privateMaterialAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "GET",
|
||||
"status": 200,
|
||||
"pskAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "PATCH",
|
||||
"status": 403,
|
||||
"emptyBody": true,
|
||||
"nativeApplication": false
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"path": "/api/%67re/tunnels",
|
||||
"method": "GET",
|
||||
"status": 200,
|
||||
"pskAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"path": "/api/%67re/tunnels",
|
||||
"method": "PATCH",
|
||||
"status": 403,
|
||||
"emptyBody": true,
|
||||
"nativeApplication": false
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "GET",
|
||||
"status": 200,
|
||||
"pskAbsent": true
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "PATCH",
|
||||
"status": 403,
|
||||
"emptyBody": true,
|
||||
"nativeApplication": false
|
||||
}
|
||||
],
|
||||
"publicAuthConfig": 200,
|
||||
"realPortalJWT": true,
|
||||
"rawResponseBodiesStored": false,
|
||||
"ownedUsersRemoved": true,
|
||||
"scope": "Anonymous GET/HEAD and actual restricted roles; denied PATCH uses empty body and cannot apply native objects"
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
"block": "12.5.211",
|
||||
"database": "mm_accept_166_1791901195054",
|
||||
"baseline": false,
|
||||
"cases": [
|
||||
{
|
||||
"path": "/api/servers",
|
||||
"method": "GET",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/api/servers",
|
||||
"method": "HEAD",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/api/%73ervers",
|
||||
"method": "GET",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/api/%73ervers",
|
||||
"method": "HEAD",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/servers",
|
||||
"method": "GET",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/servers",
|
||||
"method": "HEAD",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/%61%70%69/servers",
|
||||
"method": "GET",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/%61%70%69/servers",
|
||||
"method": "HEAD",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "GET",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "HEAD",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "GET",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "HEAD",
|
||||
"role": "anonymous",
|
||||
"status": 401
|
||||
},
|
||||
{
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "GET",
|
||||
"role": "dashboard",
|
||||
"status": 403,
|
||||
"privateMaterialStored": false
|
||||
},
|
||||
{
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "PATCH",
|
||||
"role": "dashboard",
|
||||
"status": 403
|
||||
},
|
||||
{
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "GET",
|
||||
"role": "reader",
|
||||
"status": 200,
|
||||
"privateMaterialStored": false
|
||||
},
|
||||
{
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "PATCH",
|
||||
"role": "reader",
|
||||
"status": 403
|
||||
},
|
||||
{
|
||||
"path": "/api/gre/tunnels",
|
||||
"method": "GET",
|
||||
"role": "writer",
|
||||
"status": 200,
|
||||
"privateMaterialStored": false
|
||||
},
|
||||
{
|
||||
"path": "/api/%67re/tunnels",
|
||||
"method": "GET",
|
||||
"role": "dashboard",
|
||||
"status": 403,
|
||||
"privateMaterialStored": false
|
||||
},
|
||||
{
|
||||
"path": "/api/%67re/tunnels",
|
||||
"method": "PATCH",
|
||||
"role": "dashboard",
|
||||
"status": 403
|
||||
},
|
||||
{
|
||||
"path": "/api/%67re/tunnels",
|
||||
"method": "GET",
|
||||
"role": "reader",
|
||||
"status": 200,
|
||||
"privateMaterialStored": false
|
||||
},
|
||||
{
|
||||
"path": "/api/%67re/tunnels",
|
||||
"method": "PATCH",
|
||||
"role": "reader",
|
||||
"status": 403
|
||||
},
|
||||
{
|
||||
"path": "/api/%67re/tunnels",
|
||||
"method": "GET",
|
||||
"role": "writer",
|
||||
"status": 200,
|
||||
"privateMaterialStored": false
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "GET",
|
||||
"role": "dashboard",
|
||||
"status": 403,
|
||||
"privateMaterialStored": false
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "PATCH",
|
||||
"role": "dashboard",
|
||||
"status": 403
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "GET",
|
||||
"role": "reader",
|
||||
"status": 200,
|
||||
"privateMaterialStored": false
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "PATCH",
|
||||
"role": "reader",
|
||||
"status": 403
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/gre/tunnels",
|
||||
"method": "GET",
|
||||
"role": "writer",
|
||||
"status": 200,
|
||||
"privateMaterialStored": false
|
||||
},
|
||||
{
|
||||
"path": "/api/auth/config",
|
||||
"role": "anonymous",
|
||||
"status": 200,
|
||||
"publicConfig": true
|
||||
},
|
||||
{
|
||||
"path": "/%61pi/auth/config",
|
||||
"role": "anonymous",
|
||||
"status": 200,
|
||||
"publicConfig": true
|
||||
}
|
||||
],
|
||||
"scope": "Production compiled canonical auth/RBAC using own restricted PostgreSQL, local native HTTP fixture and synthetic JWT/PSK",
|
||||
"passed": true,
|
||||
"nativeWrites": 0,
|
||||
"databaseAndRoleRemoved": true
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
"block": "12.5.211",
|
||||
"canonicalAuthCases": 42,
|
||||
"commands": [
|
||||
"npm --prefix backend run test:auth",
|
||||
"npx tsx backend/src/plugins/auth.geoip.test.ts",
|
||||
"npx tsx backend/src/plugins/auth.netflow-settings.test.ts"
|
||||
],
|
||||
"passed": true,
|
||||
"backendBuildPassed": true,
|
||||
"scope": "Matched static/parameter routes, GET/HEAD/PATCH, OSPF read preview, public auth config/health, existing auth/GeoIP/private NetFlow export policy"
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.166",
|
||||
"productionPoolKeepsAlive": true,
|
||||
"readOnlyConnection": true,
|
||||
"queryCompleted": true,
|
||||
"historyCount": 8,
|
||||
"bounds": [
|
||||
"Compiled166 in NODE_ENV=production keeps pool lifecycle; readonly actual PostgreSQL SELECT",
|
||||
"Positive partial/error SQL and full profiles verified independently in owned database; no main writes"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.166",
|
||||
"name": "mm_accept_166_1791779292730",
|
||||
"created": true,
|
||||
"tests": [
|
||||
{
|
||||
"command": "npm --prefix backend test",
|
||||
"passed": true,
|
||||
"profileCount": 24,
|
||||
"durationMs": 286958,
|
||||
"ownedHistorySqlRows": 6,
|
||||
"sqlConfirmStabilityPassed": true,
|
||||
"postgresUnavailableSkip": false,
|
||||
"optionalNetworkDisabledSqlSkipped": true
|
||||
}
|
||||
],
|
||||
"databaseRemoved": true,
|
||||
"mainServerStaticUnchanged": true,
|
||||
"passed": true
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.237",
|
||||
"passed": true,
|
||||
"checks": [
|
||||
{
|
||||
"listStates": {
|
||||
"directory237": "unknown",
|
||||
"remote237": "not-stored",
|
||||
"both237": "missing",
|
||||
"missing237": "missing",
|
||||
"available237": "available"
|
||||
}
|
||||
},
|
||||
{
|
||||
"availableDownload": 200
|
||||
},
|
||||
{
|
||||
"missingDownload": 404
|
||||
},
|
||||
{
|
||||
"missingRestore": 400,
|
||||
"outcome": "not-applied",
|
||||
"nativeRequests": 0
|
||||
},
|
||||
{
|
||||
"failurePreservesCatalog": true
|
||||
},
|
||||
{
|
||||
"recreatedFilePreserved": 409
|
||||
},
|
||||
{
|
||||
"missingRecordDeletion": 204,
|
||||
"mode": "record-only"
|
||||
}
|
||||
],
|
||||
"externalS3Contacts": 0,
|
||||
"chrContacts": 0,
|
||||
"ownedDatabaseAndRoleRemoved": true
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.230",
|
||||
"backendSourceMatched": 500,
|
||||
"compiledMatched": 1060,
|
||||
"frontendChanged": false,
|
||||
"services": {
|
||||
"backend": {
|
||||
"image": "mmapp-test/backend:ux-backup230",
|
||||
"imageId": "sha256:796aef2b62f03218e4e07f15cedb7bc14613494b4ec6e61af85480703a4d5e37",
|
||||
"running": true,
|
||||
"health": "healthy"
|
||||
},
|
||||
"frontend": {
|
||||
"image": "mmapp-test/frontend:ux-routing218",
|
||||
"imageId": "sha256:ec658b9da88c19d60987be5bfc0c15fb339a0310d7a42dc761b40a70a3428c5a",
|
||||
"running": true,
|
||||
"health": null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.230",
|
||||
"kinds": [
|
||||
{
|
||||
"kind": "backend",
|
||||
"matched": 500
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.231",
|
||||
"backendSourceMatched": 500,
|
||||
"compiledMatched": 1060,
|
||||
"frontendChanged": false,
|
||||
"services": {
|
||||
"backend": {
|
||||
"image": "mmapp-test/backend:ux-backup231",
|
||||
"imageId": "sha256:a52c0243525dd141a10be8a6f615fed99faa04db16b6c250eb87879881b06133",
|
||||
"running": true,
|
||||
"health": "healthy"
|
||||
},
|
||||
"frontend": {
|
||||
"image": "mmapp-test/frontend:ux-routing218",
|
||||
"imageId": "sha256:ec658b9da88c19d60987be5bfc0c15fb339a0310d7a42dc761b40a70a3428c5a",
|
||||
"running": true,
|
||||
"health": null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.231",
|
||||
"kinds": [
|
||||
{
|
||||
"kind": "backend",
|
||||
"matched": 500
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.233",
|
||||
"backendSourceMatched": 503,
|
||||
"compiledMatched": 1064,
|
||||
"frontendChanged": false,
|
||||
"services": {
|
||||
"backend": {
|
||||
"image": "mmapp-test/backend:ux-backup233",
|
||||
"imageId": "sha256:f7dbe781cc96b578cc3c81d37e3cbda2d5271fd2a885cd0861f588810b4328d4",
|
||||
"running": true,
|
||||
"health": "healthy"
|
||||
},
|
||||
"frontend": {
|
||||
"image": "mmapp-test/frontend:ux-routing218",
|
||||
"imageId": "sha256:ec658b9da88c19d60987be5bfc0c15fb339a0310d7a42dc761b40a70a3428c5a",
|
||||
"running": true,
|
||||
"health": null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.233",
|
||||
"kinds": [
|
||||
{
|
||||
"kind": "backend",
|
||||
"matched": 503
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.234",
|
||||
"backendImage": "ux-backup234",
|
||||
"imageId": "sha256:0bbf998de821f9a45c58f9155506e2e2d52ca8ffcf4453351f4dde094a306b2b",
|
||||
"healthy": true,
|
||||
"sourceMatched": 504,
|
||||
"compiledMatched": 1064,
|
||||
"frontendChanged": false
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.234",
|
||||
"kinds": [
|
||||
{
|
||||
"kind": "backend",
|
||||
"matched": 504
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.230",
|
||||
"realPortalLogin": true,
|
||||
"noMocks": true,
|
||||
"views": [
|
||||
{
|
||||
"width": 1440,
|
||||
"settingsVisible": true,
|
||||
"successfulApiRead": true,
|
||||
"horizontalOverflow": false
|
||||
},
|
||||
{
|
||||
"width": 390,
|
||||
"settingsVisible": true,
|
||||
"successfulApiRead": true,
|
||||
"horizontalOverflow": false
|
||||
}
|
||||
],
|
||||
"pageErrors": 0,
|
||||
"storageMutations": 0,
|
||||
"nativeRestoreViaUI": false
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.235",
|
||||
"realPortalLogin": true,
|
||||
"noMocks": true,
|
||||
"nativeBackups": [
|
||||
{
|
||||
"bytes": 917,
|
||||
"sha256": "e168508263ea6a6195558490345af104b3766799ffaa27a5e2f6d0514737ce75",
|
||||
"hashMatchedAfterRecreate": true
|
||||
},
|
||||
{
|
||||
"bytes": 782,
|
||||
"sha256": "0e1ecfa4ea11f0a64526b5f3572bd4b241e7f8129e49b585318f4a34abe5e545",
|
||||
"hashMatchedAfterRecreate": true
|
||||
}
|
||||
],
|
||||
"ownCatalogAndFilesDeleted": true,
|
||||
"originalCatalogAllFieldsMatched": true,
|
||||
"originalCatalogRows": 10,
|
||||
"storageProviderUnchanged": "local",
|
||||
"passwordChanges": 0
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.237",
|
||||
"backendSourceMatched": 508,
|
||||
"backendCompiledMatched": 1068,
|
||||
"frontendSourceMatched": 529,
|
||||
"originalCatalogAllFieldsMatched": true,
|
||||
"originalCatalogRows": 10,
|
||||
"privateCatalogSnapshotRemoved": true,
|
||||
"containers": {
|
||||
"backend": {
|
||||
"tag": "mmapp-test/backend:ux-backups237",
|
||||
"imageId": "sha256:184aa8844b1c3aaa12e06ee47332a214e84e6962405360acb4026b392dc407ed",
|
||||
"state": "running",
|
||||
"health": "healthy",
|
||||
"backupsMounts": [
|
||||
{
|
||||
"source": "/opt/mmapp-test/data/backups",
|
||||
"destination": "/app/storage/backups"
|
||||
}
|
||||
]
|
||||
},
|
||||
"frontend": {
|
||||
"tag": "mmapp-test/frontend:ux-backups237",
|
||||
"imageId": "sha256:baf9989cde6527715890e608c2c3271c5ea40dfb235ee47a48e21939b0ec1fd0",
|
||||
"state": "running",
|
||||
"health": null,
|
||||
"backupsMounts": []
|
||||
}
|
||||
},
|
||||
"rollbackTags": {
|
||||
"backend": "ux-backup234",
|
||||
"frontend": "ux-routing218"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.237",
|
||||
"realPortalLogin": true,
|
||||
"noMocks": true,
|
||||
"existingRows": 10,
|
||||
"allLocalFilesMissing": true,
|
||||
"downloadAndRestoreDisabled": true,
|
||||
"recordOnlyDialogCancelled": true,
|
||||
"pageErrors": [],
|
||||
"backupWrites": 0,
|
||||
"screens": [
|
||||
{
|
||||
"width": 1440,
|
||||
"globalOverflow": false,
|
||||
"screenshot": "docs/ux-ui/screens/backups237-missing-desktop.png"
|
||||
},
|
||||
{
|
||||
"width": 390,
|
||||
"globalOverflow": false,
|
||||
"screenshot": "docs/ux-ui/screens/backups237-missing-mobile.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.241",
|
||||
"width": 1440,
|
||||
"fixtureRows": 1000,
|
||||
"fixtureBytes": 199062,
|
||||
"renderedRows": 50,
|
||||
"domNodes": 2477,
|
||||
"readyMs": 1203,
|
||||
"globalSearchAllRows": true,
|
||||
"lastGoodStatusRetained": true,
|
||||
"pagePreservedOnRefresh": true,
|
||||
"keyboardCancelFocusRestored": true,
|
||||
"scopedAxeViolations": 0,
|
||||
"backupWrites": 0
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"date": "2026-10-14",
|
||||
"block": "12.5.241",
|
||||
"width": 320,
|
||||
"fixtureRows": 1000,
|
||||
"fixtureBytes": 199062,
|
||||
"renderedRows": 50,
|
||||
"domNodes": 2239,
|
||||
"readyMs": 806,
|
||||
"globalSearchAllRows": true,
|
||||
"lastGoodStatusRetained": true,
|
||||
"pagePreservedOnRefresh": true,
|
||||
"keyboardCancelFocusRestored": true,
|
||||
"scopedAxeViolations": 0,
|
||||
"backupWrites": 0
|
||||
}
|
||||
@@ -0,0 +1,998 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.163",
|
||||
"backendVersion": "1.0.0-test.bgp163",
|
||||
"normalization": "CRLF to LF; emitted files derived from tracked non-test source inputs",
|
||||
"matched": [
|
||||
"backend/dist/config.js",
|
||||
"backend/dist/config.js.map",
|
||||
"backend/dist/config.d.ts",
|
||||
"backend/dist/config.d.ts.map",
|
||||
"backend/dist/constants/ping-probe.js",
|
||||
"backend/dist/constants/ping-probe.js.map",
|
||||
"backend/dist/constants/ping-probe.d.ts",
|
||||
"backend/dist/constants/ping-probe.d.ts.map",
|
||||
"backend/dist/db/bootstrap.js",
|
||||
"backend/dist/db/bootstrap.js.map",
|
||||
"backend/dist/db/bootstrap.d.ts",
|
||||
"backend/dist/db/bootstrap.d.ts.map",
|
||||
"backend/dist/db/index.js",
|
||||
"backend/dist/db/index.js.map",
|
||||
"backend/dist/db/index.d.ts",
|
||||
"backend/dist/db/index.d.ts.map",
|
||||
"backend/dist/db/json.js",
|
||||
"backend/dist/db/json.js.map",
|
||||
"backend/dist/db/json.d.ts",
|
||||
"backend/dist/db/json.d.ts.map",
|
||||
"backend/dist/db/migrate.js",
|
||||
"backend/dist/db/migrate.js.map",
|
||||
"backend/dist/db/migrate.d.ts",
|
||||
"backend/dist/db/migrate.d.ts.map",
|
||||
"backend/dist/db/operation-lock.js",
|
||||
"backend/dist/db/operation-lock.js.map",
|
||||
"backend/dist/db/operation-lock.d.ts",
|
||||
"backend/dist/db/operation-lock.d.ts.map",
|
||||
"backend/dist/db/partitions.js",
|
||||
"backend/dist/db/partitions.js.map",
|
||||
"backend/dist/db/partitions.d.ts",
|
||||
"backend/dist/db/partitions.d.ts.map",
|
||||
"backend/dist/db/schema.js",
|
||||
"backend/dist/db/schema.js.map",
|
||||
"backend/dist/db/schema.d.ts",
|
||||
"backend/dist/db/schema.d.ts.map",
|
||||
"backend/dist/db/sql-bind.js",
|
||||
"backend/dist/db/sql-bind.js.map",
|
||||
"backend/dist/db/sql-bind.d.ts",
|
||||
"backend/dist/db/sql-bind.d.ts.map",
|
||||
"backend/dist/db/sqlite-import.js",
|
||||
"backend/dist/db/sqlite-import.js.map",
|
||||
"backend/dist/db/sqlite-import.d.ts",
|
||||
"backend/dist/db/sqlite-import.d.ts.map",
|
||||
"backend/dist/db/traffic-flags.js",
|
||||
"backend/dist/db/traffic-flags.js.map",
|
||||
"backend/dist/db/traffic-flags.d.ts",
|
||||
"backend/dist/db/traffic-flags.d.ts.map",
|
||||
"backend/dist/index.js",
|
||||
"backend/dist/index.js.map",
|
||||
"backend/dist/index.d.ts",
|
||||
"backend/dist/index.d.ts.map",
|
||||
"backend/dist/lib/permissions.js",
|
||||
"backend/dist/lib/permissions.js.map",
|
||||
"backend/dist/lib/permissions.d.ts",
|
||||
"backend/dist/lib/permissions.d.ts.map",
|
||||
"backend/dist/managed-markers.js",
|
||||
"backend/dist/managed-markers.js.map",
|
||||
"backend/dist/managed-markers.d.ts",
|
||||
"backend/dist/managed-markers.d.ts.map",
|
||||
"backend/dist/modules/events/repository/events-repository.js",
|
||||
"backend/dist/modules/events/repository/events-repository.js.map",
|
||||
"backend/dist/modules/events/repository/events-repository.d.ts",
|
||||
"backend/dist/modules/events/repository/events-repository.d.ts.map",
|
||||
"backend/dist/modules/events/service/events-service.js",
|
||||
"backend/dist/modules/events/service/events-service.js.map",
|
||||
"backend/dist/modules/events/service/events-service.d.ts",
|
||||
"backend/dist/modules/events/service/events-service.d.ts.map",
|
||||
"backend/dist/modules/servers/mapper/servers-mapper.js",
|
||||
"backend/dist/modules/servers/mapper/servers-mapper.js.map",
|
||||
"backend/dist/modules/servers/mapper/servers-mapper.d.ts",
|
||||
"backend/dist/modules/servers/mapper/servers-mapper.d.ts.map",
|
||||
"backend/dist/modules/servers/repository/servers-repository.js",
|
||||
"backend/dist/modules/servers/repository/servers-repository.js.map",
|
||||
"backend/dist/modules/servers/repository/servers-repository.d.ts",
|
||||
"backend/dist/modules/servers/repository/servers-repository.d.ts.map",
|
||||
"backend/dist/modules/servers/service/servers-service.js",
|
||||
"backend/dist/modules/servers/service/servers-service.js.map",
|
||||
"backend/dist/modules/servers/service/servers-service.d.ts",
|
||||
"backend/dist/modules/servers/service/servers-service.d.ts.map",
|
||||
"backend/dist/modules/users/iface-type.js",
|
||||
"backend/dist/modules/users/iface-type.js.map",
|
||||
"backend/dist/modules/users/iface-type.d.ts",
|
||||
"backend/dist/modules/users/iface-type.d.ts.map",
|
||||
"backend/dist/modules/users/interface-inventory.js",
|
||||
"backend/dist/modules/users/interface-inventory.js.map",
|
||||
"backend/dist/modules/users/interface-inventory.d.ts",
|
||||
"backend/dist/modules/users/interface-inventory.d.ts.map",
|
||||
"backend/dist/modules/users/peer-bind.js",
|
||||
"backend/dist/modules/users/peer-bind.js.map",
|
||||
"backend/dist/modules/users/peer-bind.d.ts",
|
||||
"backend/dist/modules/users/peer-bind.d.ts.map",
|
||||
"backend/dist/modules/users/repository/users-repository.js",
|
||||
"backend/dist/modules/users/repository/users-repository.js.map",
|
||||
"backend/dist/modules/users/repository/users-repository.d.ts",
|
||||
"backend/dist/modules/users/repository/users-repository.d.ts.map",
|
||||
"backend/dist/modules/users/service/users-service.js",
|
||||
"backend/dist/modules/users/service/users-service.js.map",
|
||||
"backend/dist/modules/users/service/users-service.d.ts",
|
||||
"backend/dist/modules/users/service/users-service.d.ts.map",
|
||||
"backend/dist/plugins/auth.js",
|
||||
"backend/dist/plugins/auth.js.map",
|
||||
"backend/dist/plugins/auth.d.ts",
|
||||
"backend/dist/plugins/auth.d.ts.map",
|
||||
"backend/dist/plugins/database-request-gate.js",
|
||||
"backend/dist/plugins/database-request-gate.js.map",
|
||||
"backend/dist/plugins/database-request-gate.d.ts",
|
||||
"backend/dist/plugins/database-request-gate.d.ts.map",
|
||||
"backend/dist/routes/alerts.js",
|
||||
"backend/dist/routes/alerts.js.map",
|
||||
"backend/dist/routes/alerts.d.ts",
|
||||
"backend/dist/routes/alerts.d.ts.map",
|
||||
"backend/dist/routes/backups.js",
|
||||
"backend/dist/routes/backups.js.map",
|
||||
"backend/dist/routes/backups.d.ts",
|
||||
"backend/dist/routes/backups.d.ts.map",
|
||||
"backend/dist/routes/bgp.js",
|
||||
"backend/dist/routes/bgp.js.map",
|
||||
"backend/dist/routes/bgp.d.ts",
|
||||
"backend/dist/routes/bgp.d.ts.map",
|
||||
"backend/dist/routes/certificates.js",
|
||||
"backend/dist/routes/certificates.js.map",
|
||||
"backend/dist/routes/certificates.d.ts",
|
||||
"backend/dist/routes/certificates.d.ts.map",
|
||||
"backend/dist/routes/containers.js",
|
||||
"backend/dist/routes/containers.js.map",
|
||||
"backend/dist/routes/containers.d.ts",
|
||||
"backend/dist/routes/containers.d.ts.map",
|
||||
"backend/dist/routes/events.js",
|
||||
"backend/dist/routes/events.js.map",
|
||||
"backend/dist/routes/events.d.ts",
|
||||
"backend/dist/routes/events.d.ts.map",
|
||||
"backend/dist/routes/evobgp-catalog.js",
|
||||
"backend/dist/routes/evobgp-catalog.js.map",
|
||||
"backend/dist/routes/evobgp-catalog.d.ts",
|
||||
"backend/dist/routes/evobgp-catalog.d.ts.map",
|
||||
"backend/dist/routes/evobgp-settings.js",
|
||||
"backend/dist/routes/evobgp-settings.js.map",
|
||||
"backend/dist/routes/evobgp-settings.d.ts",
|
||||
"backend/dist/routes/evobgp-settings.d.ts.map",
|
||||
"backend/dist/routes/evobgp.js",
|
||||
"backend/dist/routes/evobgp.js.map",
|
||||
"backend/dist/routes/evobgp.d.ts",
|
||||
"backend/dist/routes/evobgp.d.ts.map",
|
||||
"backend/dist/routes/exec.js",
|
||||
"backend/dist/routes/exec.js.map",
|
||||
"backend/dist/routes/exec.d.ts",
|
||||
"backend/dist/routes/exec.d.ts.map",
|
||||
"backend/dist/routes/filters.js",
|
||||
"backend/dist/routes/filters.js.map",
|
||||
"backend/dist/routes/filters.d.ts",
|
||||
"backend/dist/routes/filters.d.ts.map",
|
||||
"backend/dist/routes/firewall.js",
|
||||
"backend/dist/routes/firewall.js.map",
|
||||
"backend/dist/routes/firewall.d.ts",
|
||||
"backend/dist/routes/firewall.d.ts.map",
|
||||
"backend/dist/routes/geoip.js",
|
||||
"backend/dist/routes/geoip.js.map",
|
||||
"backend/dist/routes/geoip.d.ts",
|
||||
"backend/dist/routes/geoip.d.ts.map",
|
||||
"backend/dist/routes/gre.js",
|
||||
"backend/dist/routes/gre.js.map",
|
||||
"backend/dist/routes/gre.d.ts",
|
||||
"backend/dist/routes/gre.d.ts.map",
|
||||
"backend/dist/routes/internet-path.js",
|
||||
"backend/dist/routes/internet-path.js.map",
|
||||
"backend/dist/routes/internet-path.d.ts",
|
||||
"backend/dist/routes/internet-path.d.ts.map",
|
||||
"backend/dist/routes/ipsec.js",
|
||||
"backend/dist/routes/ipsec.js.map",
|
||||
"backend/dist/routes/ipsec.d.ts",
|
||||
"backend/dist/routes/ipsec.d.ts.map",
|
||||
"backend/dist/routes/network.js",
|
||||
"backend/dist/routes/network.js.map",
|
||||
"backend/dist/routes/network.d.ts",
|
||||
"backend/dist/routes/network.d.ts.map",
|
||||
"backend/dist/routes/ospf.js",
|
||||
"backend/dist/routes/ospf.js.map",
|
||||
"backend/dist/routes/ospf.d.ts",
|
||||
"backend/dist/routes/ospf.d.ts.map",
|
||||
"backend/dist/routes/ping-probes-write.js",
|
||||
"backend/dist/routes/ping-probes-write.js.map",
|
||||
"backend/dist/routes/ping-probes-write.d.ts",
|
||||
"backend/dist/routes/ping-probes-write.d.ts.map",
|
||||
"backend/dist/routes/probes.js",
|
||||
"backend/dist/routes/probes.js.map",
|
||||
"backend/dist/routes/probes.d.ts",
|
||||
"backend/dist/routes/probes.d.ts.map",
|
||||
"backend/dist/routes/recursive-routes.js",
|
||||
"backend/dist/routes/recursive-routes.js.map",
|
||||
"backend/dist/routes/recursive-routes.d.ts",
|
||||
"backend/dist/routes/recursive-routes.d.ts.map",
|
||||
"backend/dist/routes/scheduler.js",
|
||||
"backend/dist/routes/scheduler.js.map",
|
||||
"backend/dist/routes/scheduler.d.ts",
|
||||
"backend/dist/routes/scheduler.d.ts.map",
|
||||
"backend/dist/routes/servers-api-ping.js",
|
||||
"backend/dist/routes/servers-api-ping.js.map",
|
||||
"backend/dist/routes/servers-api-ping.d.ts",
|
||||
"backend/dist/routes/servers-api-ping.d.ts.map",
|
||||
"backend/dist/routes/servers.js",
|
||||
"backend/dist/routes/servers.js.map",
|
||||
"backend/dist/routes/servers.d.ts",
|
||||
"backend/dist/routes/servers.d.ts.map",
|
||||
"backend/dist/routes/sidebar-counts.js",
|
||||
"backend/dist/routes/sidebar-counts.js.map",
|
||||
"backend/dist/routes/sidebar-counts.d.ts",
|
||||
"backend/dist/routes/sidebar-counts.d.ts.map",
|
||||
"backend/dist/routes/speed-probes-write.js",
|
||||
"backend/dist/routes/speed-probes-write.js.map",
|
||||
"backend/dist/routes/speed-probes-write.d.ts",
|
||||
"backend/dist/routes/speed-probes-write.d.ts.map",
|
||||
"backend/dist/routes/speed-test.js",
|
||||
"backend/dist/routes/speed-test.js.map",
|
||||
"backend/dist/routes/speed-test.d.ts",
|
||||
"backend/dist/routes/speed-test.d.ts.map",
|
||||
"backend/dist/routes/statistics.js",
|
||||
"backend/dist/routes/statistics.js.map",
|
||||
"backend/dist/routes/statistics.d.ts",
|
||||
"backend/dist/routes/statistics.d.ts.map",
|
||||
"backend/dist/routes/system-database.js",
|
||||
"backend/dist/routes/system-database.js.map",
|
||||
"backend/dist/routes/system-database.d.ts",
|
||||
"backend/dist/routes/system-database.d.ts.map",
|
||||
"backend/dist/routes/traffic-flow-purge.js",
|
||||
"backend/dist/routes/traffic-flow-purge.js.map",
|
||||
"backend/dist/routes/traffic-flow-purge.d.ts",
|
||||
"backend/dist/routes/traffic-flow-purge.d.ts.map",
|
||||
"backend/dist/routes/traffic-flow-settings.js",
|
||||
"backend/dist/routes/traffic-flow-settings.js.map",
|
||||
"backend/dist/routes/traffic-flow-settings.d.ts",
|
||||
"backend/dist/routes/traffic-flow-settings.d.ts.map",
|
||||
"backend/dist/routes/traffic-flow.js",
|
||||
"backend/dist/routes/traffic-flow.js.map",
|
||||
"backend/dist/routes/traffic-flow.d.ts",
|
||||
"backend/dist/routes/traffic-flow.d.ts.map",
|
||||
"backend/dist/routes/traffic.js",
|
||||
"backend/dist/routes/traffic.js.map",
|
||||
"backend/dist/routes/traffic.d.ts",
|
||||
"backend/dist/routes/traffic.d.ts.map",
|
||||
"backend/dist/routes/uptime.js",
|
||||
"backend/dist/routes/uptime.js.map",
|
||||
"backend/dist/routes/uptime.d.ts",
|
||||
"backend/dist/routes/uptime.d.ts.map",
|
||||
"backend/dist/routes/users.js",
|
||||
"backend/dist/routes/users.js.map",
|
||||
"backend/dist/routes/users.d.ts",
|
||||
"backend/dist/routes/users.d.ts.map",
|
||||
"backend/dist/routes/vxlan.js",
|
||||
"backend/dist/routes/vxlan.js.map",
|
||||
"backend/dist/routes/vxlan.d.ts",
|
||||
"backend/dist/routes/vxlan.d.ts.map",
|
||||
"backend/dist/routes/wireguard.js",
|
||||
"backend/dist/routes/wireguard.js.map",
|
||||
"backend/dist/routes/wireguard.d.ts",
|
||||
"backend/dist/routes/wireguard.d.ts.map",
|
||||
"backend/dist/scripts/migrate-sqlite-to-pg.js",
|
||||
"backend/dist/scripts/migrate-sqlite-to-pg.js.map",
|
||||
"backend/dist/scripts/migrate-sqlite-to-pg.d.ts",
|
||||
"backend/dist/scripts/migrate-sqlite-to-pg.d.ts.map",
|
||||
"backend/dist/scripts/rebuild-flow-facts.js",
|
||||
"backend/dist/scripts/rebuild-flow-facts.js.map",
|
||||
"backend/dist/scripts/rebuild-flow-facts.d.ts",
|
||||
"backend/dist/scripts/rebuild-flow-facts.d.ts.map",
|
||||
"backend/dist/services/acme-cloudflare.js",
|
||||
"backend/dist/services/acme-cloudflare.js.map",
|
||||
"backend/dist/services/acme-cloudflare.d.ts",
|
||||
"backend/dist/services/acme-cloudflare.d.ts.map",
|
||||
"backend/dist/services/alert-collector-hooks.js",
|
||||
"backend/dist/services/alert-collector-hooks.js.map",
|
||||
"backend/dist/services/alert-collector-hooks.d.ts",
|
||||
"backend/dist/services/alert-collector-hooks.d.ts.map",
|
||||
"backend/dist/services/alert-engine/confirm-stability.js",
|
||||
"backend/dist/services/alert-engine/confirm-stability.js.map",
|
||||
"backend/dist/services/alert-engine/confirm-stability.d.ts",
|
||||
"backend/dist/services/alert-engine/confirm-stability.d.ts.map",
|
||||
"backend/dist/services/alert-engine/cooldown.js",
|
||||
"backend/dist/services/alert-engine/cooldown.js.map",
|
||||
"backend/dist/services/alert-engine/cooldown.d.ts",
|
||||
"backend/dist/services/alert-engine/cooldown.d.ts.map",
|
||||
"backend/dist/services/alert-engine/decision-engine.js",
|
||||
"backend/dist/services/alert-engine/decision-engine.js.map",
|
||||
"backend/dist/services/alert-engine/decision-engine.d.ts",
|
||||
"backend/dist/services/alert-engine/decision-engine.d.ts.map",
|
||||
"backend/dist/services/alert-engine/evaluate-rule.js",
|
||||
"backend/dist/services/alert-engine/evaluate-rule.js.map",
|
||||
"backend/dist/services/alert-engine/evaluate-rule.d.ts",
|
||||
"backend/dist/services/alert-engine/evaluate-rule.d.ts.map",
|
||||
"backend/dist/services/alert-engine/groups.js",
|
||||
"backend/dist/services/alert-engine/groups.js.map",
|
||||
"backend/dist/services/alert-engine/groups.d.ts",
|
||||
"backend/dist/services/alert-engine/groups.d.ts.map",
|
||||
"backend/dist/services/alert-engine/outbox-execution.js",
|
||||
"backend/dist/services/alert-engine/outbox-execution.js.map",
|
||||
"backend/dist/services/alert-engine/outbox-execution.d.ts",
|
||||
"backend/dist/services/alert-engine/outbox-execution.d.ts.map",
|
||||
"backend/dist/services/alert-engine/outbox.js",
|
||||
"backend/dist/services/alert-engine/outbox.js.map",
|
||||
"backend/dist/services/alert-engine/outbox.d.ts",
|
||||
"backend/dist/services/alert-engine/outbox.d.ts.map",
|
||||
"backend/dist/services/alert-engine/prev-live-store.js",
|
||||
"backend/dist/services/alert-engine/prev-live-store.js.map",
|
||||
"backend/dist/services/alert-engine/prev-live-store.d.ts",
|
||||
"backend/dist/services/alert-engine/prev-live-store.d.ts.map",
|
||||
"backend/dist/services/alert-engine/rule-matcher.js",
|
||||
"backend/dist/services/alert-engine/rule-matcher.js.map",
|
||||
"backend/dist/services/alert-engine/rule-matcher.d.ts",
|
||||
"backend/dist/services/alert-engine/rule-matcher.d.ts.map",
|
||||
"backend/dist/services/alert-engine/run-once.js",
|
||||
"backend/dist/services/alert-engine/run-once.js.map",
|
||||
"backend/dist/services/alert-engine/run-once.d.ts",
|
||||
"backend/dist/services/alert-engine/run-once.d.ts.map",
|
||||
"backend/dist/services/alert-engine/signal-ingestor.js",
|
||||
"backend/dist/services/alert-engine/signal-ingestor.js.map",
|
||||
"backend/dist/services/alert-engine/signal-ingestor.d.ts",
|
||||
"backend/dist/services/alert-engine/signal-ingestor.d.ts.map",
|
||||
"backend/dist/services/alert-engine/signals-from-collectors.js",
|
||||
"backend/dist/services/alert-engine/signals-from-collectors.js.map",
|
||||
"backend/dist/services/alert-engine/signals-from-collectors.d.ts",
|
||||
"backend/dist/services/alert-engine/signals-from-collectors.d.ts.map",
|
||||
"backend/dist/services/alert-engine/snapshot.js",
|
||||
"backend/dist/services/alert-engine/snapshot.js.map",
|
||||
"backend/dist/services/alert-engine/snapshot.d.ts",
|
||||
"backend/dist/services/alert-engine/snapshot.d.ts.map",
|
||||
"backend/dist/services/alert-engine/source-watermark.js",
|
||||
"backend/dist/services/alert-engine/source-watermark.js.map",
|
||||
"backend/dist/services/alert-engine/source-watermark.d.ts",
|
||||
"backend/dist/services/alert-engine/source-watermark.d.ts.map",
|
||||
"backend/dist/services/alert-engine/state-machine.js",
|
||||
"backend/dist/services/alert-engine/state-machine.js.map",
|
||||
"backend/dist/services/alert-engine/state-machine.d.ts",
|
||||
"backend/dist/services/alert-engine/state-machine.d.ts.map",
|
||||
"backend/dist/services/alert-engine/telegram-emoji.js",
|
||||
"backend/dist/services/alert-engine/telegram-emoji.js.map",
|
||||
"backend/dist/services/alert-engine/telegram-emoji.d.ts",
|
||||
"backend/dist/services/alert-engine/telegram-emoji.d.ts.map",
|
||||
"backend/dist/services/alert-engine/types.js",
|
||||
"backend/dist/services/alert-engine/types.js.map",
|
||||
"backend/dist/services/alert-engine/types.d.ts",
|
||||
"backend/dist/services/alert-engine/types.d.ts.map",
|
||||
"backend/dist/services/alerts-config-execution.js",
|
||||
"backend/dist/services/alerts-config-execution.js.map",
|
||||
"backend/dist/services/alerts-config-execution.d.ts",
|
||||
"backend/dist/services/alerts-config-execution.d.ts.map",
|
||||
"backend/dist/services/alerts-outbox-overview.js",
|
||||
"backend/dist/services/alerts-outbox-overview.js.map",
|
||||
"backend/dist/services/alerts-outbox-overview.d.ts",
|
||||
"backend/dist/services/alerts-outbox-overview.d.ts.map",
|
||||
"backend/dist/services/alerts-outbox-retry.js",
|
||||
"backend/dist/services/alerts-outbox-retry.js.map",
|
||||
"backend/dist/services/alerts-outbox-retry.d.ts",
|
||||
"backend/dist/services/alerts-outbox-retry.d.ts.map",
|
||||
"backend/dist/services/alerts-overview.js",
|
||||
"backend/dist/services/alerts-overview.js.map",
|
||||
"backend/dist/services/alerts-overview.d.ts",
|
||||
"backend/dist/services/alerts-overview.d.ts.map",
|
||||
"backend/dist/services/alerts-revision.js",
|
||||
"backend/dist/services/alerts-revision.js.map",
|
||||
"backend/dist/services/alerts-revision.d.ts",
|
||||
"backend/dist/services/alerts-revision.d.ts.map",
|
||||
"backend/dist/services/alerts-service.js",
|
||||
"backend/dist/services/alerts-service.js.map",
|
||||
"backend/dist/services/alerts-service.d.ts",
|
||||
"backend/dist/services/alerts-service.d.ts.map",
|
||||
"backend/dist/services/alerts-telegram-delivery.js",
|
||||
"backend/dist/services/alerts-telegram-delivery.js.map",
|
||||
"backend/dist/services/alerts-telegram-delivery.d.ts",
|
||||
"backend/dist/services/alerts-telegram-delivery.d.ts.map",
|
||||
"backend/dist/services/alerts-telegram-send.js",
|
||||
"backend/dist/services/alerts-telegram-send.js.map",
|
||||
"backend/dist/services/alerts-telegram-send.d.ts",
|
||||
"backend/dist/services/alerts-telegram-send.d.ts.map",
|
||||
"backend/dist/services/alerts-telegram-settings.js",
|
||||
"backend/dist/services/alerts-telegram-settings.js.map",
|
||||
"backend/dist/services/alerts-telegram-settings.d.ts",
|
||||
"backend/dist/services/alerts-telegram-settings.d.ts.map",
|
||||
"backend/dist/services/backup-deletion.js",
|
||||
"backend/dist/services/backup-deletion.js.map",
|
||||
"backend/dist/services/backup-deletion.d.ts",
|
||||
"backend/dist/services/backup-deletion.d.ts.map",
|
||||
"backend/dist/services/backup-dto.js",
|
||||
"backend/dist/services/backup-dto.js.map",
|
||||
"backend/dist/services/backup-dto.d.ts",
|
||||
"backend/dist/services/backup-dto.d.ts.map",
|
||||
"backend/dist/services/backup-job-execution.js",
|
||||
"backend/dist/services/backup-job-execution.js.map",
|
||||
"backend/dist/services/backup-job-execution.d.ts",
|
||||
"backend/dist/services/backup-job-execution.d.ts.map",
|
||||
"backend/dist/services/backup-prune.js",
|
||||
"backend/dist/services/backup-prune.js.map",
|
||||
"backend/dist/services/backup-prune.d.ts",
|
||||
"backend/dist/services/backup-prune.d.ts.map",
|
||||
"backend/dist/services/backup-restore.js",
|
||||
"backend/dist/services/backup-restore.js.map",
|
||||
"backend/dist/services/backup-restore.d.ts",
|
||||
"backend/dist/services/backup-restore.d.ts.map",
|
||||
"backend/dist/services/backup-scheduler-collector.js",
|
||||
"backend/dist/services/backup-scheduler-collector.js.map",
|
||||
"backend/dist/services/backup-scheduler-collector.d.ts",
|
||||
"backend/dist/services/backup-scheduler-collector.d.ts.map",
|
||||
"backend/dist/services/backup-scheduler-run.js",
|
||||
"backend/dist/services/backup-scheduler-run.js.map",
|
||||
"backend/dist/services/backup-scheduler-run.d.ts",
|
||||
"backend/dist/services/backup-scheduler-run.d.ts.map",
|
||||
"backend/dist/services/backup-service.js",
|
||||
"backend/dist/services/backup-service.js.map",
|
||||
"backend/dist/services/backup-service.d.ts",
|
||||
"backend/dist/services/backup-service.d.ts.map",
|
||||
"backend/dist/services/backup-storage-update.js",
|
||||
"backend/dist/services/backup-storage-update.js.map",
|
||||
"backend/dist/services/backup-storage-update.d.ts",
|
||||
"backend/dist/services/backup-storage-update.d.ts.map",
|
||||
"backend/dist/services/bandwidth-test-rates.js",
|
||||
"backend/dist/services/bandwidth-test-rates.js.map",
|
||||
"backend/dist/services/bandwidth-test-rates.d.ts",
|
||||
"backend/dist/services/bandwidth-test-rates.d.ts.map",
|
||||
"backend/dist/services/bandwidth-test-status.js",
|
||||
"backend/dist/services/bandwidth-test-status.js.map",
|
||||
"backend/dist/services/bandwidth-test-status.d.ts",
|
||||
"backend/dist/services/bandwidth-test-status.d.ts.map",
|
||||
"backend/dist/services/bgp-catalog-poll.js",
|
||||
"backend/dist/services/bgp-catalog-poll.js.map",
|
||||
"backend/dist/services/bgp-catalog-poll.d.ts",
|
||||
"backend/dist/services/bgp-catalog-poll.d.ts.map",
|
||||
"backend/dist/services/bgp-parse-sessions.js",
|
||||
"backend/dist/services/bgp-parse-sessions.js.map",
|
||||
"backend/dist/services/bgp-parse-sessions.d.ts",
|
||||
"backend/dist/services/bgp-parse-sessions.d.ts.map",
|
||||
"backend/dist/services/bgp-peers-live.js",
|
||||
"backend/dist/services/bgp-peers-live.js.map",
|
||||
"backend/dist/services/bgp-peers-live.d.ts",
|
||||
"backend/dist/services/bgp-peers-live.d.ts.map",
|
||||
"backend/dist/services/btest-node-locks.js",
|
||||
"backend/dist/services/btest-node-locks.js.map",
|
||||
"backend/dist/services/btest-node-locks.d.ts",
|
||||
"backend/dist/services/btest-node-locks.d.ts.map",
|
||||
"backend/dist/services/certificate-issue-dto.js",
|
||||
"backend/dist/services/certificate-issue-dto.js.map",
|
||||
"backend/dist/services/certificate-issue-dto.d.ts",
|
||||
"backend/dist/services/certificate-issue-dto.d.ts.map",
|
||||
"backend/dist/services/certificate-issue-execution.js",
|
||||
"backend/dist/services/certificate-issue-execution.js.map",
|
||||
"backend/dist/services/certificate-issue-execution.d.ts",
|
||||
"backend/dist/services/certificate-issue-execution.d.ts.map",
|
||||
"backend/dist/services/certificate-issue-request.js",
|
||||
"backend/dist/services/certificate-issue-request.js.map",
|
||||
"backend/dist/services/certificate-issue-request.d.ts",
|
||||
"backend/dist/services/certificate-issue-request.d.ts.map",
|
||||
"backend/dist/services/certificate-issue-runner.js",
|
||||
"backend/dist/services/certificate-issue-runner.js.map",
|
||||
"backend/dist/services/certificate-issue-runner.d.ts",
|
||||
"backend/dist/services/certificate-issue-runner.d.ts.map",
|
||||
"backend/dist/services/certificate-parse.js",
|
||||
"backend/dist/services/certificate-parse.js.map",
|
||||
"backend/dist/services/certificate-parse.d.ts",
|
||||
"backend/dist/services/certificate-parse.d.ts.map",
|
||||
"backend/dist/services/certificate-renew-collector.js",
|
||||
"backend/dist/services/certificate-renew-collector.js.map",
|
||||
"backend/dist/services/certificate-renew-collector.d.ts",
|
||||
"backend/dist/services/certificate-renew-collector.d.ts.map",
|
||||
"backend/dist/services/certificates-service.js",
|
||||
"backend/dist/services/certificates-service.js.map",
|
||||
"backend/dist/services/certificates-service.d.ts",
|
||||
"backend/dist/services/certificates-service.d.ts.map",
|
||||
"backend/dist/services/certificates-state.js",
|
||||
"backend/dist/services/certificates-state.js.map",
|
||||
"backend/dist/services/certificates-state.d.ts",
|
||||
"backend/dist/services/certificates-state.d.ts.map",
|
||||
"backend/dist/services/complete-count.js",
|
||||
"backend/dist/services/complete-count.js.map",
|
||||
"backend/dist/services/complete-count.d.ts",
|
||||
"backend/dist/services/complete-count.d.ts.map",
|
||||
"backend/dist/services/config-apply-plan.js",
|
||||
"backend/dist/services/config-apply-plan.js.map",
|
||||
"backend/dist/services/config-apply-plan.d.ts",
|
||||
"backend/dist/services/config-apply-plan.d.ts.map",
|
||||
"backend/dist/services/config-revisions.js",
|
||||
"backend/dist/services/config-revisions.js.map",
|
||||
"backend/dist/services/config-revisions.d.ts",
|
||||
"backend/dist/services/config-revisions.d.ts.map",
|
||||
"backend/dist/services/containers-live.js",
|
||||
"backend/dist/services/containers-live.js.map",
|
||||
"backend/dist/services/containers-live.d.ts",
|
||||
"backend/dist/services/containers-live.d.ts.map",
|
||||
"backend/dist/services/containers-state.js",
|
||||
"backend/dist/services/containers-state.js.map",
|
||||
"backend/dist/services/containers-state.d.ts",
|
||||
"backend/dist/services/containers-state.d.ts.map",
|
||||
"backend/dist/services/database-background-work.js",
|
||||
"backend/dist/services/database-background-work.js.map",
|
||||
"backend/dist/services/database-background-work.d.ts",
|
||||
"backend/dist/services/database-background-work.d.ts.map",
|
||||
"backend/dist/services/database-request-gate.js",
|
||||
"backend/dist/services/database-request-gate.js.map",
|
||||
"backend/dist/services/database-request-gate.d.ts",
|
||||
"backend/dist/services/database-request-gate.d.ts.map",
|
||||
"backend/dist/services/entity-snapshots.js",
|
||||
"backend/dist/services/entity-snapshots.js.map",
|
||||
"backend/dist/services/entity-snapshots.d.ts",
|
||||
"backend/dist/services/entity-snapshots.d.ts.map",
|
||||
"backend/dist/services/evobgp-catalog.js",
|
||||
"backend/dist/services/evobgp-catalog.js.map",
|
||||
"backend/dist/services/evobgp-catalog.d.ts",
|
||||
"backend/dist/services/evobgp-catalog.d.ts.map",
|
||||
"backend/dist/services/firewall-live.js",
|
||||
"backend/dist/services/firewall-live.js.map",
|
||||
"backend/dist/services/firewall-live.d.ts",
|
||||
"backend/dist/services/firewall-live.d.ts.map",
|
||||
"backend/dist/services/firewall-poll.js",
|
||||
"backend/dist/services/firewall-poll.js.map",
|
||||
"backend/dist/services/firewall-poll.d.ts",
|
||||
"backend/dist/services/firewall-poll.d.ts.map",
|
||||
"backend/dist/services/geoip-settings.js",
|
||||
"backend/dist/services/geoip-settings.js.map",
|
||||
"backend/dist/services/geoip-settings.d.ts",
|
||||
"backend/dist/services/geoip-settings.d.ts.map",
|
||||
"backend/dist/services/geoip-update-collector.js",
|
||||
"backend/dist/services/geoip-update-collector.js.map",
|
||||
"backend/dist/services/geoip-update-collector.d.ts",
|
||||
"backend/dist/services/geoip-update-collector.d.ts.map",
|
||||
"backend/dist/services/gre-bgp-snapshot-collector.js",
|
||||
"backend/dist/services/gre-bgp-snapshot-collector.js.map",
|
||||
"backend/dist/services/gre-bgp-snapshot-collector.d.ts",
|
||||
"backend/dist/services/gre-bgp-snapshot-collector.d.ts.map",
|
||||
"backend/dist/services/gre-catalog-poll.js",
|
||||
"backend/dist/services/gre-catalog-poll.js.map",
|
||||
"backend/dist/services/gre-catalog-poll.d.ts",
|
||||
"backend/dist/services/gre-catalog-poll.d.ts.map",
|
||||
"backend/dist/services/gre-comment.js",
|
||||
"backend/dist/services/gre-comment.js.map",
|
||||
"backend/dist/services/gre-comment.d.ts",
|
||||
"backend/dist/services/gre-comment.d.ts.map",
|
||||
"backend/dist/services/gre-live.js",
|
||||
"backend/dist/services/gre-live.js.map",
|
||||
"backend/dist/services/gre-live.d.ts",
|
||||
"backend/dist/services/gre-live.d.ts.map",
|
||||
"backend/dist/services/gre-tunnels-live.js",
|
||||
"backend/dist/services/gre-tunnels-live.js.map",
|
||||
"backend/dist/services/gre-tunnels-live.d.ts",
|
||||
"backend/dist/services/gre-tunnels-live.d.ts.map",
|
||||
"backend/dist/services/internet-path-collector.js",
|
||||
"backend/dist/services/internet-path-collector.js.map",
|
||||
"backend/dist/services/internet-path-collector.d.ts",
|
||||
"backend/dist/services/internet-path-collector.d.ts.map",
|
||||
"backend/dist/services/internet-path-snapshot.js",
|
||||
"backend/dist/services/internet-path-snapshot.js.map",
|
||||
"backend/dist/services/internet-path-snapshot.d.ts",
|
||||
"backend/dist/services/internet-path-snapshot.d.ts.map",
|
||||
"backend/dist/services/ipsec-ca.js",
|
||||
"backend/dist/services/ipsec-ca.js.map",
|
||||
"backend/dist/services/ipsec-ca.d.ts",
|
||||
"backend/dist/services/ipsec-ca.d.ts.map",
|
||||
"backend/dist/services/ipsec-certificate-dn.js",
|
||||
"backend/dist/services/ipsec-certificate-dn.js.map",
|
||||
"backend/dist/services/ipsec-certificate-dn.d.ts",
|
||||
"backend/dist/services/ipsec-certificate-dn.d.ts.map",
|
||||
"backend/dist/services/ipsec-cleanup.js",
|
||||
"backend/dist/services/ipsec-cleanup.js.map",
|
||||
"backend/dist/services/ipsec-cleanup.d.ts",
|
||||
"backend/dist/services/ipsec-cleanup.d.ts.map",
|
||||
"backend/dist/services/ipsec-config.js",
|
||||
"backend/dist/services/ipsec-config.js.map",
|
||||
"backend/dist/services/ipsec-config.d.ts",
|
||||
"backend/dist/services/ipsec-config.d.ts.map",
|
||||
"backend/dist/services/ipsec-live.js",
|
||||
"backend/dist/services/ipsec-live.js.map",
|
||||
"backend/dist/services/ipsec-live.d.ts",
|
||||
"backend/dist/services/ipsec-live.d.ts.map",
|
||||
"backend/dist/services/ipsec-operation.js",
|
||||
"backend/dist/services/ipsec-operation.js.map",
|
||||
"backend/dist/services/ipsec-operation.d.ts",
|
||||
"backend/dist/services/ipsec-operation.d.ts.map",
|
||||
"backend/dist/services/ipsec-ros.js",
|
||||
"backend/dist/services/ipsec-ros.js.map",
|
||||
"backend/dist/services/ipsec-ros.d.ts",
|
||||
"backend/dist/services/ipsec-ros.d.ts.map",
|
||||
"backend/dist/services/mikrotik.js",
|
||||
"backend/dist/services/mikrotik.js.map",
|
||||
"backend/dist/services/mikrotik.d.ts",
|
||||
"backend/dist/services/mikrotik.d.ts.map",
|
||||
"backend/dist/services/monitoring-server-catalog.js",
|
||||
"backend/dist/services/monitoring-server-catalog.js.map",
|
||||
"backend/dist/services/monitoring-server-catalog.d.ts",
|
||||
"backend/dist/services/monitoring-server-catalog.d.ts.map",
|
||||
"backend/dist/services/ospf-catalog-poll.js",
|
||||
"backend/dist/services/ospf-catalog-poll.js.map",
|
||||
"backend/dist/services/ospf-catalog-poll.d.ts",
|
||||
"backend/dist/services/ospf-catalog-poll.d.ts.map",
|
||||
"backend/dist/services/ospf-effective-disabled.js",
|
||||
"backend/dist/services/ospf-effective-disabled.js.map",
|
||||
"backend/dist/services/ospf-effective-disabled.d.ts",
|
||||
"backend/dist/services/ospf-effective-disabled.d.ts.map",
|
||||
"backend/dist/services/ospf-observed-values.js",
|
||||
"backend/dist/services/ospf-observed-values.js.map",
|
||||
"backend/dist/services/ospf-observed-values.d.ts",
|
||||
"backend/dist/services/ospf-observed-values.d.ts.map",
|
||||
"backend/dist/services/ospf-optimizer-identity.js",
|
||||
"backend/dist/services/ospf-optimizer-identity.js.map",
|
||||
"backend/dist/services/ospf-optimizer-identity.d.ts",
|
||||
"backend/dist/services/ospf-optimizer-identity.d.ts.map",
|
||||
"backend/dist/services/ospf-optimizer-metrics.js",
|
||||
"backend/dist/services/ospf-optimizer-metrics.js.map",
|
||||
"backend/dist/services/ospf-optimizer-metrics.d.ts",
|
||||
"backend/dist/services/ospf-optimizer-metrics.d.ts.map",
|
||||
"backend/dist/services/ospf-optimizer-plan.js",
|
||||
"backend/dist/services/ospf-optimizer-plan.js.map",
|
||||
"backend/dist/services/ospf-optimizer-plan.d.ts",
|
||||
"backend/dist/services/ospf-optimizer-plan.d.ts.map",
|
||||
"backend/dist/services/ospf-route-parse.js",
|
||||
"backend/dist/services/ospf-route-parse.js.map",
|
||||
"backend/dist/services/ospf-route-parse.d.ts",
|
||||
"backend/dist/services/ospf-route-parse.d.ts.map",
|
||||
"backend/dist/services/ping-probe-replacement.js",
|
||||
"backend/dist/services/ping-probe-replacement.js.map",
|
||||
"backend/dist/services/ping-probe-replacement.d.ts",
|
||||
"backend/dist/services/ping-probe-replacement.d.ts.map",
|
||||
"backend/dist/services/poller.js",
|
||||
"backend/dist/services/poller.js.map",
|
||||
"backend/dist/services/poller.d.ts",
|
||||
"backend/dist/services/poller.d.ts.map",
|
||||
"backend/dist/services/recursive-apply.js",
|
||||
"backend/dist/services/recursive-apply.js.map",
|
||||
"backend/dist/services/recursive-apply.d.ts",
|
||||
"backend/dist/services/recursive-apply.d.ts.map",
|
||||
"backend/dist/services/recursive-route-catalog.js",
|
||||
"backend/dist/services/recursive-route-catalog.js.map",
|
||||
"backend/dist/services/recursive-route-catalog.d.ts",
|
||||
"backend/dist/services/recursive-route-catalog.d.ts.map",
|
||||
"backend/dist/services/recursive-route-validation.js",
|
||||
"backend/dist/services/recursive-route-validation.js.map",
|
||||
"backend/dist/services/recursive-route-validation.d.ts",
|
||||
"backend/dist/services/recursive-route-validation.d.ts.map",
|
||||
"backend/dist/services/ros-metric-parse.js",
|
||||
"backend/dist/services/ros-metric-parse.js.map",
|
||||
"backend/dist/services/ros-metric-parse.d.ts",
|
||||
"backend/dist/services/ros-metric-parse.d.ts.map",
|
||||
"backend/dist/services/ros-ops.js",
|
||||
"backend/dist/services/ros-ops.js.map",
|
||||
"backend/dist/services/ros-ops.d.ts",
|
||||
"backend/dist/services/ros-ops.d.ts.map",
|
||||
"backend/dist/services/s3-backup-client.js",
|
||||
"backend/dist/services/s3-backup-client.js.map",
|
||||
"backend/dist/services/s3-backup-client.d.ts",
|
||||
"backend/dist/services/s3-backup-client.d.ts.map",
|
||||
"backend/dist/services/scheduler-recorded-run.js",
|
||||
"backend/dist/services/scheduler-recorded-run.js.map",
|
||||
"backend/dist/services/scheduler-recorded-run.d.ts",
|
||||
"backend/dist/services/scheduler-recorded-run.d.ts.map",
|
||||
"backend/dist/services/scheduler-running.js",
|
||||
"backend/dist/services/scheduler-running.js.map",
|
||||
"backend/dist/services/scheduler-running.d.ts",
|
||||
"backend/dist/services/scheduler-running.d.ts.map",
|
||||
"backend/dist/services/scheduler.js",
|
||||
"backend/dist/services/scheduler.js.map",
|
||||
"backend/dist/services/scheduler.d.ts",
|
||||
"backend/dist/services/scheduler.d.ts.map",
|
||||
"backend/dist/services/serial-operation.js",
|
||||
"backend/dist/services/serial-operation.js.map",
|
||||
"backend/dist/services/serial-operation.d.ts",
|
||||
"backend/dist/services/serial-operation.d.ts.map",
|
||||
"backend/dist/services/servers-rest-ping-collector.js",
|
||||
"backend/dist/services/servers-rest-ping-collector.js.map",
|
||||
"backend/dist/services/servers-rest-ping-collector.d.ts",
|
||||
"backend/dist/services/servers-rest-ping-collector.d.ts.map",
|
||||
"backend/dist/services/speed-history-dto.js",
|
||||
"backend/dist/services/speed-history-dto.js.map",
|
||||
"backend/dist/services/speed-history-dto.d.ts",
|
||||
"backend/dist/services/speed-history-dto.d.ts.map",
|
||||
"backend/dist/services/speed-probe-dto.js",
|
||||
"backend/dist/services/speed-probe-dto.js.map",
|
||||
"backend/dist/services/speed-probe-dto.d.ts",
|
||||
"backend/dist/services/speed-probe-dto.d.ts.map",
|
||||
"backend/dist/services/speed-probe-replacement.js",
|
||||
"backend/dist/services/speed-probe-replacement.js.map",
|
||||
"backend/dist/services/speed-probe-replacement.d.ts",
|
||||
"backend/dist/services/speed-probe-replacement.d.ts.map",
|
||||
"backend/dist/services/speed-run-error-message.js",
|
||||
"backend/dist/services/speed-run-error-message.js.map",
|
||||
"backend/dist/services/speed-run-error-message.d.ts",
|
||||
"backend/dist/services/speed-run-error-message.d.ts.map",
|
||||
"backend/dist/services/speed-run-persistence.js",
|
||||
"backend/dist/services/speed-run-persistence.js.map",
|
||||
"backend/dist/services/speed-run-persistence.d.ts",
|
||||
"backend/dist/services/speed-run-persistence.d.ts.map",
|
||||
"backend/dist/services/statistics-aggregate.js",
|
||||
"backend/dist/services/statistics-aggregate.js.map",
|
||||
"backend/dist/services/statistics-aggregate.d.ts",
|
||||
"backend/dist/services/statistics-aggregate.d.ts.map",
|
||||
"backend/dist/services/system-database-backup.js",
|
||||
"backend/dist/services/system-database-backup.js.map",
|
||||
"backend/dist/services/system-database-backup.d.ts",
|
||||
"backend/dist/services/system-database-backup.d.ts.map",
|
||||
"backend/dist/services/system-database-cache.js",
|
||||
"backend/dist/services/system-database-cache.js.map",
|
||||
"backend/dist/services/system-database-cache.d.ts",
|
||||
"backend/dist/services/system-database-cache.d.ts.map",
|
||||
"backend/dist/services/system-database-operation.js",
|
||||
"backend/dist/services/system-database-operation.js.map",
|
||||
"backend/dist/services/system-database-operation.d.ts",
|
||||
"backend/dist/services/system-database-operation.d.ts.map",
|
||||
"backend/dist/services/system-database-partition-restore.js",
|
||||
"backend/dist/services/system-database-partition-restore.js.map",
|
||||
"backend/dist/services/system-database-partition-restore.d.ts",
|
||||
"backend/dist/services/system-database-partition-restore.d.ts.map",
|
||||
"backend/dist/services/system-database-restore-execution.js",
|
||||
"backend/dist/services/system-database-restore-execution.js.map",
|
||||
"backend/dist/services/system-database-restore-execution.d.ts",
|
||||
"backend/dist/services/system-database-restore-execution.d.ts.map",
|
||||
"backend/dist/services/traffic-collector.js",
|
||||
"backend/dist/services/traffic-collector.js.map",
|
||||
"backend/dist/services/traffic-collector.d.ts",
|
||||
"backend/dist/services/traffic-collector.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-analytics.js",
|
||||
"backend/dist/services/traffic-flow-analytics.js.map",
|
||||
"backend/dist/services/traffic-flow-analytics.d.ts",
|
||||
"backend/dist/services/traffic-flow-analytics.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-apps.js",
|
||||
"backend/dist/services/traffic-flow-apps.js.map",
|
||||
"backend/dist/services/traffic-flow-apps.d.ts",
|
||||
"backend/dist/services/traffic-flow-apps.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-brands.js",
|
||||
"backend/dist/services/traffic-flow-brands.js.map",
|
||||
"backend/dist/services/traffic-flow-brands.d.ts",
|
||||
"backend/dist/services/traffic-flow-brands.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-classify.js",
|
||||
"backend/dist/services/traffic-flow-classify.js.map",
|
||||
"backend/dist/services/traffic-flow-classify.d.ts",
|
||||
"backend/dist/services/traffic-flow-classify.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-collector-ipc.js",
|
||||
"backend/dist/services/traffic-flow-collector-ipc.js.map",
|
||||
"backend/dist/services/traffic-flow-collector-ipc.d.ts",
|
||||
"backend/dist/services/traffic-flow-collector-ipc.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-collector-worker.js",
|
||||
"backend/dist/services/traffic-flow-collector-worker.js.map",
|
||||
"backend/dist/services/traffic-flow-collector-worker.d.ts",
|
||||
"backend/dist/services/traffic-flow-collector-worker.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-dedup.js",
|
||||
"backend/dist/services/traffic-flow-dedup.js.map",
|
||||
"backend/dist/services/traffic-flow-dedup.d.ts",
|
||||
"backend/dist/services/traffic-flow-dedup.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-dest.js",
|
||||
"backend/dist/services/traffic-flow-dest.js.map",
|
||||
"backend/dist/services/traffic-flow-dest.d.ts",
|
||||
"backend/dist/services/traffic-flow-dest.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-engine.js",
|
||||
"backend/dist/services/traffic-flow-engine.js.map",
|
||||
"backend/dist/services/traffic-flow-engine.d.ts",
|
||||
"backend/dist/services/traffic-flow-engine.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-facts-filter.js",
|
||||
"backend/dist/services/traffic-flow-facts-filter.js.map",
|
||||
"backend/dist/services/traffic-flow-facts-filter.d.ts",
|
||||
"backend/dist/services/traffic-flow-facts-filter.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-facts-rebuild.js",
|
||||
"backend/dist/services/traffic-flow-facts-rebuild.js.map",
|
||||
"backend/dist/services/traffic-flow-facts-rebuild.d.ts",
|
||||
"backend/dist/services/traffic-flow-facts-rebuild.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-facts.js",
|
||||
"backend/dist/services/traffic-flow-facts.js.map",
|
||||
"backend/dist/services/traffic-flow-facts.d.ts",
|
||||
"backend/dist/services/traffic-flow-facts.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-geoip.js",
|
||||
"backend/dist/services/traffic-flow-geoip.js.map",
|
||||
"backend/dist/services/traffic-flow-geoip.d.ts",
|
||||
"backend/dist/services/traffic-flow-geoip.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-host-file-builders.js",
|
||||
"backend/dist/services/traffic-flow-host-file-builders.js.map",
|
||||
"backend/dist/services/traffic-flow-host-file-builders.d.ts",
|
||||
"backend/dist/services/traffic-flow-host-file-builders.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-host-files.js",
|
||||
"backend/dist/services/traffic-flow-host-files.js.map",
|
||||
"backend/dist/services/traffic-flow-host-files.d.ts",
|
||||
"backend/dist/services/traffic-flow-host-files.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-ifaces.js",
|
||||
"backend/dist/services/traffic-flow-ifaces.js.map",
|
||||
"backend/dist/services/traffic-flow-ifaces.d.ts",
|
||||
"backend/dist/services/traffic-flow-ifaces.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-ifindex.js",
|
||||
"backend/dist/services/traffic-flow-ifindex.js.map",
|
||||
"backend/dist/services/traffic-flow-ifindex.d.ts",
|
||||
"backend/dist/services/traffic-flow-ifindex.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-ingest.js",
|
||||
"backend/dist/services/traffic-flow-ingest.js.map",
|
||||
"backend/dist/services/traffic-flow-ingest.d.ts",
|
||||
"backend/dist/services/traffic-flow-ingest.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-ip.js",
|
||||
"backend/dist/services/traffic-flow-ip.js.map",
|
||||
"backend/dist/services/traffic-flow-ip.d.ts",
|
||||
"backend/dist/services/traffic-flow-ip.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-key-execution.js",
|
||||
"backend/dist/services/traffic-flow-key-execution.js.map",
|
||||
"backend/dist/services/traffic-flow-key-execution.d.ts",
|
||||
"backend/dist/services/traffic-flow-key-execution.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-map-exporter.js",
|
||||
"backend/dist/services/traffic-flow-map-exporter.js.map",
|
||||
"backend/dist/services/traffic-flow-map-exporter.d.ts",
|
||||
"backend/dist/services/traffic-flow-map-exporter.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-map-hops.js",
|
||||
"backend/dist/services/traffic-flow-map-hops.js.map",
|
||||
"backend/dist/services/traffic-flow-map-hops.d.ts",
|
||||
"backend/dist/services/traffic-flow-map-hops.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-overlay.js",
|
||||
"backend/dist/services/traffic-flow-overlay.js.map",
|
||||
"backend/dist/services/traffic-flow-overlay.d.ts",
|
||||
"backend/dist/services/traffic-flow-overlay.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-parse.js",
|
||||
"backend/dist/services/traffic-flow-parse.js.map",
|
||||
"backend/dist/services/traffic-flow-parse.d.ts",
|
||||
"backend/dist/services/traffic-flow-parse.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-planes.js",
|
||||
"backend/dist/services/traffic-flow-planes.js.map",
|
||||
"backend/dist/services/traffic-flow-planes.d.ts",
|
||||
"backend/dist/services/traffic-flow-planes.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-purge-execution.js",
|
||||
"backend/dist/services/traffic-flow-purge-execution.js.map",
|
||||
"backend/dist/services/traffic-flow-purge-execution.d.ts",
|
||||
"backend/dist/services/traffic-flow-purge-execution.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-ripe.js",
|
||||
"backend/dist/services/traffic-flow-ripe.js.map",
|
||||
"backend/dist/services/traffic-flow-ripe.d.ts",
|
||||
"backend/dist/services/traffic-flow-ripe.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-settings.js",
|
||||
"backend/dist/services/traffic-flow-settings.js.map",
|
||||
"backend/dist/services/traffic-flow-settings.d.ts",
|
||||
"backend/dist/services/traffic-flow-settings.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-topology.js",
|
||||
"backend/dist/services/traffic-flow-topology.js.map",
|
||||
"backend/dist/services/traffic-flow-topology.d.ts",
|
||||
"backend/dist/services/traffic-flow-topology.d.ts.map",
|
||||
"backend/dist/services/traffic-flow-worker-shutdown.js",
|
||||
"backend/dist/services/traffic-flow-worker-shutdown.js.map",
|
||||
"backend/dist/services/traffic-flow-worker-shutdown.d.ts",
|
||||
"backend/dist/services/traffic-flow-worker-shutdown.d.ts.map",
|
||||
"backend/dist/services/traffic-rate.js",
|
||||
"backend/dist/services/traffic-rate.js.map",
|
||||
"backend/dist/services/traffic-rate.d.ts",
|
||||
"backend/dist/services/traffic-rate.d.ts.map",
|
||||
"backend/dist/services/traffic-users.js",
|
||||
"backend/dist/services/traffic-users.js.map",
|
||||
"backend/dist/services/traffic-users.d.ts",
|
||||
"backend/dist/services/traffic-users.d.ts.map",
|
||||
"backend/dist/services/uptime-collector.js",
|
||||
"backend/dist/services/uptime-collector.js.map",
|
||||
"backend/dist/services/uptime-collector.d.ts",
|
||||
"backend/dist/services/uptime-collector.d.ts.map",
|
||||
"backend/dist/services/uptime-probe-observations.js",
|
||||
"backend/dist/services/uptime-probe-observations.js.map",
|
||||
"backend/dist/services/uptime-probe-observations.d.ts",
|
||||
"backend/dist/services/uptime-probe-observations.d.ts.map",
|
||||
"backend/dist/services/uptime-speed-service.js",
|
||||
"backend/dist/services/uptime-speed-service.js.map",
|
||||
"backend/dist/services/uptime-speed-service.d.ts",
|
||||
"backend/dist/services/uptime-speed-service.d.ts.map",
|
||||
"backend/dist/services/vxlan-live.js",
|
||||
"backend/dist/services/vxlan-live.js.map",
|
||||
"backend/dist/services/vxlan-live.d.ts",
|
||||
"backend/dist/services/vxlan-live.d.ts.map",
|
||||
"backend/dist/services/wg-keys.js",
|
||||
"backend/dist/services/wg-keys.js.map",
|
||||
"backend/dist/services/wg-keys.d.ts",
|
||||
"backend/dist/services/wg-keys.d.ts.map",
|
||||
"backend/dist/services/wireguard-config.js",
|
||||
"backend/dist/services/wireguard-config.js.map",
|
||||
"backend/dist/services/wireguard-config.d.ts",
|
||||
"backend/dist/services/wireguard-config.d.ts.map",
|
||||
"backend/dist/services/wireguard-delete.js",
|
||||
"backend/dist/services/wireguard-delete.js.map",
|
||||
"backend/dist/services/wireguard-delete.d.ts",
|
||||
"backend/dist/services/wireguard-delete.d.ts.map",
|
||||
"backend/dist/services/wireguard-import-apply.js",
|
||||
"backend/dist/services/wireguard-import-apply.js.map",
|
||||
"backend/dist/services/wireguard-import-apply.d.ts",
|
||||
"backend/dist/services/wireguard-import-apply.d.ts.map",
|
||||
"backend/dist/services/wireguard-import-revision.js",
|
||||
"backend/dist/services/wireguard-import-revision.js.map",
|
||||
"backend/dist/services/wireguard-import-revision.d.ts",
|
||||
"backend/dist/services/wireguard-import-revision.d.ts.map",
|
||||
"backend/dist/services/wireguard-import.js",
|
||||
"backend/dist/services/wireguard-import.js.map",
|
||||
"backend/dist/services/wireguard-import.d.ts",
|
||||
"backend/dist/services/wireguard-import.d.ts.map",
|
||||
"backend/dist/services/wireguard-live.js",
|
||||
"backend/dist/services/wireguard-live.js.map",
|
||||
"backend/dist/services/wireguard-live.d.ts",
|
||||
"backend/dist/services/wireguard-live.d.ts.map",
|
||||
"backend/dist/services/wireguard-observed-values.js",
|
||||
"backend/dist/services/wireguard-observed-values.js.map",
|
||||
"backend/dist/services/wireguard-observed-values.d.ts",
|
||||
"backend/dist/services/wireguard-observed-values.d.ts.map",
|
||||
"backend/dist/services/wireguard-ros.js",
|
||||
"backend/dist/services/wireguard-ros.js.map",
|
||||
"backend/dist/services/wireguard-ros.d.ts",
|
||||
"backend/dist/services/wireguard-ros.d.ts.map",
|
||||
"backend/dist/test/pg.js",
|
||||
"backend/dist/test/pg.js.map",
|
||||
"backend/dist/test/pg.d.ts",
|
||||
"backend/dist/test/pg.d.ts.map",
|
||||
"backend/dist/types/scheduler-run-snapshot.js",
|
||||
"backend/dist/types/scheduler-run-snapshot.js.map",
|
||||
"backend/dist/types/scheduler-run-snapshot.d.ts",
|
||||
"backend/dist/types/scheduler-run-snapshot.d.ts.map",
|
||||
"backend/dist/types/server.js",
|
||||
"backend/dist/types/server.js.map",
|
||||
"backend/dist/types/server.d.ts",
|
||||
"backend/dist/types/server.d.ts.map",
|
||||
"backend/dist/utils/abort-signals.js",
|
||||
"backend/dist/utils/abort-signals.js.map",
|
||||
"backend/dist/utils/abort-signals.d.ts",
|
||||
"backend/dist/utils/abort-signals.d.ts.map",
|
||||
"backend/dist/utils/ros-src-address.js",
|
||||
"backend/dist/utils/ros-src-address.js.map",
|
||||
"backend/dist/utils/ros-src-address.d.ts",
|
||||
"backend/dist/utils/ros-src-address.d.ts.map",
|
||||
"backend/dist/utils/server-id.js",
|
||||
"backend/dist/utils/server-id.js.map",
|
||||
"backend/dist/utils/server-id.d.ts",
|
||||
"backend/dist/utils/server-id.d.ts.map",
|
||||
"packages/contracts/dist/alerts.js",
|
||||
"packages/contracts/dist/alerts.js.map",
|
||||
"packages/contracts/dist/alerts.d.ts",
|
||||
"packages/contracts/dist/alerts.d.ts.map",
|
||||
"packages/contracts/dist/backups.js",
|
||||
"packages/contracts/dist/backups.js.map",
|
||||
"packages/contracts/dist/backups.d.ts",
|
||||
"packages/contracts/dist/backups.d.ts.map",
|
||||
"packages/contracts/dist/certificates.js",
|
||||
"packages/contracts/dist/certificates.js.map",
|
||||
"packages/contracts/dist/certificates.d.ts",
|
||||
"packages/contracts/dist/certificates.d.ts.map",
|
||||
"packages/contracts/dist/containers.js",
|
||||
"packages/contracts/dist/containers.js.map",
|
||||
"packages/contracts/dist/containers.d.ts",
|
||||
"packages/contracts/dist/containers.d.ts.map",
|
||||
"packages/contracts/dist/events.js",
|
||||
"packages/contracts/dist/events.js.map",
|
||||
"packages/contracts/dist/events.d.ts",
|
||||
"packages/contracts/dist/events.d.ts.map",
|
||||
"packages/contracts/dist/evobgp.js",
|
||||
"packages/contracts/dist/evobgp.js.map",
|
||||
"packages/contracts/dist/evobgp.d.ts",
|
||||
"packages/contracts/dist/evobgp.d.ts.map",
|
||||
"packages/contracts/dist/geoip.js",
|
||||
"packages/contracts/dist/geoip.js.map",
|
||||
"packages/contracts/dist/geoip.d.ts",
|
||||
"packages/contracts/dist/geoip.d.ts.map",
|
||||
"packages/contracts/dist/index.js",
|
||||
"packages/contracts/dist/index.js.map",
|
||||
"packages/contracts/dist/index.d.ts",
|
||||
"packages/contracts/dist/index.d.ts.map",
|
||||
"packages/contracts/dist/ipsec.js",
|
||||
"packages/contracts/dist/ipsec.js.map",
|
||||
"packages/contracts/dist/ipsec.d.ts",
|
||||
"packages/contracts/dist/ipsec.d.ts.map",
|
||||
"packages/contracts/dist/ospf-optimizer.js",
|
||||
"packages/contracts/dist/ospf-optimizer.js.map",
|
||||
"packages/contracts/dist/ospf-optimizer.d.ts",
|
||||
"packages/contracts/dist/ospf-optimizer.d.ts.map",
|
||||
"packages/contracts/dist/servers.js",
|
||||
"packages/contracts/dist/servers.js.map",
|
||||
"packages/contracts/dist/servers.d.ts",
|
||||
"packages/contracts/dist/servers.d.ts.map",
|
||||
"packages/contracts/dist/statistics.js",
|
||||
"packages/contracts/dist/statistics.js.map",
|
||||
"packages/contracts/dist/statistics.d.ts",
|
||||
"packages/contracts/dist/statistics.d.ts.map",
|
||||
"packages/contracts/dist/traffic-flow.js",
|
||||
"packages/contracts/dist/traffic-flow.js.map",
|
||||
"packages/contracts/dist/traffic-flow.d.ts",
|
||||
"packages/contracts/dist/traffic-flow.d.ts.map",
|
||||
"packages/contracts/dist/uptime-probes.js",
|
||||
"packages/contracts/dist/uptime-probes.js.map",
|
||||
"packages/contracts/dist/uptime-probes.d.ts",
|
||||
"packages/contracts/dist/uptime-probes.d.ts.map",
|
||||
"packages/contracts/dist/uptime-speed.js",
|
||||
"packages/contracts/dist/uptime-speed.js.map",
|
||||
"packages/contracts/dist/uptime-speed.d.ts",
|
||||
"packages/contracts/dist/uptime-speed.d.ts.map",
|
||||
"packages/contracts/dist/users.js",
|
||||
"packages/contracts/dist/users.js.map",
|
||||
"packages/contracts/dist/users.d.ts",
|
||||
"packages/contracts/dist/users.d.ts.map",
|
||||
"packages/contracts/dist/wireguard.js",
|
||||
"packages/contracts/dist/wireguard.js.map",
|
||||
"packages/contracts/dist/wireguard.d.ts",
|
||||
"packages/contracts/dist/wireguard.d.ts.map",
|
||||
"backend/dist/services/alert-engine/bgp-signals.js",
|
||||
"backend/dist/services/alert-engine/bgp-signals.js.map",
|
||||
"backend/dist/services/alert-engine/bgp-signals.d.ts",
|
||||
"backend/dist/services/alert-engine/bgp-signals.d.ts.map"
|
||||
],
|
||||
"missing": [],
|
||||
"different": []
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"runtime": {
|
||||
"backend": "ux-bgp163",
|
||||
"frontend": "ux-bfd158"
|
||||
},
|
||||
"checks": [
|
||||
{
|
||||
"path": "/api/bgp/catalog",
|
||||
"status": 200
|
||||
},
|
||||
{
|
||||
"path": "/api/servers/1/bgp/sessions",
|
||||
"status": 200
|
||||
},
|
||||
{
|
||||
"path": "/api/servers/2/bgp/sessions",
|
||||
"status": 200
|
||||
}
|
||||
],
|
||||
"cases": [
|
||||
{
|
||||
"width": 1440,
|
||||
"http200": true,
|
||||
"catalog200": true,
|
||||
"noOverflow": true,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"width": 320,
|
||||
"http200": true,
|
||||
"catalog200": true,
|
||||
"noOverflow": true,
|
||||
"errors": []
|
||||
}
|
||||
],
|
||||
"bounds": [
|
||||
"Read-only production catalog/selected API/UI after own native cleanup; empty catalog is not positive native inactive proof",
|
||||
"Inactive native payloads tested by compiled replay of160 separately; no new RouterOS mutations or Telegram message"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.163",
|
||||
"nativeSourceBlock": 160,
|
||||
"sha256": "bfd1290bb97669b0e201e949c296bd1d2427f9449b8d082619eca6b2a7c40f1a",
|
||||
"snapshots": 46,
|
||||
"ambiguousSnapshots": 46,
|
||||
"problemChecks": 46,
|
||||
"recoveryChecks": 46,
|
||||
"passed": true,
|
||||
"bounds": [
|
||||
"Captured real two-device native rows replayed with their legacy names; no new RouterOS changes",
|
||||
"Ambiguous same-run keys suppress events; stable-ID target migration not implemented",
|
||||
"No SQL stability/outbox/delivery claim"
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,387 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.162",
|
||||
"name": "mm-bgp162-1791774990658",
|
||||
"devices": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"catalog": {
|
||||
"id": "*280000C",
|
||||
"serverId": 1,
|
||||
"serverName": "CHR",
|
||||
"serverSite": "",
|
||||
"serverCountry": "",
|
||||
"name": "mm-bgp162-1791774990658-1",
|
||||
"peerIp": "fd00:162:1::2",
|
||||
"remoteAs": 4200000163,
|
||||
"localAs": 4200000162,
|
||||
"localId": "198.18.255.1",
|
||||
"remoteId": "198.18.255.2",
|
||||
"state": "Established",
|
||||
"type": "eBGP",
|
||||
"uptime": "250ms",
|
||||
"holdTime": 180,
|
||||
"keepalive": 60,
|
||||
"prefixesRx": 1,
|
||||
"prefixesTx": null,
|
||||
"inputMessages": 2,
|
||||
"outputMessages": 2,
|
||||
"capabilities": [
|
||||
"MP-BGP",
|
||||
"Route Refresh",
|
||||
"Extended Next-Hop",
|
||||
"Graceful Restart",
|
||||
"4-byte-AS"
|
||||
],
|
||||
"lastError": null,
|
||||
"afi": "ipv6"
|
||||
},
|
||||
"route": {
|
||||
".id": "*2014F000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "fd00:162:ff::2/128",
|
||||
"dynamic": "true",
|
||||
"gateway": "fd00:162:1::2",
|
||||
"immediate-gw": "fd00:162:1::2%mm-bgp162-1791774990658-g",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"catalog": {
|
||||
"id": "*280000A",
|
||||
"serverId": 2,
|
||||
"serverName": "CHR",
|
||||
"serverSite": "",
|
||||
"serverCountry": "",
|
||||
"name": "mm-bgp162-1791774990658-1",
|
||||
"peerIp": "fd00:162:1::1",
|
||||
"remoteAs": 4200000162,
|
||||
"localAs": 4200000163,
|
||||
"localId": "198.18.255.2",
|
||||
"remoteId": "198.18.255.1",
|
||||
"state": "Established",
|
||||
"type": "eBGP",
|
||||
"uptime": "100ms",
|
||||
"holdTime": 180,
|
||||
"keepalive": 60,
|
||||
"prefixesRx": 1,
|
||||
"prefixesTx": null,
|
||||
"inputMessages": 2,
|
||||
"outputMessages": 2,
|
||||
"capabilities": [
|
||||
"MP-BGP",
|
||||
"Route Refresh",
|
||||
"Extended Next-Hop",
|
||||
"Graceful Restart",
|
||||
"4-byte-AS"
|
||||
],
|
||||
"lastError": null,
|
||||
"afi": "ipv6"
|
||||
},
|
||||
"route": {
|
||||
".id": "*2014F000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "fd00:162:ff::1/128",
|
||||
"dynamic": "true",
|
||||
"gateway": "fd00:162:1::1",
|
||||
"immediate-gw": "fd00:162:1::1%mm-bgp162-1791774990658-g",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"/routing/bgp/connection": true,
|
||||
"/routing/bgp/instance": true,
|
||||
"/routing/filter/rule": true,
|
||||
"/ipv6/firewall/address-list": true,
|
||||
"/interface/gre": true,
|
||||
"/interface/bridge": true,
|
||||
"/ipv6/address": true,
|
||||
"/ipv6/route": true,
|
||||
"/ip/address": true,
|
||||
"/ip/route": true,
|
||||
"/ipv6/firewall/filter": true
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"/routing/bgp/connection": true,
|
||||
"/routing/bgp/instance": true,
|
||||
"/routing/filter/rule": true,
|
||||
"/ipv6/firewall/address-list": true,
|
||||
"/interface/gre": true,
|
||||
"/interface/bridge": true,
|
||||
"/ipv6/address": true,
|
||||
"/ipv6/route": true,
|
||||
"/ip/address": true,
|
||||
"/ip/route": true,
|
||||
"/ipv6/firewall/filter": true
|
||||
}
|
||||
],
|
||||
"initial": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"sessions": [
|
||||
{
|
||||
".id": "*280000C",
|
||||
"ebgp": "",
|
||||
"established": "true",
|
||||
"hold-time": "3m",
|
||||
"input.filter": "mm-bgp162-1791774990658-in",
|
||||
"input.procid": "20",
|
||||
"instance": "mm-bgp162-1791774990658",
|
||||
"keepalive-time": "1m",
|
||||
"last-started": "2026-10-12 06:16:41",
|
||||
"local.address": "fd00:162:1::1",
|
||||
"local.afi": "ipv6",
|
||||
"local.as": "4200000162",
|
||||
"local.bytes": "98",
|
||||
"local.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"local.cluster-id": "198.18.255.1",
|
||||
"local.eor": "",
|
||||
"local.id": "198.18.255.1",
|
||||
"local.messages": "2",
|
||||
"name": "mm-bgp162-1791774990658-1",
|
||||
"output.filter-chain": "mm-bgp162-1791774990658-out",
|
||||
"output.network": "mm-bgp162-1791774990658",
|
||||
"output.procid": "20",
|
||||
"prefix-count": "0",
|
||||
"remote.address": "fd00:162:1::2",
|
||||
"remote.afi": "ipv6",
|
||||
"remote.as": "4200000163",
|
||||
"remote.bytes": "98",
|
||||
"remote.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"remote.eor": "",
|
||||
"remote.id": "198.18.255.2",
|
||||
"remote.messages": "2",
|
||||
"uptime": "250ms"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
".id": "*2014F000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "fd00:162:ff::2/128",
|
||||
"dynamic": "true",
|
||||
"gateway": "fd00:162:1::2",
|
||||
"immediate-gw": "fd00:162:1::2%mm-bgp162-1791774990658-g",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"sessions": [
|
||||
{
|
||||
".id": "*280000A",
|
||||
"ebgp": "",
|
||||
"established": "true",
|
||||
"hold-time": "3m",
|
||||
"input.filter": "mm-bgp162-1791774990658-in",
|
||||
"input.procid": "20",
|
||||
"instance": "mm-bgp162-1791774990658",
|
||||
"keepalive-time": "1m",
|
||||
"last-started": "2026-10-12 05:16:42",
|
||||
"local.address": "fd00:162:1::2",
|
||||
"local.afi": "ipv6",
|
||||
"local.as": "4200000163",
|
||||
"local.bytes": "98",
|
||||
"local.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"local.cluster-id": "198.18.255.2",
|
||||
"local.eor": "",
|
||||
"local.id": "198.18.255.2",
|
||||
"local.messages": "2",
|
||||
"name": "mm-bgp162-1791774990658-1",
|
||||
"output.filter-chain": "mm-bgp162-1791774990658-out",
|
||||
"output.network": "mm-bgp162-1791774990658",
|
||||
"output.procid": "20",
|
||||
"prefix-count": "0",
|
||||
"remote.address": "fd00:162:1::1",
|
||||
"remote.afi": "ipv6",
|
||||
"remote.as": "4200000162",
|
||||
"remote.bytes": "98",
|
||||
"remote.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"remote.eor": "",
|
||||
"remote.id": "198.18.255.1",
|
||||
"remote.messages": "2",
|
||||
"uptime": "100ms"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
".id": "*2014F000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "fd00:162:ff::1/128",
|
||||
"dynamic": "true",
|
||||
"gateway": "fd00:162:1::1",
|
||||
"immediate-gw": "fd00:162:1::1%mm-bgp162-1791774990658-g",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"pings": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"sent": 3,
|
||||
"received": 3
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"sent": 3,
|
||||
"received": 3
|
||||
}
|
||||
],
|
||||
"withdrawal": {
|
||||
"elapsedMs": 135,
|
||||
"ownIpv6RouteWithdrawn": true
|
||||
},
|
||||
"recovery": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"sessions": [
|
||||
{
|
||||
".id": "*280000D",
|
||||
"ebgp": "",
|
||||
"established": "true",
|
||||
"hold-time": "3m",
|
||||
"input.filter": "mm-bgp162-1791774990658-in",
|
||||
"input.procid": "20",
|
||||
"instance": "mm-bgp162-1791774990658",
|
||||
"keepalive-time": "1m",
|
||||
"last-started": "2026-10-12 06:17:16",
|
||||
"local.address": "fd00:162:1::1",
|
||||
"local.afi": "ipv6",
|
||||
"local.as": "4200000162",
|
||||
"local.bytes": "98",
|
||||
"local.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"local.cluster-id": "198.18.255.1",
|
||||
"local.eor": "",
|
||||
"local.id": "198.18.255.1",
|
||||
"local.messages": "2",
|
||||
"name": "mm-bgp162-1791774990658-1",
|
||||
"output.filter-chain": "mm-bgp162-1791774990658-out",
|
||||
"output.network": "mm-bgp162-1791774990658",
|
||||
"output.procid": "20",
|
||||
"prefix-count": "1",
|
||||
"remote.address": "fd00:162:1::2",
|
||||
"remote.afi": "ipv6",
|
||||
"remote.as": "4200000163",
|
||||
"remote.bytes": "98",
|
||||
"remote.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"remote.eor": "",
|
||||
"remote.id": "198.18.255.2",
|
||||
"remote.messages": "2",
|
||||
"uptime": "380ms"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
".id": "*2014F000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "fd00:162:ff::2/128",
|
||||
"dynamic": "true",
|
||||
"gateway": "fd00:162:1::2",
|
||||
"immediate-gw": "fd00:162:1::2%mm-bgp162-1791774990658-g",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"sessions": [
|
||||
{
|
||||
".id": "*280000A",
|
||||
"ebgp": "",
|
||||
"established": "true",
|
||||
"hold-time": "3m",
|
||||
"input.filter": "mm-bgp162-1791774990658-in",
|
||||
"input.procid": "20",
|
||||
"instance": "mm-bgp162-1791774990658",
|
||||
"keepalive-time": "1m",
|
||||
"last-started": "2026-10-12 05:17:16",
|
||||
"last-stopped": "2026-10-12 05:17:16",
|
||||
"local.address": "fd00:162:1::2",
|
||||
"local.afi": "ipv6",
|
||||
"local.as": "4200000163",
|
||||
"local.bytes": "98",
|
||||
"local.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"local.cluster-id": "198.18.255.2",
|
||||
"local.eor": "",
|
||||
"local.id": "198.18.255.2",
|
||||
"local.messages": "2",
|
||||
"name": "mm-bgp162-1791774990658-1",
|
||||
"output.filter-chain": "mm-bgp162-1791774990658-out",
|
||||
"output.network": "mm-bgp162-1791774990658",
|
||||
"output.procid": "20",
|
||||
"prefix-count": "1",
|
||||
"remote.address": "fd00:162:1::1",
|
||||
"remote.afi": "ipv6",
|
||||
"remote.as": "4200000162",
|
||||
"remote.bytes": "98",
|
||||
"remote.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"remote.eor": "",
|
||||
"remote.id": "198.18.255.1",
|
||||
"remote.messages": "2",
|
||||
"uptime": "280ms"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
".id": "*2014F000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "fd00:162:ff::1/128",
|
||||
"dynamic": "true",
|
||||
"gateway": "fd00:162:1::1",
|
||||
"immediate-gw": "fd00:162:1::1%mm-bgp162-1791774990658-g",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"recoveryPings": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"sent": 3,
|
||||
"received": 3
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"sent": 3,
|
||||
"received": 3
|
||||
}
|
||||
],
|
||||
"passed": true
|
||||
}
|
||||
@@ -0,0 +1,718 @@
|
||||
{
|
||||
"date": "2026-10-10",
|
||||
"name": "mm-bgp104-1791577657130",
|
||||
"devices": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"catalog": {
|
||||
"id": "*2800007",
|
||||
"serverId": 1,
|
||||
"serverName": "CHR",
|
||||
"serverSite": "",
|
||||
"serverCountry": "",
|
||||
"name": "mm-bgp104-1791577657130-1",
|
||||
"peerIp": "198.18.104.2",
|
||||
"remoteAs": 65105,
|
||||
"localAs": 65104,
|
||||
"localId": "198.18.204.1",
|
||||
"remoteId": "198.18.204.2",
|
||||
"state": "Established",
|
||||
"type": "eBGP",
|
||||
"uptime": "440ms",
|
||||
"holdTime": 3,
|
||||
"keepalive": 1,
|
||||
"prefixesRx": 1,
|
||||
"prefixesTx": null,
|
||||
"inputMessages": 2,
|
||||
"outputMessages": 2,
|
||||
"capabilities": [
|
||||
"MP-BGP",
|
||||
"Route Refresh",
|
||||
"Extended Next-Hop",
|
||||
"Graceful Restart",
|
||||
"4-byte-AS"
|
||||
],
|
||||
"lastError": null,
|
||||
"afi": "ip"
|
||||
},
|
||||
"nativeRoute": {
|
||||
".id": "*2014D000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "198.18.204.2/32",
|
||||
"dynamic": "true",
|
||||
"gateway": "198.18.104.2",
|
||||
"immediate-gw": "198.18.104.2%mm-bgp104-1791577657130",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
},
|
||||
"pingReceived": 3,
|
||||
"pingAttempts": [
|
||||
3
|
||||
],
|
||||
"exactOwnPrefixOnly": true
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"catalog": {
|
||||
"id": "*2800006",
|
||||
"serverId": 2,
|
||||
"serverName": "CHR",
|
||||
"serverSite": "",
|
||||
"serverCountry": "",
|
||||
"name": "mm-bgp104-1791577657130-1",
|
||||
"peerIp": "198.18.104.1",
|
||||
"remoteAs": 65104,
|
||||
"localAs": 65105,
|
||||
"localId": "198.18.204.2",
|
||||
"remoteId": "198.18.204.1",
|
||||
"state": "Established",
|
||||
"type": "eBGP",
|
||||
"uptime": "320ms",
|
||||
"holdTime": 3,
|
||||
"keepalive": 1,
|
||||
"prefixesRx": 1,
|
||||
"prefixesTx": null,
|
||||
"inputMessages": 2,
|
||||
"outputMessages": 2,
|
||||
"capabilities": [
|
||||
"MP-BGP",
|
||||
"Route Refresh",
|
||||
"Extended Next-Hop",
|
||||
"Graceful Restart",
|
||||
"4-byte-AS"
|
||||
],
|
||||
"lastError": null,
|
||||
"afi": "ip"
|
||||
},
|
||||
"nativeRoute": {
|
||||
".id": "*2014D000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "198.18.204.1/32",
|
||||
"dynamic": "true",
|
||||
"gateway": "198.18.104.1",
|
||||
"immediate-gw": "198.18.104.1%mm-bgp104-1791577657130",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
},
|
||||
"pingReceived": 3,
|
||||
"pingAttempts": [
|
||||
3
|
||||
],
|
||||
"exactOwnPrefixOnly": true
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"/ip/firewall/filter": true,
|
||||
"/routing/bfd/configuration": true,
|
||||
"/routing/bgp/connection": true,
|
||||
"/routing/bgp/instance": true,
|
||||
"/routing/filter/rule": true,
|
||||
"/ip/firewall/address-list": true,
|
||||
"/interface/gre": true,
|
||||
"/interface/bridge": true,
|
||||
"/ip/address": true,
|
||||
"/ip/route": true
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"/ip/firewall/filter": true,
|
||||
"/routing/bfd/configuration": true,
|
||||
"/routing/bgp/connection": true,
|
||||
"/routing/bgp/instance": true,
|
||||
"/routing/filter/rule": true,
|
||||
"/ip/firewall/address-list": true,
|
||||
"/interface/gre": true,
|
||||
"/interface/bridge": true,
|
||||
"/ip/address": true,
|
||||
"/ip/route": true
|
||||
}
|
||||
],
|
||||
"initial": [
|
||||
{
|
||||
"sessions": [
|
||||
{
|
||||
".id": "*2800007",
|
||||
"ebgp": "",
|
||||
"established": "true",
|
||||
"hold-time": "3s",
|
||||
"input.filter": "mm-bgp104-1791577657130-in",
|
||||
"input.procid": "20",
|
||||
"instance": "mm-bgp104-1791577657130",
|
||||
"keepalive-time": "1s",
|
||||
"last-started": "2026-10-09 23:27:41",
|
||||
"local.address": "198.18.104.1",
|
||||
"local.afi": "ip",
|
||||
"local.as": "65104",
|
||||
"local.bytes": "68",
|
||||
"local.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"local.cluster-id": "198.18.204.1",
|
||||
"local.eor": "",
|
||||
"local.id": "198.18.204.1",
|
||||
"local.messages": "2",
|
||||
"name": "mm-bgp104-1791577657130-1",
|
||||
"output.filter-chain": "mm-bgp104-1791577657130-out",
|
||||
"output.network": "mm-bgp104-1791577657130",
|
||||
"output.procid": "20",
|
||||
"prefix-count": "1",
|
||||
"remote.address": "198.18.104.2",
|
||||
"remote.afi": "ip",
|
||||
"remote.as": "65105",
|
||||
"remote.bytes": "68",
|
||||
"remote.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"remote.eor": "",
|
||||
"remote.hold-time": "3s",
|
||||
"remote.id": "198.18.204.2",
|
||||
"remote.messages": "2",
|
||||
"uptime": "440ms"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
".id": "*2014D000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "198.18.204.2/32",
|
||||
"dynamic": "true",
|
||||
"gateway": "198.18.104.2",
|
||||
"immediate-gw": "198.18.104.2%mm-bgp104-1791577657130",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sessions": [
|
||||
{
|
||||
".id": "*2800006",
|
||||
"ebgp": "",
|
||||
"established": "true",
|
||||
"hold-time": "3s",
|
||||
"input.filter": "mm-bgp104-1791577657130-in",
|
||||
"input.procid": "20",
|
||||
"instance": "mm-bgp104-1791577657130",
|
||||
"keepalive-time": "1s",
|
||||
"last-started": "2026-10-09 22:27:41",
|
||||
"local.address": "198.18.104.2",
|
||||
"local.afi": "ip",
|
||||
"local.as": "65105",
|
||||
"local.bytes": "68",
|
||||
"local.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"local.cluster-id": "198.18.204.2",
|
||||
"local.eor": "",
|
||||
"local.id": "198.18.204.2",
|
||||
"local.messages": "2",
|
||||
"name": "mm-bgp104-1791577657130-1",
|
||||
"output.filter-chain": "mm-bgp104-1791577657130-out",
|
||||
"output.network": "mm-bgp104-1791577657130",
|
||||
"output.procid": "20",
|
||||
"prefix-count": "0",
|
||||
"remote.address": "198.18.104.1",
|
||||
"remote.afi": "ip",
|
||||
"remote.as": "65104",
|
||||
"remote.bytes": "68",
|
||||
"remote.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"remote.eor": "",
|
||||
"remote.hold-time": "3s",
|
||||
"remote.id": "198.18.204.1",
|
||||
"remote.messages": "2",
|
||||
"uptime": "320ms"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
".id": "*2014D000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "198.18.204.1/32",
|
||||
"dynamic": "true",
|
||||
"gateway": "198.18.104.1",
|
||||
"immediate-gw": "198.18.104.1%mm-bgp104-1791577657130",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"nativeConnections": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"useBfd": "false",
|
||||
"hold": "3s",
|
||||
"keepalive": "1s"
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"useBfd": "false",
|
||||
"hold": "3s",
|
||||
"keepalive": "1s"
|
||||
}
|
||||
],
|
||||
"loss": {
|
||||
"scopedTcpOnly": true,
|
||||
"interfaceDisabled": false,
|
||||
"connectionDisabled": false,
|
||||
"acknowledgedMs": 41.25659199999973,
|
||||
"firstNotEstablished": 2667.269095999999,
|
||||
"firstNoActiveRoute": 3690.540894999999,
|
||||
"samples": [
|
||||
{
|
||||
"beganMs": 41.262173000000075,
|
||||
"endedMs": 267.55814199999986,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 368.28421699999944,
|
||||
"endedMs": 436.9728669999995,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 537.3723649999993,
|
||||
"endedMs": 606.6827239999993,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 707.1440159999993,
|
||||
"endedMs": 777.1101789999993,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 877.5098009999992,
|
||||
"endedMs": 947.3788399999994,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 1047.8871149999995,
|
||||
"endedMs": 1124.0534739999994,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 1224.647223,
|
||||
"endedMs": 1297.0276879999992,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 1397.4342539999989,
|
||||
"endedMs": 1467.2807449999991,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 1567.6731119999995,
|
||||
"endedMs": 1639.8602739999997,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 1740.2848239999994,
|
||||
"endedMs": 1809.9277119999997,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 1910.3524179999995,
|
||||
"endedMs": 1979.1934699999993,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 2079.598013,
|
||||
"endedMs": 2149.2285079999992,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 2249.6923909999996,
|
||||
"endedMs": 2327.2061430000003,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 2427.641654,
|
||||
"endedMs": 2496.8365949999998,
|
||||
"established": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 2597.2220740000002,
|
||||
"endedMs": 2667.269095999999,
|
||||
"established": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 2767.72232,
|
||||
"endedMs": 2836.9666019999995,
|
||||
"established": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 2937.351680999999,
|
||||
"endedMs": 3007.000541999999,
|
||||
"established": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 3107.417828999999,
|
||||
"endedMs": 3179.8466070000004,
|
||||
"established": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 3280.268379,
|
||||
"endedMs": 3348.9262389999994,
|
||||
"established": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 3449.27934,
|
||||
"endedMs": 3518.761459999999,
|
||||
"established": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"activeRoutes": [
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"beganMs": 3620.6175749999993,
|
||||
"endedMs": 3690.540894999999,
|
||||
"established": [
|
||||
false,
|
||||
false
|
||||
],
|
||||
"activeRoutes": [
|
||||
false,
|
||||
false
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"linkDuringLoss": [
|
||||
{
|
||||
"serverId": 1,
|
||||
"received": 3
|
||||
},
|
||||
{
|
||||
"serverId": 2,
|
||||
"received": 3
|
||||
}
|
||||
],
|
||||
"recovered": [
|
||||
{
|
||||
"sessions": [
|
||||
{
|
||||
".id": "*2800007",
|
||||
"ebgp": "",
|
||||
"established": "true",
|
||||
"hold-time": "3s",
|
||||
"input.filter": "mm-bgp104-1791577657130-in",
|
||||
"input.procid": "20",
|
||||
"instance": "mm-bgp104-1791577657130",
|
||||
"keepalive-time": "1s",
|
||||
"last-started": "2026-10-09 23:27:50",
|
||||
"last-stopped": "2026-10-09 23:27:45",
|
||||
"local.address": "198.18.104.1",
|
||||
"local.afi": "ip",
|
||||
"local.as": "65104",
|
||||
"local.bytes": "68",
|
||||
"local.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"local.cluster-id": "198.18.204.1",
|
||||
"local.eor": "",
|
||||
"local.id": "198.18.204.1",
|
||||
"local.messages": "2",
|
||||
"name": "mm-bgp104-1791577657130-1",
|
||||
"output.filter-chain": "mm-bgp104-1791577657130-out",
|
||||
"output.last-notification": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0015030400",
|
||||
"output.network": "mm-bgp104-1791577657130",
|
||||
"output.procid": "20",
|
||||
"prefix-count": "1",
|
||||
"remote.address": "198.18.104.2",
|
||||
"remote.afi": "ip",
|
||||
"remote.as": "65105",
|
||||
"remote.bytes": "68",
|
||||
"remote.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"remote.eor": "",
|
||||
"remote.hold-time": "3s",
|
||||
"remote.id": "198.18.204.2",
|
||||
"remote.messages": "2",
|
||||
"uptime": "40ms"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
".id": "*2014D000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "198.18.204.2/32",
|
||||
"dynamic": "true",
|
||||
"gateway": "198.18.104.2",
|
||||
"immediate-gw": "198.18.104.2%mm-bgp104-1791577657130",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sessions": [
|
||||
{
|
||||
".id": "*2800006",
|
||||
"ebgp": "",
|
||||
"established": "true",
|
||||
"hold-time": "3s",
|
||||
"input.filter": "mm-bgp104-1791577657130-in",
|
||||
"input.procid": "20",
|
||||
"instance": "mm-bgp104-1791577657130",
|
||||
"keepalive-time": "1s",
|
||||
"last-started": "2026-10-09 22:27:50",
|
||||
"last-stopped": "2026-10-09 22:27:46",
|
||||
"local.address": "198.18.104.2",
|
||||
"local.afi": "ip",
|
||||
"local.as": "65105",
|
||||
"local.bytes": "68",
|
||||
"local.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"local.cluster-id": "198.18.204.2",
|
||||
"local.eor": "",
|
||||
"local.id": "198.18.204.2",
|
||||
"local.messages": "2",
|
||||
"name": "mm-bgp104-1791577657130-1",
|
||||
"output.filter-chain": "mm-bgp104-1791577657130-out",
|
||||
"output.last-notification": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0015030400",
|
||||
"output.network": "mm-bgp104-1791577657130",
|
||||
"output.procid": "20",
|
||||
"prefix-count": "1",
|
||||
"remote.address": "198.18.104.1",
|
||||
"remote.afi": "ip",
|
||||
"remote.as": "65104",
|
||||
"remote.bytes": "68",
|
||||
"remote.capabilities": "mp,rr,enhe,gr,as4",
|
||||
"remote.eor": "",
|
||||
"remote.hold-time": "3s",
|
||||
"remote.id": "198.18.204.1",
|
||||
"remote.messages": "2",
|
||||
"uptime": "140ms"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
".id": "*2014D000",
|
||||
"active": "true",
|
||||
"bgp": "true",
|
||||
"distance": "20",
|
||||
"dst-address": "198.18.204.1/32",
|
||||
"dynamic": "true",
|
||||
"gateway": "198.18.104.1",
|
||||
"immediate-gw": "198.18.104.1%mm-bgp104-1791577657130",
|
||||
"inactive": "false",
|
||||
"routing-table": "main",
|
||||
"scope": "40",
|
||||
"target-scope": "10"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"recoveryCatalog": [
|
||||
{
|
||||
"id": "*2800007",
|
||||
"serverId": 1,
|
||||
"serverName": "CHR",
|
||||
"serverSite": "",
|
||||
"serverCountry": "",
|
||||
"name": "mm-bgp104-1791577657130-1",
|
||||
"peerIp": "198.18.104.2",
|
||||
"remoteAs": 65105,
|
||||
"localAs": 65104,
|
||||
"localId": "198.18.204.1",
|
||||
"remoteId": "198.18.204.2",
|
||||
"state": "Established",
|
||||
"type": "eBGP",
|
||||
"uptime": "40ms",
|
||||
"holdTime": 3,
|
||||
"keepalive": 1,
|
||||
"prefixesRx": 1,
|
||||
"prefixesTx": null,
|
||||
"inputMessages": 2,
|
||||
"outputMessages": 2,
|
||||
"capabilities": [
|
||||
"MP-BGP",
|
||||
"Route Refresh",
|
||||
"Extended Next-Hop",
|
||||
"Graceful Restart",
|
||||
"4-byte-AS"
|
||||
],
|
||||
"lastError": null,
|
||||
"afi": "ip"
|
||||
},
|
||||
{
|
||||
"id": "*2800006",
|
||||
"serverId": 2,
|
||||
"serverName": "CHR",
|
||||
"serverSite": "",
|
||||
"serverCountry": "",
|
||||
"name": "mm-bgp104-1791577657130-1",
|
||||
"peerIp": "198.18.104.1",
|
||||
"remoteAs": 65104,
|
||||
"localAs": 65105,
|
||||
"localId": "198.18.204.2",
|
||||
"remoteId": "198.18.204.1",
|
||||
"state": "Established",
|
||||
"type": "eBGP",
|
||||
"uptime": "140ms",
|
||||
"holdTime": 3,
|
||||
"keepalive": 1,
|
||||
"prefixesRx": 1,
|
||||
"prefixesTx": null,
|
||||
"inputMessages": 2,
|
||||
"outputMessages": 2,
|
||||
"capabilities": [
|
||||
"MP-BGP",
|
||||
"Route Refresh",
|
||||
"Extended Next-Hop",
|
||||
"Graceful Restart",
|
||||
"4-byte-AS"
|
||||
],
|
||||
"lastError": null,
|
||||
"afi": "ip"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"date": "2026-10-12",
|
||||
"block": "12.5.162",
|
||||
"runtime": {
|
||||
"backend": "ux-bgp161b",
|
||||
"frontend": "ux-bfd158"
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"width": 1440,
|
||||
"rows": 2,
|
||||
"ipv6PeersRendered": true,
|
||||
"establishedRendered": true,
|
||||
"fourByteAsnRendered": true,
|
||||
"noOverflow": true,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"width": 320,
|
||||
"rows": 2,
|
||||
"ipv6PeersRendered": true,
|
||||
"establishedRendered": true,
|
||||
"fourByteAsnRendered": true,
|
||||
"noOverflow": true,
|
||||
"errors": []
|
||||
}
|
||||
],
|
||||
"bounds": [
|
||||
"Readonly production API with real two CHR IPv6 peers over own GRE/IPv4 outer; no response substitution",
|
||||
"Native IPv6 NLRI/Ping/withdrawal/cleanup are checked separately; no public IPv6 WAN, independent WAN, arbitrary external peer, scale or throughput claim"
|
||||
]
|
||||
}
|
||||
Loaded 100 of 3835 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user