Files
ros_control/docs/changes/017-events-ui-rotation/summary.md
T
ayurishchevandClaude Sonnet 5 26dd1f8be4 Уникальные ID сущностей, журнал событий и его UI с ротацией и очисткой
Глобально уникальные ID (docs/changes/016):
- у устройств, групп, задач, резервных копий и записей журнала ID вида
  <префикс>_<uuid7> (dev_, grp_, job_, bkp_, evt_): типы не пересекаются,
  внутри типа ID не повторяются и сортируются по времени;
- миграция БД v1 заменяет числовые ID с пересчётом ссылок (копия файла БД
  перед миграцией, сверка числа строк, одна транзакция);
- резервная копия = пара файлов с одним bkp_ ID, файлы в S3 получают
  метаданные backup-id/device-id; синхронизация метаданных с бакетом;
- журнал событий в БД (events): создание/изменение/удаление, задачи, бэкапы,
  смена online/offline, вход в UI; API чтения GET /api/v1/events.

Журнал в UI, ротация и очистка (docs/changes/017):
- страница «Журнал»: фильтры, подгрузка «Показать ещё», окно записи;
- настройки ротации (срок и максимум записей) хранятся в БД (схема v2),
  ротация при старте, раз в час и после сохранения настроек;
- очистка журнала только через окно с паролем пользователя, блокировка
  после 5 неверных попыток, остаётся запись о факте очистки; через API
  очистки нет.

Тесты: 20 из 20.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 17:01:52 +03:00

5.5 KiB
Raw Blame History

Итоги: 017 — журнал в UI, ротация, очистка с паролем

Сделано (по утверждённому макету)

  • Страница «Журнал» (пункт меню): сводка («N записей · старейшая … · ротация: …»), фильтры (тип и группа типов, актор, устройство, период, поиск по сообщению/ID; закладки), таблица (время UTC, тип цветной меткой, сущность, сообщение, актор, короткий ID), «Показать ещё 100» (подгрузка по курсору ID), клик по строке или по ID открывает окно записи с полными ID, данными JSON и кнопками «Копировать».
  • Настройки ротации (окно): срок хранения (дней) и максимум записей, 0 — без ограничения. Хранятся в БД (app_settings, схема v2), значения по умолчанию из .env (EVENTS_RETENTION_DAYS=90, EVENTS_MAX_ROWS=100000). Ротация: при старте, раз в час и сразу после сохранения; по сроку и по числу записей (после неё в журнале ровно max_rows, без «пилы»); оставляет journal.rotated; изменение настроек пишет journal.settings_changed.
  • Очистка: окно с паролем пользователя сессии (постоянное сравнение, пароль не пишется в журнал и не возвращается в поле). Кнопка «Очистить» неактивна, пока поле пустое; неверный пароль — событие journal.clear_denied и счётчик попыток («Осталось попыток: N»); 5 неверных за 10 минут — блокировка на 10 минут (journal.clear_locked). Успех: в одной транзакции удаляются все записи и остаётся одна journal.cleared (кто, сколько). POST не из окна отклоняется; в API очистки нет (только GET/PUT /api/v1/events/settings и чтение журнала с новыми фильтрами actor, date_from, date_to, q).

Проверено

  • pytest: 20 из 20 (+3: ротация по сроку/числу/«0 = без ограничения»/валидация; очистка: пароль, блокировка, одна оставшаяся запись, отсутствие API-очистки; страница журнала: фильтры, курсор, окно записи, настройки).
  • Браузер (Playwright) на копии боевой БД во втором экземпляре (порт 8766, опрос и S3 выключены; боевой журнал не затронут): пункт меню, подгрузка 100+100+69 записей, фильтры (тип, актор, «Сбросить (2)»), окно записи по клику строки, «Копировать», настройки (ошибка валидации в окне; срок 30 дней удалил 8 искусственно состаренных записей и оставил journal.rotated/journal.settings_changed), очистка (кнопка неактивна → активна; ошибки «Осталось попыток: 4/3»; верный пароль → одна запись journal.cleared с deleted: 273), блокировка после 5 неверных, тёмная тема, узкое окно; ошибок JS нет. Стартовая ротация подтверждена (при запуске копии удалены 6 записей старше 90 дней).
  • Боевая система пересобрана: схема v2, журнал цел (16 записей), настройки по умолчанию 90 дней / 100 000 записей.

Отличия от макета

  • В состоянии «неверный пароль» поле пароля очищается (макет показывал введённые точки): введённый пароль не возвращается с сервера. Кнопка «Очистить» снова неактивна до нового ввода.
  • Найдено и исправлено при проверке: время в таблице переносилось на вторую строку (колонка расширена), необработанная ошибка при запрете буфера обмена (добавлен запасной путь копирования), отключённое поле пароля не было серым.

Оговорки

  • Единственный пользователь — ADMIN_USER; блокировка попыток хранится в памяти процесса (сбрасывается перезапуском).
  • Уменьшение срока/лимита в настройках сразу удаляет старые записи (пароль для настроек по ТЗ не требуется); действие фиксируется в журнале.
  • Очистка необратима (кроме восстановления из копии БД/тома). Боевой журнал при проверке не очищался.