17 KiB
UX/UI: протокол внешней приёмки 12.5
Статус на 2026-10-07: стенд161.104.46.222/source673e5ba развёрнут; PG-1 проверен в границах bootstrap/restart/schema/control-row, PG-2 проверен архивом и отдельной БД, PG-5 — реальными конкурентными backup/restore HTTP200/409. PG-7 — HTTP RBAC 401/403 при AUTH_REQUIRED=true, без доказательства отсутствия процессов и реального Portal SSO. Native TCP transmit/receive/both по3s и первоначальный отказ подключения проверены на паре CHR; прочие ROS/PG/Q/интеграционные сценарии остаются открытыми. PG evidence, паспорт, журнал, план.
Паспорт стенда
Перед внешним запуском зафиксировать отдельные 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, migrations, 0008, 0009, database operation, restore execution.
Приложение использует pg_dump -Fc и pg_restore --single-transaction --clean --if-exists. Транзакционный режим описан в документации PostgreSQL. Проверка пяти байтов PGDMP проверяет заголовок, но не полноту и не доверие к архиву. Для rollback нужен сценарий с ошибкой исполнения restore, а не только отказ HTTP до его начала.
В локальном блоке12.5.8 добавлено ожидание текущих scheduler jobs с закрытием admission, но этот код ещё не развёрнут на стенде673e5ba. Локальный вызов stopTrafficFlowListener пока не подтверждает завершение worker/flush; ручные API writers и экземпляры на других хостах также требуют отдельного контроля. PG-6 остаётся открытым до наблюдаемого подтверждения; восстановление стенда выполняется после его получения. Реальные тесты backend, способные очищать таблицы, запускаются только против выделенной тестовой БД.
После bootstrap достаточно следующих запросов чтения для начальной проверки, без вывода секретов:
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, delivery, retry, HTTP.
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; несовместимый 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.