feat: закрыть остаточный backlog

- keyset-пагинация аудита с курсором (occurred_at, id) и UI «Показать ещё»
- пакетный /api/v1/labs/details и переход progress на один запрос
- абсолютный потолок сессии 30 дней (identity V12 + web), очистка refresh
- админская инвентаризация legacy-активов (/admin/legacy-assets, скрипт)
- E2E в Chromium/Firefox/WebKit (18/18), CI preflight
- LDD: 51 claim, 346 тестов, docs и handoff обновлены
This commit is contained in:
2026-10-28 19:29:23 +03:00
parent d45137220c
commit 1e1e9ae0e4
64 changed files with 2124 additions and 372 deletions

View File

@@ -60,13 +60,18 @@ Compose передаёт одно и то же значение identity, academ
Сроки аутентификации и сессии (можно не задавать — действуют значения ниже):
```dotenv
LMS_ACCESS_TOKEN_TTL=15m # access JWT identity, короткий
LMS_REFRESH_TOKEN_TTL=7d # refresh-токен, ротация и отзыв
LMS_SESSION_TIMEOUT=7d # web-сессия LMS_SESSION, sliding
LMS_ACCESS_TOKEN_TTL=15m # access JWT identity, короткий
LMS_REFRESH_TOKEN_TTL=7d # refresh-токен, ротация и отзыв
LMS_SESSION_TIMEOUT=7d # web-сессия LMS_SESSION, sliding
LMS_SESSION_ABSOLUTE_TIMEOUT=30d # жёсткий потолок сессии
LMS_REFRESH_TOKEN_RETENTION=30d # сколько хранить истёкшие refresh
LMS_REFRESH_TOKEN_CLEANUP_CRON=0 30 3 * * *
```
`LMS_ACCESS_TOKEN_TTL` и `LMS_REFRESH_TOKEN_TTL` читает identity,
`LMS_SESSION_TIMEOUT` — web. `docker-compose.prod.yml` прокидывает эти
`LMS_ACCESS_TOKEN_TTL`, `LMS_REFRESH_TOKEN_TTL`,
`LMS_SESSION_ABSOLUTE_TIMEOUT`, `LMS_REFRESH_TOKEN_RETENTION` и
`LMS_REFRESH_TOKEN_CLEANUP_CRON` читает identity; `LMS_SESSION_TIMEOUT` и
`LMS_SESSION_ABSOLUTE_TIMEOUT` — web. `docker-compose.prod.yml` прокидывает эти
переменные в environment соответствующих сервисов; при переопределении
используются значения из `.env.prod`. Access
обновляется автоматически за 2 минуты до истечения; прямой API-клиент должен
@@ -125,24 +130,30 @@ git pull
`deploy.sh up` **обязательно** делает backup перед обновлением. Если backup
завершился ошибкой, деплой прерывается. Миграции БД (Flyway) применяются
автоматически при старте сервисов: identity `V4–V11` (`V10` создаёт
`identity.audit_events`, `V11` — `identity.refresh_tokens`), academic `V6–V12`,
автоматически при старте сервисов: identity `V4–V13` (`V10` создаёт
`identity.audit_events`, `V11` — `identity.refresh_tokens`, `V12` —
`absolute_expires_at`, `V13` — keyset-индексы аудита), academic `V6–V12`,
progress `V13`.
После обновления проверьте, что админ открывает `/admin/audit` и видит события
(например, после входа в профиль студента — `PROFILE_VIEW`); преподаватель и
студент на эту страницу не попадают. Журнал листается через `page`/`limit`
(«Показать ещё»). Для инвентаризации старых файлов админ может вызвать
`GET /api/v1/content/legacy-assets`: файлы без привязки к статье больше не
публичны (`404` для обычных пользователей), их нужно привязать или удалить.
студент на эту страницу не попадают. Журнал листается keyset-курсором
(`cursor`/`limit`, «Показать ещё»; offset `page` остаётся для совместимости).
Для инвентаризации старых файлов админ открывает `/admin/legacy-assets`,
вызывает `GET /api/v1/content/legacy-assets` или запускает
`scripts/legacy-assets.sh`: файлы без привязки к статье больше не публичны
(`404` для обычных пользователей), их нужно привязать или удалить.
CI (`.gitlab-ci.yml`) на каждом push/MR выполняет
`./gradlew --no-daemon test ktlintCheck detekt evidenceCheck` и job `smoke`
(`./scripts/ldd-smoke.sh`: полный стек, health, вход админа, один курс).
Полный job `release-evidence` (`./scripts/ldd-release.sh`) обязателен для тегов
и запускается вручную для веток. `check` использует privileged `docker:dind`
и запускается вручную для веток. `smoke` и release запускают
`scripts/ci-preflight.sh`, который проверяет Java 21, Docker Compose v2,
Python 3, Node и Playwright. `check` использует privileged `docker:dind`
для Testcontainers; `smoke`/`release-evidence` выполняются на shell-runner
с Java 21, Docker Compose v2, Python 3, Node и Chromium Playwright.
с Java 21, Docker Compose v2, Python 3, Node и браузерами
Chromium/Firefox/WebKit.
## 8. Резервное копирование