Перейти к основному содержимому

События LMS

Зачем нужно

LMS события нужны для интеграций с CRM, task-bank, notifications, management analytics, storefront и внешней LMS. События должны быть минимальными, безопасными и идемпотентными.

Общий envelope

type LmsEvent<T> = {
messageId: string;
messageKind: 'event';
messageType: string;
messageVersion: number;
producer: 'lms';
producerInstance: string;
traceId: string;
occurredAt: string;
correlationId?: string;
actor?: {
type: 'user' | 'service' | 'system';
id?: string;
};
data: T;
metadata?: Record<string, unknown>;
};

Правила безопасности

Events не должны содержать:

  • полный ответ ученика;
  • приватный комментарий преподавателя;
  • содержимое чата;
  • состав Learning Group с ФИО или контактами;
  • персональные данные сверх необходимых IDs;
  • payment details;
  • access tokens;
  • storage signed URLs.

Если потребителю нужны подробности, он должен запросить их через API с permission checks.

Outgoing events

Content events

EventКогдаPayload
lms.course.createdсоздан coursecourseId, subjectKey, createdByUserId
lms.course.updatedизменена metadatacourseId, changedFields
lms.course.archivedcourse архивированcourseId, reason
lms.course_version.createdсоздан draftcourseId, courseVersionId, sourceVersionId
lms.course_version.submitted_for_reviewотправлено на reviewcourseVersionId
lms.course_version.publishedопубликована versioncourseId, courseVersionId, version, contentHash
lms.course_version.retiredversion retiredcourseVersionId, reason

Потребители:

  • storefront получает публичную проекцию;
  • management получает факт публикации;
  • notifications может уведомить внутренних пользователей;
  • sync service может подготовить migration.

Enrollment events

EventКогдаPayload
lms.enrollment.createdсоздан enrollmentenrollmentId, studentProfileId, courseId, courseVersionId, source
lms.enrollment.activatedоткрыт доступenrollmentId, studentProfileId, courseId
lms.enrollment.pausedдоступ остановленenrollmentId, reason
lms.enrollment.resumedдоступ возобновлёнenrollmentId
lms.enrollment.revokedдоступ отозванenrollmentId, reason
lms.enrollment.completedкурс завершёнenrollmentId, completedAt, completionPercent
lms.entitlement.consumedLMS списала учебное потребление CRM entitlemententitlementId, sessionId, attendanceId, quantity
lms.entitlement.consumption_revertedсписание entitlement отмененоentitlementId, consumerRef, reason

Потребители:

  • notifications отправляет учебные уведомления;
  • management строит агрегаты;
  • CRM может сверить entitlement lifecycle;
  • roadmap может получить learning evidence.

Learning Workspace events

EventКогдаPayload
lms.learning_group.createdсоздана Learning GroupgroupId, organizationId, ownerTeacherUserId
lms.learning_group.updatedизменены title/description/statusgroupId, changedFields
lms.learning_group.archivedгруппа архивированаgroupId, reason
lms.learning_group_participant.addedучастник добавленgroupId, studentProfileId, source
lms.learning_group_participant.removedучастник удалёнgroupId, studentProfileId, reason
lms.learning_group_invite.sentinvite отправленinviteId, groupId, targetType
lms.learning_group_invite.acceptedinvite принятinviteId, groupId, studentProfileId
lms.learning_group_assignment.createdсоздано назначениеassignmentId, groupId, targetDomain, targetType
lms.learning_group_assignment.cancelledназначение отмененоassignmentId, reason

Learning Workspace events описывают рабочий контур преподавателя. Они не являются событиями enrollment, progress или competition result.

Learning activity events

EventКогдаPayload
lms.lesson.openedученик впервые открыл lessonenrollmentId, nodeId, courseVersionId
lms.content_block.viewedпросмотрен required blockenrollmentId, nodeId, contentBlockId
lms.activity.startedначата attemptattemptId, enrollmentId, contentBlockId
lms.activity.attemptedattempt создана или обновленаattemptId, enrollmentId, contentBlockId, status
lms.activity.submittedattempt отправленаattemptId, enrollmentId, contentBlockId
lms.activity.checkedattempt проверенаattemptId, status, score, maxScore, checkerSource
lms.activity.completedactivity завершенаattemptId, enrollmentId, contentBlockId, completedAt
lms.homework.submittedдомашняя работа отправленаsubmissionId, enrollmentId, nodeId
lms.homework.gradedдомашняя работа оцененаsubmissionId, score, statusDecision
lms.submission.submittedработа отправленаsubmissionId, enrollmentId, sourceType, sourceId
lms.feedback.createdсоздан feedbackfeedbackId, submissionId, statusDecision, score
lms.progress.updatedпересчитан snapshotenrollmentId, nodeId, status, completionPercent
lms.lesson.progress_updatedизменён прогресс урокаenrollmentId, nodeId, status, completionPercent
lms.topic.completion_updatedизменён topic completiontopicId, studentProfileId, status, masteryScore
lms.evidence.recordedзаписано evidenceevidenceId, sourceType, sourceId, studentProfileId

Roadmap events

EventКогдаPayload
lms.roadmap.publishedопубликована roadmap program/versionprogramId, version, publishedAt
lms.roadmap.topic_changedизменена тема roadmaptopicId, changedFields
lms.fact.changedсоздан, опубликован или изменён публичный учебный факт для витриныfactKey, sourceRef, changedFields

Live delivery events

EventКогдаPayload
lms.attendance.recordedзафиксирована посещаемостьattendanceId, sessionId, studentProfileId, status
lms.session.completedзанятие завершеноsessionId, groupId, completedAt
lms.teacher_session.completedзанятие преподавателя завершено для payrollsessionId, teacherUserId, durationMinutes

Gamification events

EventКогдаPayload
lms.xp.awardedначислен опытxpEventId, studentProfileId, amount, sourceRef
lms.badge.awardedвыдан badgebadgeAwardId, badgeId, studentProfileId
lms.streak.updatedобновлён streakstreakId, studentProfileId, currentCount

Workbook and project events

EventКогдаPayload
lms.workbook.revision_savedсохранена revisionworkbookId, revisionNo, enrollmentId
lms.workbook.submittedтетрадь отправленаworkbookId, enrollmentId
lms.project.createdсоздан проектprojectId, enrollmentId
lms.project_milestone.submittedmilestone отправленprojectId, milestoneId, enrollmentId
lms.project_milestone.completedmilestone принятprojectId, milestoneId, enrollmentId

Booking events

EventКогдаPayload
lms.booking_slot.createdсоздан учебный слотslotId, courseId, startsAt, teacherUserId
lms.booking.heldслот удержанslotId, enrollmentId, expiresAt
lms.booking.bookedзапись подтвержденаbookingId, slotId, enrollmentId
lms.booking.cancelledзапись отмененаbookingId, reason
lms.booking.completedзанятие завершеноbookingId
lms.booking.missedученик не пришёлbookingId

Chat events

EventКогдаPayload
lms.chat.thread_createdсоздан threadthreadId, contextType, contextId
lms.chat.message_createdсоздано сообщениеthreadId, messageId, senderUserId
lms.chat.message_hiddenсообщение скрытоthreadId, messageId, reason
lms.chat.thread_closedthread закрытthreadId, reason

lms.chat.message_created не содержит текст сообщения.

Incoming events

From CRM

EventДействие LMS
crm.entitlement.activatedсоздать или активировать enrollment
crm.entitlement.suspendedперевести enrollment в paused
crm.entitlement.resumedвернуть enrollment в active, если курс доступен
crm.entitlement.expiredперевести enrollment в revoked или paused по политике продукта
crm.entitlement.revokedперевести enrollment в revoked
crm.entitlement.changed_course_versionсоздать migration request

LMS не должна открывать доступ, если course или version не найдены.

From task-bank

EventДействие LMS
task-bank.attempt.checkedобновить attempt, создать feedback/evidence, пересчитать progress
task-bank.problem.updatedпометить draft references как needing review
task-bank.problem.retiredзапретить публикацию draft с устаревшей ссылкой

Published version не меняется автоматически при изменениях task-bank.

From identity

EventДействие LMS
identity.family_relation.changedинвалидировать family access cache
identity.user.deactivatedзакрыть login-dependent действия, не удалять history
identity.role.changedпересчитать permission cache
identity.organization_membership.changedпересчитать teacher mode и Learning Workspace visibility
identity.invite.acceptedактивировать Learning Group participant, если invite относится к группе
identity.student_profile.mergedrelink Learning Group participant refs после явного merge

From competitions

EventДействие LMS
competitions.training_publication.createdразрешить назначение опубликованного комплекта как LMS/training material
competitions.training_publication.revokedскрыть новое назначение тренировки, не менять historical LMS attempts

Competitions events не создают competition_result внутри LMS. Разборы и тренировочные попытки пишутся в учебный контур.

From external LMS sync

EventДействие LMS
external_lms.progress.importedсоздать external sync record и learning evidence
external_lms.course_mapping.updatedобновить mapping для migration
external_lms.sync.failedсохранить error и показать admin

Event versioning

  • Новые поля добавляются optional.
  • Удаление или изменение смысла поля требует новой messageVersion.
  • Consumer должен игнорировать неизвестные поля.
  • Producer должен сохранять совместимость минимум на один major cycle.

Idempotency

Каждый event обрабатывается по messageId.

Для webhook источников также используется natural key:

  • CRM: entitlementId + messageType + occurredAt;
  • task-bank: attemptId + checkerResultId;
  • external LMS: externalSystem + externalId + syncedAt.

Повторная доставка не должна создавать дубликаты enrollments, attempts, feedback или evidence.

Ordering

Ordering гарантируется только внутри aggregate:

  • course version;
  • enrollment;
  • attempt;
  • submission;
  • chat thread;
  • booking slot.

Если событие пришло раньше зависимости, consumer создаёт retry или dead-letter entry.

Observability

Для каждого event flow должны быть метрики:

  • produced count;
  • consumed count;
  • failed count;
  • retry count;
  • dead-letter count;
  • processing latency;
  • idempotent duplicate count.

Минимальный event backlog для MVP

Для MVP обязательны:

  • lms.course_version.published;
  • lms.enrollment.created;
  • lms.enrollment.activated;
  • lms.enrollment.revoked;
  • lms.learning_group.created;
  • lms.learning_group_assignment.created;
  • lms.lesson.opened;
  • lms.activity.submitted;
  • lms.feedback.created;
  • lms.progress.updated;
  • incoming crm.entitlement.activated;
  • incoming task-bank.attempt.checked.