Files
MikrotikManager/docs/ux-ui-external-acceptance.md
T

108 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# UX/UI: протокол внешней приёмки 12.5
Статус на2026-10-07: основнойbackend4c12c55/frontend673e5ba развёрнуты,healthy иrealbrowser smoke passed. PG-1/2/5 иPG-3/4 принятывописанныхконтрольныхграницах; integratedPG-6 принятдляодногоisolatedbackend в12.5.17 (HTTP/UDP/scheduler/backgroundSQL/restore/restart),безкоординациидругихпроцессов. PG-7 ранееHTTP-RBAC,Portal/browserrestore ещёнеприняты. NativeTCPspeed ипервыйотказподключенияпройдены;остальнойROS/Q/интеграции открыты. [Паспорт](ux-ui-test-server.md),[журнал](ux-ui-progress.md).
## Паспорт стенда
Перед внешним запуском зафиксировать отдельные PostgreSQL и RouterOS тестовые устройства, версии server/client PostgreSQL и RouterOS, HEAD backend/frontend, роли пользователей, число экземпляров backend/планировщика/отправителей и способ их остановки. Для Telegram использовать тестовый чат, для остальных интеграций — тестовые endpoints и учётные записи. Зафиксировать ожидаемые изменения и способ восстановления стенда.
Пароли, JWT, REUI_LICENSE_KEY, DATABASE_URL, дампы БД и исходные приватные журналы хранить вне Git. В отчёт включать очищенные ответы, ID тестовых объектов, UTC-время, request ID, HTTP-код и проверенные изменения. Контрольный снимок данных должен позволять сравнить состояние до/после; успешный toast без независимой проверки не завершает сценарий.
## PostgreSQL и восстановление
| ID | Сценарий | Проверяемый результат | Доказательство |
| --- | --- | --- | --- |
| PG-1 | Штатный bootstrap чистой тестовой БД и повторный старт | Миграции 0008/0009 отражены в schema_migrations; constraint допускает pending/processing/unknown/sent/failed; resolution_version неотрицательна. Повторный старт сохраняет данные | Версии, очищенный журнал миграций, контрольные строки и ограничения |
| PG-2 | GET /api/system/database/backup с mm:settings:admin | Архив сформирован pg_dump, открывается совместимым pg_restore; контрольные бизнес-записи/схема присутствуют | Размер/SHA256 архива, список объектов, receipt и предупреждения |
| PG-3 | POST /api/system/database/restore из доверенного тестового архива | Данные тестовой БД соответствуют архиву; последующая запись получает корректный новый ID. UI различает завершение restore и ошибки перезапуска listener/scheduler/event | Сравнение схемы/контрольных записей, проверка последовательностей, HTTP/UI |
| PG-4 | Ошибка внутри реального pg_restore | Восстановление не объявляется успешным. Проверить rollback по контрольным бизнес-строкам и схеме, отдельно проверить последовательности | Ошибка процесса, HTTP/UI и независимые запросы до/после |
| PG-5 | Два конкурентных backup/restore запроса | Advisory lock исключает конкурирующее выполнение; второй запрос сообщает конфликт | Два request ID, HTTP-коды, журнал фактических процессов |
| PG-6 | Длительная фоновая запись и UDP-приём во время подготовки restore | Подтверждена остановка всех writers и отсутствие записей в критическом интервале; после операции потребители восстановлены либо показано предупреждение | Процесс/worker lifecycle, счётчики приёма/записей, состояния jobs |
| PG-8 | Ошибка записи speed snapshot/history и потеря commit acknowledgement | Снимок/история атомарны; неизвестный commit не выдаётся за гарантированный rollback и не вызывает автоматический повтор native test | Состояние PG после восстановления соединения, runId, HTTP/UI |
| PG-7 | Неавторизованный пользователь и обычный settings writer | Backup/restore требуют settings admin, отказ происходит до выполнения процесса | 401/403, неизменные контрольные данные, отсутствие pg_dump/pg_restore |
Реализация: [bootstrap](../backend/src/db/bootstrap.ts), [migrations](../backend/src/db/migrate.ts), [0008](../backend/drizzle/0008_alert_outbox_outcomes.sql), [0009](../backend/drizzle/0009_alert_outbox_resolution.sql), [database operation](../backend/src/services/system-database-operation.ts), [restore execution](../backend/src/services/system-database-restore-execution.ts).
После12.5.15 приложение используетpg_dump -Fc, проверкуpg_restore --list, генерациюpg_restore --clean --if-exists --file иодинpsql -X --single-transaction --set ON_ERROR_STOP=on -c partition parent preparation -f SQL. Предварительнаяподготовкаиrestore находятсявобщейтранзакции. Транзакционный режим описан в [документации PostgreSQL](https://www.postgresql.org/docs/current/app-pgrestore.html). Проверка пяти байтов PGDMP проверяет заголовок, но не полноту и не доверие к архиву. Для rollback нужен сценарий с ошибкой исполнения restore, а не только отказ HTTP до его начала.
В локальном блоке12.5.8 добавлено ожидание текущих scheduler jobs с закрытием admission, но этот код ещё не развёрнут на стенде673e5ba. Блок12.5.9 добавляет отдельный graceful shutdown worker для database operation, serial flush, pool.end и обязательные acknowledgement/exit0. Локальные protocol tests и настоящий isolated collector/UDP/blocked SQL drain12.5.10 прошли: [evidence](ux-ui/acceptance/netflow-worker-2026-10-07.json). Основной код на стенде ещё не обновлён; app-wide quiescence этим не подтверждена. Блок12.5.11 локально добавляет admission/drain всех API handlers иtraffic live streams; новые tests/build passed, на стенде patch не развёрнут. В12.5.12 локально добавлен общий background registry/drain дляbackup/audit/certificate/partition maintenance/cache work, атакжеpause RIPE enqueue. Tests/build passed; В12.5.13 добавленcache invalidation послеуспешногоrestore идоconsumer restart, локальныесовместныеhelpers tests passed. Всяцепочка требуетreal-PG integrated quiescence/restore12.5.14. Основнойстенд покаsource673e5ba. Другие экземпляры/хосты требуют отдельного контроля. PG-6 остаётся открытым до наблюдаемого подтверждения; восстановление стенда выполняется после его получения. Реальные тесты backend, способные очищать таблицы, запускаются только против выделенной тестовой БД.
После bootstrap достаточно следующих запросов чтения для начальной проверки, без вывода секретов:
```sql
SELECT id FROM schema_migrations
WHERE id IN ('0008_alert_outbox_outcomes', '0009_alert_outbox_resolution');
SELECT status, count(*) FROM alert_outbox GROUP BY status;
SELECT min(resolution_version), max(resolution_version) FROM alert_outbox;
```
## Очередь уведомлений и Telegram
| ID | Сценарий | Проверяемый результат |
| --- | --- | --- |
| Q-1 | Два конкурентных claim одной записи | Один sender получает право отправить; duplicate claim не отправляет второй запрос |
| Q-2 | Telegram принял сообщение, затем settlement/history transaction отказала | Ответ Telegram не подменяет DB receipt; запись удерживается в unknown/processing, автоматического повторения нет |
| Q-3 | Timeout после возможной отправки | UI сообщает неизвестный исход; сообщение в чате и состояние БД проверяются независимо |
| Q-4 | POST /api/alerts/outbox/:id/retry для unknown с текущим expectedVersion | Одна транзакция переводит запись в pending и увеличивает resolutionVersion ровно на1; stale version даёт409 без нового изменения |
| Q-5 | Повтор processing или unknown без подтверждённой остановки всех отправителей | Processing не разрешается вручную через этот API. Перед повтором unknown зафиксированы остановка всех senders и осознанный риск дубликата |
| Q-6 | Два enqueue с одинаковым dedupe key | В PostgreSQL создана одна запись; нет двух отправок из-за race |
| Q-7 | Нарушение прав, malformed receipt, изменение источника при pending | Отказ до действия; UI сохраняет checkpoint/черновик и не переносит результат в другой источник |
Для Q-1/Q-6 нужны конкурентные соединения реального PG; in-memory DI не доказывает изоляцию. Для Q-2 проверить атомарность status/history при ошибке внутри транзакции. Остановка senders подтверждается процессами/контейнерами и завершением in-flight requests; checkbox, timeout и отсутствие недавних логов достаточным доказательством не являются. Различать принятие Telegram API и прочтение пользователем.
Источники: [outbox](../backend/src/services/alert-engine/outbox.ts), [delivery](../backend/src/services/alert-engine/outbox-execution.ts), [retry](../backend/src/services/alerts-outbox-retry.ts), [HTTP](../backend/src/routes/alerts.ts).
## RouterOS и сетевые операции
| ID | Сценарий | Проверяемый результат |
| --- | --- | --- |
| ROS-1 | Bandwidth-test transmit/receive/both на паре тестовых устройств | Реальный REST shape содержит native completion; TX — отправка клиента, RX — приём. Неизмеренная сторона null, измеренный0 сохраняется |
| ROS-2 | Authentication failed, unreachable, busy, disconnect и прерванный тест | Backend не пишет done и не заменяет старые probe averages; error run/HTTP/UI согласованы |
| ROS-3 | Выбранный srcInterface и тест скорости | Независимо проверить маршрут bandwidth-test и interface after-ping. UI не выдаёт выбор Ping-интерфейса за доказательство WAN скоростного теста |
| ROS-4 | Home→JH и JH↔Exit с асимметричной скоростью | Направления DL/UL соответствуют клиентской стороне; model limits применяются к правильному направлению |
| ROS-5 | OSPF preview → действие → перечитывание templates | Preview соответствует исправленным RX/DL и TX/UL. Применение подтверждается фактическим cost; частичный отказ не становится полным успехом |
| ROS-6 | WireGuard/IPsec/GRE/VXLAN/Firewall/BGP/маршруты | Проблема→устройство→форма→подтверждённое действие→возврат сохраняет контекст. Права и повторное нажатие проверены; фактическая конфигурация и connectivity сверены |
| ROS-9 | Смена пары или параметров измерения в каталоге и конкурентное завершение native test | Новый snapshot unknown, старый run сохранён с actual endpoints; enable/reorder сохраняют измеренный0. Проверить row locks/условный UPDATE в реальном PG |
| ROS-8 | Смена пары, интерфейсов, протокола, направления, длительности или удаление speed-пробы до запуска и во время теста | Preflight409 до команды; при поздней смене новый snapshot не перезаписан, actual run сохранён без stale probe association |
| ROS-10 | POST speed-test и последующий GET истории/пробы с разными часовыми поясами браузера и сервера | createdAt сохраняет серверный instant и совпадает с записью; nullable Ping не становится timeout. Это время перед after-ping, не начало bandwidth-test; legacy receipt без createdAt отдельно обозначить в evidence |
| ROS-7 | Удаление/отсутствие доступа/частичный отказ одного устройства | Ошибка не стирает форму, последний снимок и объекты остальных устройств; неизвестные метрики не превращаются в0 |
Для ROS-1/ROS-2 зафиксировать версию RouterOS и очищенный сырой ответ. Строковый status подтверждается по [официальному CLI reference](https://manual.mikrotik.com/docs/cli-reference/tool/bandwidth-test/); несовместимый REST shape требует отдельной коррекции контракта. Тест скорости способен нагрузить канал — длительность и endpoints выбираются для выделенного стенда. Команды и правила маршрутизации этой UX/UI-серией не расширялись.
## Остальные интеграции
| Область | Минимальная реальная проверка |
| --- | --- |
| MaxMind/RIPE | Валидный ответ, отказ/timeout, свежесть источника и неизвестное значение; реальные данные сверены с тестовыми адресами |
| Portal/Evolution | Настоящие роли/JWT, истечение/отзыв прав, scope приложения и смена backend; отказ происходит до операции |
| Сертификаты/S3/контейнеры | Реальный job/файл/объект и права после receipt; ошибка/частичный исход, восстановление контекста |
| Gitea/CI/релизы | Сборка и delivery в выделенном стенде, отображение фактического статуса и версия. Git-коммиты текущей задачи остаются локальными; публикация — отдельное действие |
BGP-prefix evaluator, отдельное live GRE расписание и recovery processing не считать реализованными по UI или локальным тестам: текущие ограничения описаны в журналах11Б/12.
## Запись результата и критерий завершения
Для каждого ID сохранить: HEAD, UTC, идентификатор стенда/версию, роль, исходное состояние, действие, HTTP/native receipt, независимо подтверждённое итоговое состояние, результат passed/failed/blocked, способ возврата стенда и ссылку на очищенное доказательство. Пример строки:
| ID | HEAD / стенд | Доказательство | Результат | Следующий шаг |
| --- | --- | --- | --- | --- |
| ROS-1 | Заполнить при запуске | Очищенные native rows + GET истории + снимок UI | Не выполнен | Проверить transmit/receive/both |
12.5 закрывается после выполнения обязательных сценариев и разбора отказов на согласованном стенде. Подготовленный протокол, успешные browser/DI tests и автоматический axe-аудит не заменяют внешние результаты или ручную работу со screen reader.
## Обнаруженный блокер restore — 2026-10-07
12.5.14 realAPI/sourcef1aac49 навыделеннойPG18.6 подтвердилadmission/drain,ноrestore400 из-заinheritedpartitionPRIMARY KEY при--clean. [Evidence/rollback controls](ux-ui/acceptance/real-restore-2026-10-07.json). PG-4 подтверждёнвграницахнастоящейSQLошибкииконтрольныхстрок/sequence/constraint; PG-3успех/последующийID иполныйPG-6 непроверены. Следующий12.5.15 исправляеттранзакционнуюочистку. Основнойruntime673e5ba сохранён.
## Restore исправлен — 2026-10-07
12.5.15 realAPI200/контрольархива/новыйID3 иinjectedCREATE INDEX400/rollback данных,sequence и1587constraints прошли: [evidence](ux-ui/acceptance/real-restore-fixed-2026-10-07.json). PG-3/4 принятывэтихграницах, Portal/UI/fullchecksum не проверены. Основнойruntime673e5ba сохранён; integratedPG-6/deployment ещёпредстоят. Приrestart ресурсныйcollector попыталсяопрашиватьdisabledserver3; исправление12.5.16.
## Политика выключенных серверов — 2026-10-07
12.5.16 по явномувыборупользователя убрал намеренноеHome Router исключение изuptime/RESTping; scheduledspeed игнорируетdisabledendpoint, manualspeedотказдосети. [RealPG/CHRматрица](ux-ui/acceptance/monitoring-enabled-2026-10-07.json) passed. Основнойruntime673e5ba не обновлён;integratedPG-6/deployment12.5.17 впереди.
## IntegratedPG-6 иdeployment — 2026-10-07
[12.5.17](ux-ui/acceptance/integrated-pg6-2026-10-07.json) подтвердилsingle-instanceadmission/drainHTTP/UDP/scheduler/backgroundwrite,restore200 ивозобновлениеUDP. [Deployment](ux-ui/acceptance/deployed-4c12c55-2026-10-07.json) основнойbackend4c12c55healthy/контрольБДpassed,frontend673e5ba прежний. Multi-instance/Portal/browserrestore/остальныеинтеграции требуютпродолжения12.5.18.