docs: видимость активов и итоговые проверки

This commit is contained in:
2026-10-27 19:41:42 +03:00
parent 9aef82e217
commit d6461a3a9c
9 changed files with 109 additions and 56 deletions

View File

@@ -3,15 +3,15 @@
**Дата:** 2026-10-27.
**Ветка:** `feature/groups-courses`.
**Статус:** проверка этапа 6 выполнена; этап 6 закрыт **не полностью**.
Миграции, security-матрица, upgrade-тест и deploy-runbook проверены. Открытыми
остаются права преподавателя на запись, видимость активов, аудит и CI — см.
Миграции, security-матрица, upgrade-тест, видимость активов и deploy-runbook
проверены. Открытыми остаются права преподавателя на запись, аудит и CI — см.
раздел 4.
## 1. Итоговый объём этапов 0–5
| Этап | Что реализовано | Отчёт |
|---|---|---|
| 0 | Схема и контракты: identity `V4–V9`, academic `V6–V11`, progress `V13`; preflight-скрипты; ADR; контракт профиля студента курса | [10](10-stage0-report.md) |
| 0 | Схема и контракты: identity `V4–V9`, academic `V6–V12`, progress `V13`; preflight-скрипты; ADR; контракт профиля студента курса | [10](10-stage0-report.md) |
| 1 | Роли `ADMIN/TEACHER/STUDENT`, группы-когорты и парсер имени, статусы студентов и аккаунтов, `membership_history`, импорт v2 | [11](11-stage1-report.md) |
| 2 | Курсы, `course_no` для браузерных URL, история преподавателей и групп, bootstrap курса C, привязка лабораторных к курсу, копирование лабораторных, админ-UI | [12](12-stage2-report.md) |
| 3 | Аккаунты преподавателей, курсовая область видимости, внутренние API identity с `LMS_INTERNAL_TOKEN`, кабинет преподавателя, профиль студента курса и скачивание всех попыток | [13](13-stage3-report.md) |
@@ -26,6 +26,9 @@
- преподаватель видит только активные назначенные курсы; студент — только курсы
активной группы; админ — все курсы;
- студент видит только опубликованные оценки и комментарии;
- активы наследуют видимость статьи → раздела → главы: курсовые требуют доступа
к курсу, глобальные — аудитории, а старые файлы без привязки остаются
публичными (см. раздел 4);
- вход закрыт для отчисленных, выпущенных и архивных студентов, а также для
архивных аккаунтов; web дополнительно перепроверяет статус;
- повышение и жизненный цикл пишут историю; применение повышения идемпотентно.
@@ -42,6 +45,10 @@
Результат: `BUILD SUCCESSFUL`, код возврата `0`, все модули зелёные.
Счётчики включают новые тесты видимости активов: `academic-service` +9
(`ContentAssetAccessIntegrationTest`, импорт активов), `web` +2
(`ApiClientContentAssetTest`). Итог — **183 теста, 0 падений**.
Для получения актуальных счётчиков тесты запущены принудительно:
```bash
@@ -51,11 +58,11 @@
| Модуль | Тестов | Failures | Errors | Skipped |
|---|---:|---:|---:|---:|
| identity-service | 62 | 0 | 0 | 0 |
| academic-service | 53 | 0 | 0 | 0 |
| web | 40 | 0 | 0 | 0 |
| academic-service | 62 | 0 | 0 | 0 |
| web | 42 | 0 | 0 | 0 |
| progress-service | 12 | 0 | 0 | 0 |
| markdown | 5 | 0 | 0 | 0 |
| **Итого** | **172** | **0** | **0** | **0** |
| **Итого** | **183** | **0** | **0** | **0** |
`ktlintCheck` и `detekt` прошли без замечаний. Отдельных unit-тестов у gateway
и `common-http` в текущем дереве нет; маршрутизация gateway проверена
@@ -73,7 +80,7 @@
статья/актив, оценка, комментарий и попытка сдачи.
3. Поверх master применены миграции ветки:
- identity `V4–V9`;
- academic `V6–V11`;
- academic `V6–V12`;
- progress `V13`.
4. Выполнены postflight-запросы и повторное применение `V13`.
@@ -87,7 +94,10 @@
- **academic:** добавлены `labs.course_id`, `chapters.course_id/audience`,
индексы `labs_number_course_uidx`, `chapters_slug_global_uidx`,
`chapters_slug_course_uidx`, `article_assets_article_idx`,
`courses_title_lower_uidx`. Курс C миграциями не создаётся — его создаёт
`courses_title_lower_uidx`. `V12__asset_links_backfill.sql`
восстанавливает связи `article_assets` из markdown-ссылок
`/api/v1/content/assets/{name}`; файлы без ссылок остаются несвязанными.
Курс C миграциями не создаётся — его создаёт
bootstrap после входа админа, поэтому `labs_without_course` до bootstrap
ожидаемо больше нуля.
- **progress:** `grade_comments.author_account_id` и
@@ -106,13 +116,20 @@
### 2.3. Security-проверки
Проверено автоматическими тестами (полный прогон 172 теста) и разбором
Проверено автоматическими тестами (полный прогон 183 теста) и разбором
конфигурации gateway.
| Сценарий | Ожидание | Факт |
|---|---|---|
| Аноним → курс/материалы курса | нет доступа | `401` на `/api/v1/courses/{id}/content/tree`; `/api/v1/courses/by-no/{no}` — `401` |
| Аноним → публичные материалы | только глобальные `ALL` | публичное дерево содержит только глобальные главы с `audience = ALL`; курсовая глава через `/api/v1/content/...` — `404` |
| Аноним → актив глобальной `ALL`-статьи | публично | `200` |
| Аноним → курсовой/`STUDENTS`/`TEACHERS` актив | `404` | `404`, существование файла не раскрывается |
| Студент своего курса → актив опубликованной статьи | доступ | `200`; скрытый курсовой актив — `404` |
| Студент/преподаватель чужого курса → курсовой актив | `403` | `403` |
| Преподаватель своего курса → скрытый курсовой актив | доступ | `200`; админ видит любой актив |
| Глобальный `STUDENTS`-актив → преподаватель | `403` | `403`; студент получает `200` |
| Legacy-актив без связи со статьёй | публично | `200`; остаточный риск, раздел 4 |
| Админ → курс, профиль, скачивание | полный доступ | доступ к любому курсу и студенту, скачивание любой попытки курса |
| Преподаватель своего курса | курс, группы, профиль, материалы | видит опубликованные и скрытые материалы, всех студентов активной группы курса, неопубликованные оценки и все попытки |
| Преподаватель чужого курса | `403` | `403` на материалы, курс по `course_no`, состав группы и профиль |
@@ -124,8 +141,8 @@
| Gateway → заголовки личности | клиент не подменяет | `X-Account-Id/Login/Role` удаляются и проставляются только после проверки JWT |
| Web-сессия | быстрый отзыв доступа | статус перепроверяется не реже чем раз в 45 секунд; `active=false` или `401/403` инвалидируют сессию; недоступность identity не разлогинивает всех |
Остаточные риски перечислены в разделе 4: публичные активы и 30-дневный JWT
для прямого API.
Остаточные риски перечислены в разделе 4: legacy-активы без привязки,
права преподавателя на запись и 30-дневный JWT для прямого API.
## 3. Чек-лист деплоя
@@ -147,7 +164,7 @@
1. **Flyway.** `./deploy/deploy.sh up` собирает образы и запускает
`postgres → identity → academic → progress → gateway → web`. Миграции
применяются автоматически при старте сервисов:
identity `V4–V9`, academic `V6–V11`, progress `V13`.
identity `V4–V9`, academic `V6–V12`, progress `V13`.
Отдельный ручной запуск Flyway не нужен.
2. **Bootstrap курса C.** После входа админа открыть `/admin/courses`.
Пока курсов нет, показан блок первичной настройки. Bootstrap идемпотентно
@@ -193,6 +210,9 @@
материалы; видны только опубликованные оценки и комментарии.
- [ ] **Материалы курса:** админ и преподаватель видят скрытые статьи, студент —
только опубликованные; чужой курс даёт `403`, аноним уходит на `/login`.
- [ ] **Активы:** картинки курсовой статьи открываются у студента своего курса
и преподавателя; чужой курс — `403`, скрытая картинка у студента — `404`,
публичная `ALL` — без входа; старый файл без привязки — публичен.
- [ ] **Копирование лабораторной:** админ копирует лабораторную в другой курс;
создаётся черновик с уровнями и вариантами; оценки, сдачи, защиты и
назначения не копируются; занятый номер даёт `409`.
@@ -206,13 +226,13 @@
## 4. Известные пробелы и follow-up
1. **Активы всё ещё публичны.** Прокси `/api/v1/content/assets/{name}` (и
web-прокси) не проверяет курс/статью: `article_assets` не связаны с
видимостью материала. Курсовые картинки может получить любой, кто знает
имя файла. Нужно использовать связь `article_assets → article → section →
chapter` для проверки видимости и сделать visibility-aware маршруты,
отдельный публичный путь для `ALL`. Осознанно
вынесено из этапа 5, зафиксировано в [15](15-stage5-course-materials.md).
1. **Legacy-активы без привязки.** Видимость связанных активов реализована:
`V12` восстанавливает `article_assets` по markdown-ссылкам, а маршрут
`/api/v1/content/assets/{name}` проверяет курс/аудиторию и публикацию.
Остаточный случай — файлы, на которые нет ссылок ни в одной статье: они
остаются публичными. Нужна инвентаризация и привязка либо удаление таких
файлов; до этого fallback сохраняется, чтобы не ломать старые ссылки.
Детали — в [15](15-stage5-course-materials.md).
2. **Права преподавателя в основном read-only.** Кабинет преподавателя даёт
обзор курса, групп, лабораторных и профилей. Авторство лабораторных и
материалов, распределение вариантов, выставление оценок, комментарии,
@@ -249,9 +269,9 @@
authoring лабораторных/материалов, распределение вариантов, выставление
оценок и комментариев, коды и действия защиты; закрыть negative-тестами
«свой/чужой курс». Это закрывает основной разрыв с ТЗ.
2. **Видимость активов.** Использовать связь `article_assets → article →
section → chapter`, проверять курс и публикацию при выдаче, оставить
отдельный публичный маршрут только для `ALL`.
2. **Инвентаризация legacy-активов.** Найти файлы без строк в `article_assets`,
привязать их к статьям или удалить; после этого можно убрать публичный
fallback для несвязанных файлов.
3. **UI авторства контента.** Выбор курса и аудитории при создании глав/
статей, чтобы преподаватель и админ не работали только через импорт;
сейчас глобальные главы создаются с `ALL`, курсовые — без аудитории.
@@ -263,9 +283,9 @@
## 6. Итог
Этапы 0–5 реализованы и проверены. Security-матрица, upgrade-тест миграций и
deploy-runbook этапа 6 зелёные; отчёт и чек-лист передачи готовы. Этап 6
**нельзя считать полностью завершённым** до закрытия прав преподавателя,
видимости активов и CI. До этого релиз допустим только с пониманием, что
преподаватели работают в режиме просмотра, а активы курсовых материалов
остаются публичными.
Этапы 0–5 реализованы и проверены. Security-матрица, upgrade-тест миграций,
видимость активов и deploy-runbook этапа 6 зелёные; отчёт и чек-лист передачи
готовы. Этап 6 **нельзя считать полностью завершённым** до закрытия прав
преподавателя и CI. Видимость связанных активов реализована; публичными
остаются только старые файлы без привязки к статье (см. раздел 4), а
преподаватели пока работают в режиме просмотра.