RF58: Usuario recibe certificado de finalización de curso
Descripción
Como usuario que finalizó un curso, quiero recibir y descargar mi certificado de finalización para acreditar lo aprendido.
El certificado lo genera el sistema (RF59) y se entrega al usuario (notificación + descarga). El PDF se guarda en S3 privado y se entrega vía URL prefirmada de corta expiración.
| Campo | Valor |
|---|---|
| Módulo | Courses Module |
| Actor | Usuario autenticado |
| Endpoint | GET /courses/:id/certificate |
| Precondiciones | El curso está finalizado (RF57) y el certificado generado (RF59) |
| Prioridad | Baja (post-MVP) |
| Etapa | MBI 1 |
| Requisitos relacionados | RF57, RF59 |
Reglas de negocio
- RN-58.1 — Solo el usuario dueño del certificado puede descargarlo (validado por
user_id). - RN-58.2 — El PDF se entrega por URL prefirmada con expiración corta; el bucket es privado.
- RN-58.3 — El certificado incluye nombre del usuario, curso, fecha y un folio/identificador verificable.
- RN-58.4 — Si el certificado aún no está generado, se informa que está en proceso.
Validaciones de entrada
| Campo | Reglas | Mensaje de error |
|---|---|---|
id | Obligatorio. Curso finalizado por el usuario. | "Certificado no disponible." (404) |
Authorization | Bearer válido. | "Sesión no válida." (401) |
Criterios de aceptación
Escenario 1: Descarga de certificado exitosa
Dado que finalicé el curso y el certificado está generado,
Cuando lo solicito,
Entonces el sistema entrega una URL prefirmada para descargar el PDF,
Y responde 200 OK.
Escenario 2: Certificado aún en proceso
Dado que finalicé el curso pero el certificado aún se está generando, Cuando lo solicito, Entonces el sistema informa que está en proceso y que se notificará cuando esté listo.
Escenario 3: Curso no finalizado
Dado que no finalicé el curso,
Cuando intento obtener el certificado,
Entonces el sistema responde 404 con "Certificado no disponible".
Escenario 4: Acceso ajeno (seguridad)
Dado que intento descargar el certificado de otro usuario, Cuando el backend valida, Entonces rechaza la solicitud (no es mío).
Criterios no funcionales
- URL prefirmada de corta expiración; bucket privado.
- Comunicación TLS 1.2+.