Базовая работа с курсами (без уроков — добавятся в следующей итерации).
CourseRepository:
- List с тем же паттерном что TestRepository: ownerFilter +
onlyPublished + visibleIDs (для будущего access_grants).
- Get / GetBySlug — slug нужен для public-страниц.
- Create — slugify(title) если slug не задан; collision retry до 5 раз
(UNIQUE constraint courses_slug_key).
- Update / Delete с CASCADE на lessons.
- courseCols + lessons_count subquery, UI получает бейдж без отдельного
запроса.
CourseHandler — стандартный набор. Гейтит owner для write/delete;
read доступен всем (внутри сервиса), portal проксирует под
service.learning.access.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>