# Итоги: 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`; блокировка попыток хранится в памяти процесса (сбрасывается перезапуском). - Уменьшение срока/лимита в настройках сразу удаляет старые записи (пароль для настроек по ТЗ не требуется); действие фиксируется в журнале. - Очистка необратима (кроме восстановления из копии БД/тома). Боевой журнал при проверке не очищался.