143 lines
7.5 KiB
Markdown
143 lines
7.5 KiB
Markdown
# LDD baseline: 2026-10-27
|
||
|
||
Первый прогон доказательной проверки текущей функциональности LMS.
|
||
Код приложения в этом прогоне не менялся; добавлены реестр claims, gate
|
||
`evidenceCheck`, runtime- и migration-скрипты.
|
||
|
||
## 1. Что проверялось
|
||
|
||
Реестр: `docs/evidence/claims.json`, 31 утверждение.
|
||
|
||
| Критичность | Claims | Proven | Gaps |
|
||
|---|---:|---:|---:|
|
||
| P0 | 19 | 19 | 0 |
|
||
| P1 | 12 | 12 | 0 |
|
||
| **Итого** | **31** | **31** | **0** |
|
||
|
||
Домены:
|
||
|
||
- доступы: аноним/студент/преподаватель/админ, чужие курс/лаба/студент/группа,
|
||
внутренние API identity;
|
||
- повышение: dry-run, apply, идемпотентность, rollback, cancel;
|
||
- жизненный цикл: академ, возврат, отчисление, архив, восстановление, вход;
|
||
- профиль студента и скачивание сдач;
|
||
- материалы и активы;
|
||
- миграция V13 и полный upgrade с master-схемы;
|
||
- аудит: токен, admin-only, сохранность после удаления, representative-хуки;
|
||
- группы курса, авторство материалов, ведомость, UI/контракты, импорт, копирование лаб;
|
||
- runtime-smoke полного стека.
|
||
|
||
## 2. Команды и результаты
|
||
|
||
### 2.1. Автоматические тесты
|
||
|
||
```bash
|
||
./gradlew test --rerun-tasks
|
||
```
|
||
|
||
Результат: **267 тестов, 0 failures, 0 errors, 0 skipped**.
|
||
`ktlintCheck` и `detekt` — зелёные.
|
||
|
||
### 2.2. LDD gate
|
||
|
||
```bash
|
||
./gradlew evidenceCheck
|
||
```
|
||
|
||
Результат: **31/31 claims proven, P0 gaps = 0**.
|
||
Отчёт: `build/reports/evidence/index.md`.
|
||
|
||
Gate устроен так:
|
||
|
||
- каждый claim ссылается на конкретный JUnit-тест `Class#method`;
|
||
- P0 без зелёного теста валит сборку;
|
||
- P1-пробел показывается в отчёте;
|
||
- runtime-проверки читаются из `build/evidence/*.json` и тоже должны быть
|
||
`passed`, если claim на них ссылается.
|
||
|
||
### 2.3. Upgrade с master-схемы
|
||
|
||
```bash
|
||
./scripts/ldd-migration-upgrade.sh
|
||
```
|
||
|
||
Сценарий: одноразовая PostgreSQL 18, master identity `V1–V3`, academic
|
||
`V1–V5`, progress `V1–V9,V11,V12`, синтетические данные, затем ветка:
|
||
identity `V4–V10`, academic `V6–V12`, progress `V13`.
|
||
|
||
Проверено:
|
||
|
||
- `identity.audit_events` создана;
|
||
- `students`, `groups`, `membership_history` сохранились;
|
||
- `labs.course_id`, `chapters.course_id`, `article_assets` созданы;
|
||
- `grade_comments.author_account_id`, `lab_grades.updated_by_account_id` созданы;
|
||
- оценки и комментарии сохранились;
|
||
- повторное применение `V13` идемпотентно.
|
||
|
||
Результат: **PASS**, evidence: `build/evidence/migration.json`.
|
||
|
||
### 2.4. Runtime-smoke полного стека
|
||
|
||
```bash
|
||
./scripts/ldd-runtime.sh
|
||
```
|
||
|
||
Сценарий: одноразовая БД, `bootJar`, запуск identity/academic/progress/gateway/web,
|
||
реальные HTTP-вызовы через gateway.
|
||
|
||
Проверено:
|
||
|
||
- health всех пяти сервисов = `UP`;
|
||
- `adminExists=false` до setup, создание админа, `/auth/me` = `ADMIN`;
|
||
- создание группы, курса, преподавателя, привязка группы, создание лабы;
|
||
- преподаватель входит и видит свой курс, лабу и состав группы;
|
||
- чужой преподаватель получает `403` на курс, лабу и аудит;
|
||
- админ видит audit-события `COURSE_CREATE`, `TEACHER_CREATE`,
|
||
`COURSE_TEACHER_ASSIGN`, `COURSE_GROUP_ATTACH`, `LAB_CREATE`;
|
||
- web `/login` отдаёт `200`, публичное дерево материалов доступно, курсовая
|
||
материалы анонимно — `401`.
|
||
|
||
Результат: **PASS**, evidence: `build/evidence/runtime.json`.
|
||
Стек и одноразовая БД после прогона остановлены/удалены.
|
||
|
||
## 3. Что это доказывает
|
||
|
||
- Критичные P0-инварианты доступа, повышения, жизненного цикла, профиля,
|
||
материалов, миграции и аудита имеют зелёные автоматические свидетельства.
|
||
- Приложение собирается, мигрируется с master-схемы и поднимается полным
|
||
стеком на чистой БД.
|
||
- Ключевой доменный поток «админ → группа → курс → преподаватель → лаба»
|
||
проходит через реальные HTTP/gateway/БД, а не только через mock.
|
||
- Чужой преподаватель не получает доступ к курсу/лабе/аудиту на реальном стеке.
|
||
- Аудит пишется и читается; upgrade не теряет синтетические данные.
|
||
|
||
## 4. Чего это не доказывает
|
||
|
||
1. **Нет браузерного E2E.** Thymeleaf-тесты проверяют HTML, но не реальные
|
||
клики/JS/CSRF/редиректы в браузере.
|
||
2. **Нет нагрузочных и конкурентных испытаний.** Advisory locks и гонки
|
||
проверены кодом и unit/integration-тестами, но не под нагрузкой.
|
||
3. **Нет mutation testing.** Сила тестов измерена косвенно; следующий шаг —
|
||
PIT на `CourseAccessService`, `PromotionService`, `StudentProfileService`.
|
||
4. **Нет property-based/model-based проверки повышения.** Один сценарный тест
|
||
не покрывает все комбинации курсов, степеней и академ-переходов.
|
||
5. **Legacy-активы без `article_assets` остаются публичными.**
|
||
6. **JWT живёт до 30 дней.** Web перепроверяет статус, прямой API — нет.
|
||
7. **Ведущие нули номера группы нормализуются** (`01` → `1`).
|
||
8. **Нет пагинации/keyset** для части списков и N+1 в отдельных экранах.
|
||
9. **Runtime-smoke не входит в unit-CI**; он запускается отдельным скриптом
|
||
перед релизом.
|
||
|
||
## 5. Вывод
|
||
|
||
Текущая функциональность прошла первый LDD-контур: **P0 gaps = 0**,
|
||
полный стек и upgrade работают. Это достаточное основание продолжать
|
||
доработки, но не «формальное доказательство всей системы». Следующий цикл
|
||
LDD должен добавить:
|
||
|
||
1. mutation testing для критичных пакетов;
|
||
2. property-based тесты повышения и матрицы доступа;
|
||
3. браузерный E2E (Playwright) для ведомости, профиля и материалов;
|
||
4. нагрузочный smoke на чтение ведомости/профиля;
|
||
5. автоматический runtime-smoke в release-пайплайне.
|