npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hed-hog/lms

v0.0.292

Published

```markdown # @hed-hog/lms

Readme

# @hed-hog/lms

## 1. Visão geral do módulo

O módulo `@hed-hog/lms` é responsável pela gestão do sistema de Learning Management System (LMS) dentro do monorepo HedHog. Ele oferece funcionalidades para gerenciamento de cursos, aulas, avaliações, certificados, matrículas, instrutores, trilhas de aprendizagem e demais componentes relacionados ao ambiente educacional digital.

## 2. Escopo e responsabilidades

- Gerenciamento de cursos, módulos, aulas e suas respectivas estruturas.
- Controle de matrículas em cursos e trilhas de aprendizagem.
- Administração de avaliações, tentativas e respostas.
- Emissão e verificação de certificados.
- Gestão de instrutores e suas atribuições.
- Controle de presenças em aulas presenciais ou online.
- Organização de trilhas de aprendizagem e seus passos.
- Suporte a imagens e arquivos relacionados a cursos, exames e trilhas.
- Avaliações e feedbacks sobre tópicos específicos do LMS.

## 3. Endpoints

> **Nota:** O código fonte fornecido não expõe endpoints REST ou GraphQL diretamente. Este módulo é consumido via serviços internos ou APIs do HedHog que integram com o LMS.

## 4. Regras de autenticação e autorização

- Existe o papel (`role`) `admin-lms` com permissão total para gestão do LMS.
- Autenticação e autorização são gerenciadas externamente, utilizando o papel `admin-lms` para operações administrativas.
- Regras específicas de acesso devem ser implementadas conforme a integração com o sistema de autenticação do HedHog.

## 5. Estruturas de request/response

- Não aplicável diretamente, pois o módulo não expõe endpoints REST no código fornecido.
- Operações são realizadas via serviços internos ou APIs que consomem este módulo.

## 6. Erros comuns

- **Violação de integridade referencial:** ao inserir ou atualizar registros com chaves estrangeiras inválidas.
- **Duplicidade de registros únicos:** como códigos únicos de certificado, slugs de cursos ou templates.
- **Status inválidos:** ao definir valores fora dos enums para status de cursos, exames, matrículas, etc.
- **Campos obrigatórios ausentes:** como títulos, slugs e chaves primárias.

## 7. Banco de dados (tabelas YAML)

### certificate

- **Finalidade:** Armazena certificados emitidos para estudantes em cursos, exames, grupos de aulas ou trilhas de aprendizagem.
- **Colunas:**
  - `id` (PK)
  - `verification_code` (varchar 50, único): código para verificação do certificado.
  - `student_id` (FK para `person.id`, onDelete CASCADE): estudante que recebeu o certificado.
  - `course_enrollment_id` (FK opcional para `course_enrollment.id`, onDelete SET NULL)
  - `course_id` (FK opcional para `course.id`, onDelete SET NULL)
  - `exam_id` (FK opcional para `exam.id`, onDelete SET NULL)
  - `course_class_group_id` (FK opcional para `course_class_group.id`, onDelete SET NULL)
  - `learning_path_id` (FK opcional para `learning_path.id`, onDelete SET NULL)
  - `certificate_template_id` (FK para `certificate_template.id`)
  - `certificate_type` (enum: `course`, `exam`, `course_class_group`, `learning_path`)
  - `student_name` (varchar 255)
  - `course_name` (varchar 255)
  - `workload_hours` (int)
  - `issued_at` (datetime)
  - `completed_at` (datetime)
  - `final_score` (int, nullable)
  - `verification_url` (varchar 500, nullable)
  - `pdf_url` (varchar 500, nullable)
  - `created_at`, `updated_at`
- **Defaults:** Não possui defaults além dos timestamps.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** Chaves estrangeiras com regras onDelete conforme descrito.
- **Índices:** único em `verification_code`.

### certificate_template

- **Finalidade:** Modelos de certificados para emissão.
- **Colunas:**
  - `id` (PK)
  - `name` (varchar 255)
  - `slug` (varchar 255, único)
  - `description` (text, nullable)
  - `template_content` (text)
  - `status` (enum: `draft`, `active`, `inactive`, default `draft`)
  - `created_at`, `updated_at`
- **Defaults:** `status` default `draft`.
- **Nulabilidade:** `description` nullable.
- **Integridade:** -
- **Índices:** único em `slug`.

### course

- **Finalidade:** Cursos disponíveis no LMS.
- **Colunas:**
  - `id` (PK)
  - `title` (varchar 255)
  - `slug` (varchar 255, único)
  - `description` (text, nullable)
  - `short_description` (varchar 500, nullable)
  - `level` (enum: `beginner`, `intermediate`, `advanced`, default `beginner`)
  - `duration_hours` (int, default 0)
  - `status` (enum: `draft`, `published`, `archived`, default `draft`)
  - `primary_color`, `primary_contrast_color`, `secondary_color`, `secondary_contrast_color` (varchar 9, nullable)
  - `certificate_workload` (int, nullable)
  - `certificate_template_id` (FK opcional para `certificate_template.id`, onDelete SET NULL)
  - `requirements`, `objectives`, `target_audience` (text, nullable)
  - `created_at`, `updated_at`
- **Defaults:** `level` default `beginner`, `duration_hours` default 0, `status` default `draft`.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** FK para `certificate_template` com onDelete SET NULL.
- **Índices:** único em `slug`.

### course_category

- **Finalidade:** Associação entre cursos e categorias.
- **Colunas:**
  - `id` (PK)
  - `course_id` (FK para `course.id`, onDelete CASCADE)
  - `category_id` (FK para `category.id`, onDelete CASCADE)
  - `created_at`, `updated_at`
- **Defaults:** -
- **Nulabilidade:** -
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `course_id` + `category_id`.

### course_class_attendance

- **Finalidade:** Registro de presença dos estudantes em sessões de aula.
- **Colunas:**
  - `id` (PK)
  - `course_class_session_id` (FK para `course_class_session.id`, onDelete CASCADE)
  - `student_id` (FK para `person.id`, onDelete CASCADE)
  - `present` (boolean, default false)
  - `justification` (text, nullable)
  - `recorded_by_id` (FK opcional para `person.id`, onDelete SET NULL)
  - `created_at`, `updated_at`
- **Defaults:** `present` default false.
- **Nulabilidade:** `justification` e `recorded_by_id` opcionais.
- **Integridade:** FK com onDelete conforme descrito.
- **Índices:** único em combinação `course_class_session_id` + `student_id`.

### course_class_group

- **Finalidade:** Grupos de aulas de um curso.
- **Colunas:**
  - `id` (PK)
  - `course_id` (FK para `course.id`, onDelete CASCADE)
  - `title` (varchar 255)
  - `code` (varchar 50, único)
  - `description` (text, nullable)
  - `delivery_mode` (enum: `presential`, `online`, `hybrid`)
  - `status` (enum: `open`, `ongoing`, `completed`, `cancelled`, default `open`)
  - `start_date` (datetime)
  - `end_date` (datetime, nullable)
  - `start_time` (varchar 5, nullable)
  - `end_time` (varchar 5, nullable)
  - `week_days` (text, nullable)
  - `capacity` (int, default 30)
  - `location` (text, nullable)
  - `virtual_room_url` (varchar 500, nullable)
  - `created_at`, `updated_at`
- **Defaults:** `status` default `open`, `capacity` default 30.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em `code`.

### course_class_session

- **Finalidade:** Sessões específicas dentro de um grupo de aula.
- **Colunas:**
  - `id` (PK)
  - `course_class_group_id` (FK para `course_class_group.id`, onDelete CASCADE)
  - `title` (varchar 255)
  - `description` (text, nullable)
  - `session_date` (datetime)
  - `start_time` (varchar 5)
  - `end_time` (varchar 5)
  - `location` (text, nullable)
  - `meeting_url` (varchar 500, nullable)
  - `status` (enum: `scheduled`, `completed`, `cancelled`, default `scheduled`)
  - `created_at`, `updated_at`
- **Defaults:** `status` default `scheduled`.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** combinação `course_class_group_id` + `session_date`.

### course_class_session_instructor

- **Finalidade:** Instrutores vinculados a sessões de aula.
- **Colunas:**
  - `id` (PK)
  - `course_class_session_id` (FK para `course_class_session.id`, onDelete CASCADE)
  - `instructor_id` (FK para `instructor.id`, onDelete CASCADE)
  - `role` (enum: `lead`, `assistant`, default `assistant`)
  - `created_at`, `updated_at`
- **Defaults:** `role` default `assistant`.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `course_class_session_id` + `instructor_id`.

### course_enrollment

- **Finalidade:** Matrículas de pessoas em cursos ou grupos de aula.
- **Colunas:**
  - `id` (PK)
  - `person_id` (FK para `person.id`, onDelete CASCADE)
  - `course_class_group_id` (FK opcional para `course_class_group.id`, onDelete SET NULL)
  - `course_id` (FK para `course.id`, onDelete CASCADE)
  - `status` (enum: `pending`, `active`, `completed`, `cancelled`, `paused`, default `active`)
  - `enrolled_at` (datetime)
  - `completed_at` (datetime, nullable)
  - `progress_percent` (int, default 0)
  - `final_score` (int, nullable)
  - `created_at`, `updated_at`
- **Defaults:** `status` default `active`, `progress_percent` default 0.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** FK com onDelete conforme descrito.
- **Índices:** único em combinação `person_id` + `course_class_group_id`.

### course_image

- **Finalidade:** Imagens associadas a cursos.
- **Colunas:**
  - `id` (PK)
  - `course_id` (FK para `course.id`, onDelete CASCADE)
  - `file_id` (FK para `file.id`, onDelete CASCADE)
  - `image_type_id` (FK para `image_type.id`, onDelete CASCADE)
  - `order` (int)
  - `is_primary` (boolean, default false)
  - `created_at`, `updated_at`
- **Defaults:** `is_primary` default false.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `course_id` + `image_type_id` + `order`.

### course_lesson

- **Finalidade:** Aulas dentro de módulos de curso.
- **Colunas:**
  - `id` (PK)
  - `course_module_id` (FK para `course_module.id`, onDelete CASCADE)
  - `title` (varchar 255)
  - `description` (text, nullable)
  - `type` (enum: `video`, `text`, `quiz`, default `video`)
  - `content` (text, nullable)
  - `duration_seconds` (int, default 0)
  - `order` (int)
  - `is_released` (boolean, default true)
  - `created_at`, `updated_at`
- **Defaults:** `type` default `video`, `duration_seconds` default 0, `is_released` default true.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `course_module_id` + `order`.

### course_lesson_file

- **Finalidade:** Arquivos vinculados a aulas.
- **Colunas:**
  - `id` (PK)
  - `course_lesson_id` (FK para `course_lesson.id`, onDelete CASCADE)
  - `file_id` (FK opcional para `file.id`, onDelete SET NULL)
  - `title` (varchar 255)
  - `created_at`, `updated_at`
- **Nulabilidade:** `file_id` opcional.
- **Integridade:** FK com onDelete conforme descrito.
- **Índices:** em `course_lesson_id`.

### course_lesson_instructor

- **Finalidade:** Instrutores vinculados a aulas.
- **Colunas:**
  - `id` (PK)
  - `course_lesson_id` (FK para `course_lesson.id`, onDelete CASCADE)
  - `instructor_id` (FK para `instructor.id`, onDelete CASCADE)
  - `role` (enum: `lead`, `assistant`, default `assistant`)
  - `created_at`, `updated_at`
- **Defaults:** `role` default `assistant`.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `course_lesson_id` + `instructor_id`.

### course_lesson_progress

- **Finalidade:** Progresso dos estudantes em aulas.
- **Colunas:**
  - `id` (PK)
  - `course_enrollment_id` (FK para `course_enrollment.id`, onDelete CASCADE)
  - `course_lesson_id` (FK para `course_lesson.id`, onDelete CASCADE)
  - `status` (enum: `not_started`, `in_progress`, `completed`, default `not_started`)
  - `progress_percent` (int, default 0)
  - `video_progress_seconds` (int, default 0)
  - `started_at` (datetime, nullable)
  - `completed_at` (datetime, nullable)
  - `time_spent_seconds` (int, default 0)
  - `created_at`, `updated_at`
- **Defaults:** `status` default `not_started`, `progress_percent` default 0, `video_progress_seconds` default 0, `time_spent_seconds` default 0.
- **Nulabilidade:** `started_at` e `completed_at` opcionais.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `course_enrollment_id` + `course_lesson_id`.

### course_lesson_question

- **Finalidade:** Questões associadas a aulas do tipo quiz.
- **Colunas:**
  - `id` (PK)
  - `course_lesson_id` (FK para `course_lesson.id`, onDelete CASCADE)
  - `question_id` (FK para `question.id`, onDelete CASCADE)
  - `order` (int)
  - `created_at`, `updated_at`
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** únicos em combinações `course_lesson_id` + `question_id` e `course_lesson_id` + `order`.

### course_module

- **Finalidade:** Módulos dentro de cursos.
- **Colunas:**
  - `id` (PK)
  - `course_id` (FK para `course.id`, onDelete CASCADE)
  - `title` (varchar 255)
  - `description` (text, nullable)
  - `order` (int)
  - `duration_minutes` (int, default 0)
  - `created_at`, `updated_at`
- **Defaults:** `duration_minutes` default 0.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `course_id` + `order`.

### course_prerequisite

- **Finalidade:** Pré-requisitos para cursos.
- **Colunas:**
  - `id` (PK)
  - `course_id` (FK para `course.id`, onDelete CASCADE)
  - `prerequisite_type` (enum: `course`, `learning_path`, `exam`, default `course`)
  - `prerequisite_course_id` (FK opcional para `course.id`, onDelete CASCADE)
  - `prerequisite_learning_path_id` (FK opcional para `learning_path.id`, onDelete CASCADE)
  - `prerequisite_exam_id` (FK opcional para `exam.id`, onDelete CASCADE)
  - `created_at`, `updated_at`
- **Defaults:** `prerequisite_type` default `course`.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** únicos para combinações de curso e pré-requisitos.

### evaluation_rating

- **Finalidade:** Avaliações e notas dadas a tópicos de avaliação.
- **Colunas:**
  - `id` (PK)
  - `evaluation_topic_id` (FK para `evaluation_topic.id`, onDelete CASCADE)
  - `evaluator_id` (FK opcional para `person.id`, onDelete SET NULL)
  - `score` (decimal 2,1)
  - `comment` (text, nullable)
  - `created_at`, `updated_at`
- **Nulabilidade:** `evaluator_id` e `comment` opcionais.
- **Integridade:** FK com onDelete conforme descrito.
- **Índices:** único em combinação `evaluation_topic_id` + `evaluator_id`.

### evaluation_topic

- **Finalidade:** Tópicos para avaliação dentro do LMS.
- **Colunas:**
  - `id` (PK)
  - `name` (varchar 255)
  - `description` (text, nullable)
  - `target_type` (enum: `course`, `course_lesson`, `course_class_session`, `question`, `exam`)
  - `course_id` (FK opcional para `course.id`, onDelete SET NULL)
  - `course_lesson_id` (FK opcional para `course_lesson.id`, onDelete SET NULL)
  - `course_class_session_id` (FK opcional para `course_class_session.id`, onDelete SET NULL)
  - `question_id` (FK opcional para `question.id`, onDelete SET NULL)
  - `exam_id` (FK opcional para `exam.id`, onDelete SET NULL)
  - `order` (int)
  - `is_active` (boolean, default true)
  - `created_at`, `updated_at`
- **Defaults:** `is_active` default true.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** FK com onDelete SET NULL.
- **Índices:** únicos para combinações de alvo e ordem.

### exam

- **Finalidade:** Exames vinculados a cursos ou grupos de aula.
- **Colunas:**
  - `id` (PK)
  - `course_id` (FK opcional para `course.id`, onDelete SET NULL)
  - `course_class_group_id` (FK opcional para `course_class_group.id`, onDelete SET NULL)
  - `title` (varchar 255)
  - `description` (text, nullable)
  - `instructions` (text, nullable)
  - `exam_type` (enum: `quiz`, `test`, `assignment`, `project`)
  - `status` (enum: `draft`, `published`, `closed`, `archived`, default `draft`)
  - `primary_color`, `primary_contrast_color`, `secondary_color`, `secondary_contrast_color` (varchar 9, nullable)
  - `starts_at` (datetime, nullable)
  - `ends_at` (datetime, nullable)
  - `time_limit_minutes` (int, nullable)
  - `attempts_allowed` (int, default 1)
  - `min_score` (int, default 60)
  - `max_score` (int, default 100)
  - `shuffle_questions` (boolean, default false)
  - `shuffle_options` (boolean, default false)
  - `show_result` (boolean, default true)
  - `show_answer_key` (boolean, default false)
  - `show_explanation_after_answer` (boolean, default false)
  - `require_all_questions_answered_to_finish` (boolean, default false)
  - `created_at`, `updated_at`
- **Defaults:** `status` default `draft`, `attempts_allowed` 1, `min_score` 60, `max_score` 100, boolean flags default conforme descrito.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** FK com onDelete SET NULL.
- **Índices:** em `course_id`, `course_class_group_id` e `status`.

### exam_answer

- **Finalidade:** Respostas dadas em tentativas de exame.
- **Colunas:**
  - `id` (PK)
  - `exam_attempt_id` (FK para `exam_attempt.id`, onDelete CASCADE)
  - `question_id` (FK para `question.id`, onDelete CASCADE)
  - `exam_option_id` (FK opcional para `exam_option.id`, onDelete SET NULL)
  - `answer_text` (text, nullable)
  - `is_correct` (boolean, nullable)
  - `points_awarded` (int, default 0)
  - `teacher_feedback` (text, nullable)
  - `created_at`, `updated_at`
- **Defaults:** `points_awarded` default 0.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** FK com onDelete conforme descrito.
- **Índices:** único em combinação `exam_attempt_id` + `question_id`.

### exam_attempt

- **Finalidade:** Tentativas de realização de exames por estudantes.
- **Colunas:**
  - `id` (PK)
  - `exam_id` (FK para `exam.id`, onDelete CASCADE)
  - `student_id` (FK para `person.id`, onDelete CASCADE)
  - `course_enrollment_id` (FK opcional para `course_enrollment.id`, onDelete SET NULL)
  - `attempt_number` (int, default 1)
  - `started_at` (datetime)
  - `finished_at` (datetime, nullable)
  - `duration_seconds` (int, nullable)
  - `score` (int, nullable)
  - `status` (enum: `in_progress`, `completed`, `abandoned`, `voided`, default `in_progress`)
  - `ip_address` (varchar 45, nullable)
  - `created_at`, `updated_at`
- **Defaults:** `attempt_number` default 1, `status` default `in_progress`.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** FK com onDelete conforme descrito.
- **Índices:** único em combinação `exam_id` + `student_id` + `attempt_number`.

### exam_image

- **Finalidade:** Imagens associadas a exames.
- **Colunas:**
  - `id` (PK)
  - `exam_id` (FK para `exam.id`, onDelete CASCADE)
  - `file_id` (FK para `file.id`, onDelete CASCADE)
  - `image_type_id` (FK para `image_type.id`, onDelete CASCADE)
  - `order` (int)
  - `is_primary` (boolean, default false)
  - `created_at`, `updated_at`
- **Defaults:** `is_primary` default false.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `exam_id` + `image_type_id` + `order`.

### exam_option

- **Finalidade:** Opções de resposta para questões de exame.
- **Colunas:**
  - `id` (PK)
  - `question_id` (FK para `question.id`, onDelete CASCADE)
  - `option_text` (text)
  - `is_correct` (boolean, default false)
  - `position` (int, default 0)
  - `feedback` (text, nullable)
  - `created_at`, `updated_at`
- **Defaults:** `is_correct` default false, `position` default 0.
- **Nulabilidade:** `feedback` opcional.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `question_id` + `position`.

### exam_question

- **Finalidade:** Questões associadas a exames.
- **Colunas:**
  - `id` (PK)
  - `exam_id` (FK para `exam.id`, onDelete CASCADE)
  - `question_id` (FK para `question.id`, onDelete CASCADE)
  - `order` (int)
  - `created_at`, `updated_at`
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** únicos em combinações `exam_id` + `question_id` e `exam_id` + `order`.

### image_type

- **Finalidade:** Tipos de imagens aplicáveis a cursos, exames e trilhas.
- **Colunas:**
  - `id` (PK)
  - `name` (varchar 100)
  - `slug` (varchar 100, único)
  - `applies_to_course` (boolean, default false)
  - `applies_to_exam` (boolean, default false)
  - `applies_to_learning_path` (boolean, default false)
  - `status` (enum: `active`, `inactive`, default `active`)
  - `created_at`, `updated_at`
- **Defaults:** booleanos default false, `status` default `active`.
- **Integridade:** -
- **Índices:** único em `slug`.

### instructor

- **Finalidade:** Instrutores cadastrados no LMS.
- **Colunas:**
  - `id` (PK)
  - `person_id` (FK único para `person.id`, onDelete CASCADE)
  - `status` (enum: `active`, `inactive`, default `active`)
  - `can_teach_courses` (boolean, default true)
  - `created_at`, `updated_at`
- **Defaults:** `status` default `active`, `can_teach_courses` default true.
- **Integridade:** FK único com onDelete CASCADE.
- **Índices:** único em `person_id`.

### learning_path

- **Finalidade:** Trilhas de aprendizagem compostas por cursos e exames.
- **Colunas:**
  - `id` (PK)
  - `title` (varchar 255)
  - `slug` (varchar 255, único)
  - `description` (text, nullable)
  - `short_description` (varchar 500, nullable)
  - `level` (enum: `beginner`, `intermediate`, `advanced`, default `beginner`)
  - `duration_hours` (int, default 0)
  - `status` (enum: `draft`, `active`, `archived`, default `draft`)
  - `primary_color`, `primary_contrast_color`, `secondary_color`, `secondary_contrast_color` (varchar 9, nullable)
  - `created_at`, `updated_at`
- **Defaults:** `level` default `beginner`, `duration_hours` default 0, `status` default `draft`.
- **Nulabilidade:** Campos opcionais indicados.
- **Integridade:** -
- **Índices:** único em `slug`.

### learning_path_enrollment

- **Finalidade:** Matrículas em trilhas de aprendizagem.
- **Colunas:**
  - `id` (PK)
  - `learning_path_id` (FK para `learning_path.id`, onDelete CASCADE)
  - `person_id` (FK para `person.id`, onDelete CASCADE)
  - `status` (enum: `active`, `completed`, `cancelled`, default `active`)
  - `progress_percent` (int, default 0)
  - `enrolled_at` (datetime)
  - `completed_at` (datetime, nullable)
  - `created_at`, `updated_at`
- **Defaults:** `status` default `active`, `progress_percent` default 0.
- **Nulabilidade:** `completed_at` opcional.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `learning_path_id` + `person_id`.

### learning_path_image

- **Finalidade:** Imagens associadas a trilhas de aprendizagem.
- **Colunas:**
  - `id` (PK)
  - `learning_path_id` (FK para `learning_path.id`, onDelete CASCADE)
  - `file_id` (FK para `file.id`, onDelete CASCADE)
  - `image_type_id` (FK para `image_type.id`, onDelete CASCADE)
  - `order` (int)
  - `is_primary` (boolean, default false)
  - `created_at`, `updated_at`
- **Defaults:** `is_primary` default false.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** único em combinação `learning_path_id` + `image_type_id` + `order`.

### learning_path_step

- **Finalidade:** Passos dentro de uma trilha, podendo ser cursos ou exames.
- **Colunas:**
  - `id` (PK)
  - `learning_path_id` (FK para `learning_path.id`, onDelete CASCADE)
  - `step_type` (enum: `course`, `exam`)
  - `course_id` (FK opcional para `course.id`, onDelete CASCADE)
  - `exam_id` (FK opcional para `exam.id`, onDelete CASCADE)
  - `order` (int)
  - `is_required` (boolean, default true)
  - `created_at`, `updated_at`
- **Defaults:** `is_required` default true.
- **Integridade:** FK com onDelete CASCADE.
- **Índices:** únicos para combinações de trilha e ordem, curso ou exame.

### question

- **Finalidade:** Questões para avaliações e quizzes.
- **Colunas:**
  - `id` (PK)
  - `question_type` (enum: `multiple_choice`, `true_false`, `essay`, `fill_blank`, `matching`)
  - `statement` (text)
  - `explanation` (text, nullable)
  - `points` (int, default 1)
  - `created_at`, `updated_at`
- **Defaults:** `points` default 1.
- **Nulabilidade:** `explanation` opcional.

## 8. Regras de negócio relevantes

- Certificados são vinculados a estudantes e podem estar associados a diferentes tipos de atividades (curso, exame, grupo de aula, trilha).
- Cursos, exames e trilhas possuem status que controlam sua visibilidade e disponibilidade.
- Matrículas e inscrições possuem status que refletem o progresso e situação do aluno.
- Avaliações e tentativas de exame são controladas para permitir múltiplas tentativas e registrar resultados detalhados.
- Instrutores podem ter papéis distintos (líder ou assistente) em aulas e sessões.
- Trilhas de aprendizagem são compostas por passos ordenados que podem ser cursos ou exames, podendo ser obrigatórios ou opcionais.
- Progresso em aulas e cursos é monitorado para permitir acompanhamento detalhado do aluno.
- Imagens e arquivos são organizados por tipo e podem ser marcados como primários para exibição.

## 9. Guia rápido de uso (exemplos)

> Como o módulo não expõe endpoints diretamente, o uso típico envolve integração via serviços internos ou APIs do HedHog.

### Exemplo: Criar um novo curso

```ts
const novoCurso = await prisma.course.create({
  data: {
    title: 'Introdução ao HedHog LMS',
    slug: 'introducao-hedhog-lms',
    description: 'Curso básico para entender o LMS HedHog',
    level: 'beginner',
    duration_hours: 10,
    status: 'draft',
  },
});

Exemplo: Matricular um estudante em um curso

const matricula = await prisma.course_enrollment.create({
  data: {
    person_id: estudanteId,
    course_id: cursoId,
    status: 'active',
    enrolled_at: new Date(),
  },
});

Exemplo: Registrar presença em uma sessão de aula

const presenca = await prisma.course_class_attendance.upsert({
  where: {
    course_class_session_id_student_id: {
      course_class_session_id: sessaoId,
      student_id: estudanteId,
    },
  },
  update: { present: true },
  create: {
    course_class_session_id: sessaoId,
    student_id: estudanteId,
    present: true,
  },
});

Exemplo: Emitir um certificado

const certificado = await prisma.certificate.create({
  data: {
    verification_code: gerarCodigoUnico(),
    student_id: estudanteId,
    course_id: cursoId,
    certificate_template_id: templateId,
    certificate_type: 'course',
    student_name: nomeEstudante,
    course_name: nomeCurso,
    workload_hours: cargaHoraria,
    issued_at: new Date(),
    completed_at: dataConclusao,
    final_score: notaFinal,
    verification_url: urlVerificacao,
    pdf_url: urlPdf,
  },
});

Para mais detalhes sobre integração e uso, consulte a documentação geral do HedHog e os serviços que consomem o módulo @hed-hog/lms.