Registro y Onboarding Polimórfico
El registro está diseñado bajo una arquitectura Onboarding-First: prioriza la validación antes de la captura de datos (polimórficos) de perfil.
Convención: en producto se usa "Profesional de la Salud"; en API/código se conserva el alias técnico
DOCTORydoctor_profiles.
Alcance V1: Creación de cuenta, validación por token, emisión de sesión post-verify, Google Auth y perfiles polimórficos (patient/doctor).
Fuera de alcance V1 (V1.1): Endpoints legacy de Google (/api/v1/auth/google/*).
Referencia de alcance congelado: ../04-Marco-Metodologico/32-contratos-registro-autenticacion-v1.md.
1. Definición y Propósito
El módulo de Registro gestiona el ciclo de vida inicial del usuario. Está diseñado bajo una arquitectura Onboarding-First: se garantiza la veracidad de la identidad del usuario antes de permitir la captura de datos densos de perfil.
- Contexto: El usuario necesita crear una identidad segura para interactuar con el ecosistema de salud.
- Valor de Negocio: Garantiza un directorio de alta fidelidad mediante la validación previa de correos y la auditoría posterior de credenciales médicas/legales.
2. Lógica Visual y de Procesos
2.1 Flujo Lógico (Miro)
Define las bifurcaciones y validaciones de identidad.
Resumen textual (fallback)
- Paso 1: REG-200 captura email/password (o Google) → crea usuario UNVERIFIED con rol inicial
PATIENT→ envía token 6 dígitos (15 min). - Paso 2: REG-300 valida token (5 intentos, cooldown 60s) → marca verified.
- Paso 3: Perfil básico común (nombre, país, teléfono requerido).
- Paso 4: Upgrade opcional desde dashboard:
- “Soy profesional” → crea
doctor_profileenPENDINGy añade rolDOCTOR. - “Crear entidad” → crea
health_entityenPENDINGy añade rolENTITY_ADMIN. - Afiliaciones y aprobación se gestionan después.
- “Soy profesional” → crea
- Paso 5: Redirección post‑signup: si solo es paciente, enviar a Home/Buscador (o dashboard paciente). Mostrar CTA persistente “Convertirme en profesional / Crear entidad” para elevar roles cuando quiera, sin bloquear la experiencia de paciente.
Snapshot (offline)
Dónde se guardan los datos comunes: nombre, apellidos, país, idioma y fecha de nacimiento se almacenan en user_profiles (1 a 1 con users). Los roles adicionales (DOCTOR, ENTITY_ADMIN) añaden datos específicos en sus propias tablas sin duplicar la identidad base.
2.2 Prototipo de Alta Fidelidad (Figma)
Referencia visual oficial para espaciados, estilos y componentes de UI.
2.3 Campos requeridos por rol
- Datos comunes (siempre en
user_profiles): nombre, apellidos, email (precargado), teléfono, fecha de nacimiento, género, país/geografía, idioma, términos y condiciones. - Paciente (sin datos extra obligatorios): mismos datos comunes; opcional seguro primario, dependientes, ubicaciones frecuentes, historial básico.
- Profesional: datos comunes + colegiatura, especialidad, documentos; queda en
PENDING. - Gestor de entidad: datos comunes + crea entidad con: nombre comercial, razón social, email, teléfono, dirección, geografía, horarios, servicios, aceptación de términos de entidad; estado
PENDING.
3. Actores y Permisos (RBAC)
| Actor | Responsabilidad / Permiso |
|---|---|
| Usuario Invitado | Puede registrarse mediante Email o Google. Debe validar identidad para proceder. |
| Paciente | Crea perfil personal, vincula su seguro primario y dependientes familiares. |
| Profesional | Captura colegiado y especialidades. Su perfil es invisible hasta ser auditado. La afiliación/creación de sede se realiza posteriormente. |
| Plataforma Admin | Responsable de auditar colegiados médicos y documentos legales de entidades. |
4. Reglas de Negocio (Business Rules)
- BR-01 (Unicidad): No se permiten duplicados de
email,license_number(médicos). El rol inicial siempre incluyePATIENT; roles adicionales se agregan sin duplicar usuarios. - BR-02 (Token Lifecycle): El token de verificación por email expira en 15 minutos. Solo el último token generado es válido.
- BR-03 (Google Shortcut): El registro vía Google marca automáticamente el correo como verificado y salta la pantalla de completar perfil (REG-400).
- BR-04 (Onboarding Persistence): Si un usuario abandona el flujo tras validar su correo pero antes de elegir rol, el sistema lo forzará a retomar en REG-400 tras su siguiente login.
- BR-05 (Auditoría): Todo registro exitoso debe capturar
registration_ipy el consentimiento explícito de términos y condiciones (timestamp).
5. Diccionario UX-Técnico por Pantalla
REG-100: Bienvenida
- Objetivo: Punto de entrada al flujo.
- Acción: Inicializa el objeto de registro en el estado local.
REG-200: Credenciales Iniciales
- Acción Técnica:
POST /api/v1/auth/register. Crea usuario en estadoUNVERIFIED.
| Elemento UI | ID Técnico (API) | Validación | Comportamiento en Error |
|---|---|---|---|
| Input Correo | email | Regex Email / Único | Mensaje: "Correo ya registrado" |
| Input Contraseña | password | Min 8 carac, 1 Mayús, 1 Núm | Mensaje: "Contraseña débil" |
| Input Repetir Contraseña | password | Min 8 carac, 1 Mayús, 1 Núm | Mensaje: "Contraseña no coincide" |
REG-300: Verificación (Token)
- Acción Técnica:
POST /api/v1/auth/token/verify. - Lógica: Bloqueo de 60s para solicitar re-envío. 5 intentos fallidos bloquean el proceso por 30 min.
- Resultado esperado: emite sesión vía cookies
HttpOnly(accessToken,refreshToken), conSecure/SameSitesegún entorno.
REG-400: Selección de Perfil
- Acción: El usuario selecciona el rol. Define la bifurcación a los perfiles REG-500 o REG-600.
REG-500: Perfil de Paciente
| Campo UI | ID Técnico (API) | Tipo de Input | Validación | Comportamiento / Origen |
|---|---|---|---|---|
| Nombre | first_name | Texto | Requerido / Solo letras | - |
| Apellido | last_name | Texto | Requerido / Solo letras | - |
| Fecha de Nac. | birth_date | DatePicker | Requerido / No mayor a hoy | Formato YYYY-MM-DD |
| Género | gender_id | Radio/Select | Requerido | Opciones: F / M / Otro |
| No. de Teléfono | phone | Tel. | Requerido/ 8 dígitos (GT) | Dispara OTP en fase 2 |
| País | country_id | Select | Requerido | Carga lista de países |
| Departamento | state_id | Select | Requerido | Depende de country_id |
| Municipio | city_id | Select | Requerido | Depende de state_id |
REG-600: Captura de datos
| Pantalla | Rol | Validación Crítica |
|---|---|---|
| REG-600 | Profesional | license_number único, Especialidad obligatoria y professional_prefix requerido para mostrar perfil público. |
Campos mínimos REG-600 (Profesional)
| Campo | ID técnico | Tipo | Validación |
|---|---|---|---|
| Prefijo profesional | professional_prefix | Select | Requerido. Valores sugeridos: DR, DRA, ENF, LIC, ODONT, PSIC, NUT, FISIO, QF, TEC. |
| Número de colegiado | license_number | Texto | Requerido, único. |
| Especialidad principal | specialty_id | Select | Requerido, FK válida. |
6. Acciones Técnicas y Eventos (Backend)
- Persistencia: Inserción en
users+user_profiles(datos comunes). Perfiles específicos solo si aplica:doctor_profiles(cuando se declare profesional) y relación con entidades desde el dashboard. La creación/afiliación de sedes se hace después en el dashboard profesional. - Roles acumulativos: todo usuario inicia con rol
PATIENT; al declararse profesional/gestor se añaden rolesDOCTORy/oENTITY_ADMINsin perder el rol paciente. - Auditoría: cambios a
user_profilesy upgrades de rol deben emitir eventosUSER_PROFILE_UPDATED/ROLE_GRANTEDconchanged_by, timestamp y origen (IP/UA). - Redirección post-signup:
- Paciente: redirigir a home/buscador (CTA secundario para completar perfil).
- Gestor/Profesional: redirigir a dashboard de profesional/entidad con wizard para crear entidad o declararse profesional.
- Notificaciones:
- Disparo de Email con Token (REG-200).
- Email de bienvenida tras éxito (REG-Success).
- Notificación interna al Admin para auditoría (REG-600).
- Auditoría: Escritura en el log de sistema:
user_id,event: REGISTER_SUCCESS,ip_address,accepted_terms_version.
7. Especificaciones Técnicas (Contratos de API)
El registro utiliza una lógica de Onboarding por Pasos. El primer paso crea la identidad base; los pasos siguientes completan la data según el rol.
Implementación Backend (Go, DDD + Clean Architecture):
- Handlers HTTP en
interfaces/httpmapean DTOs de estos contratos a use casesRegisterUser,VerifyOtp,ResendOtp. - Use cases viven en
application/auth; repositorios (UserRepo,OtpRepo) son interfaces ahí; las implementaciones están eninfrastructure/persistence(Postgres/Redis). - Entidades de dominio no dependen de structs de persistencia; DTOs de OpenAPI se mantienen en la capa de interfaz.
- Nomenclatura y estructura completas: ver
arquitectura-y-despliegue.md§7.1.
Endpoints de Registro y Sesión
Base path: /api/v1
| Recurso | Método | Descripción |
|---|---|---|
/api/v1/auth/register | POST | Crea usuario UNVERIFIED (email + password). 422 si datos inválidos, 409 si email duplicado. |
/api/v1/auth/token/verify | POST | Verifica token de 6 dígitos, activa cuenta y emite sesión vía cookies accessToken/refreshToken. 401 si token inválido/expirado. |
/api/v1/auth/token/resend | POST | Reenvía token (cooldown 60s). |
Parámetros exactos de seguridad (AUTH-CTR-004/005)
| Control | Endpoint(s) | Valor exacto |
|---|---|---|
| TTL OTP | /api/v1/auth/register, /api/v1/auth/token/verify, /api/v1/auth/token/resend | 900s (15 min) |
| Intentos máximos OTP por challenge | /api/v1/auth/token/verify | 5 intentos |
| Bloqueo por intentos OTP agotados | /api/v1/auth/token/verify | 1800s (30 min) |
| Cooldown de reenvío OTP | /api/v1/auth/token/resend | 60s |
| Reenvíos OTP máximos | /api/v1/auth/token/resend | 3 solicitudes por 900s (15 min) por email+ip |
| Rate limit registro | /api/v1/auth/register | 5 solicitudes por 900s (15 min) por email+ip |
| Rate limit verify | /api/v1/auth/token/verify | 5 solicitudes por 900s (15 min) por email+ip |
| Access token TTL post-verify | /api/v1/auth/token/verify | 900s (15 min) |
| Refresh token TTL post-verify | /api/v1/auth/token/verify | 604800s (7 días) en cookie HttpOnly; Secure/SameSite por entorno (local: false/Lax, prod: true/Strict) |
| Política de refresh reuse | /api/v1/auth/refresh (aplica a sesión emitida en verify) | 409 + REFRESH_REUSE; revocar todos los refresh tokens; invalidar todas las sesiones; forzar re-login; registrar evento REFRESH_REUSE; captcha en el siguiente login |
Códigos de error (resumen)
| Endpoint | 400 | 401 | 409 | 422 |
|---|---|---|---|---|
/auth/register | - | - | Email duplicado | Datos inválidos |
/auth/token/verify | - | Token inválido/expirado | - | Formato inválido |
/auth/token/resend | - | - | - | Formato inválido/cooldown |
Endpoints de Perfil (Post-Registro)
| Recurso | Método | Datos Esperados |
|---|---|---|
/api/v1/profiles/doctor | PATCH | professional_prefix, license_number, specialty_id, education_json; 409 si colegiado duplicado. |
/api/v1/profiles/patient | PATCH | insurance_id, phone, birth_date. |
Ejemplos de Requests/Responses
- Register
Request:{ "email": "user@mail.com", "password": "Secret123" }
201:{ "status": "success", "user_id": "uuid" }
409:{ "message": "Correo ya registrado" } - Verify
Request:{ "email": "user@mail.com", "code": "123456" }
200:{ "status": "success" }
401/422:{ "message": "Token inválido o expirado" }
Contrato completo: ver /swagger (landing), /swagger.html (Swagger UI) y /openapi.yaml (YAML).
Catalogo de errores obligatorio (canonico)
Registro debe reutilizar el catalogo canonico definido en 11-swagger-ui.md.
| Escenario | Codigo canonico | HTTP |
|---|---|---|
| Correo ya registrado | CONFLICT | 409 |
| Token invalido o expirado | UNAUTHORIZED | 401 |
| Datos de perfil incompletos | VALIDATION_ERROR | 422 |
| Reintentos excedidos (OTP/register) | RATE_LIMITED | 429 |
| Error no controlado | INTERNAL_ERROR | 500 |
Ejemplo de Body (Registro Profesional de Salud)
{
"email": "clinica.central@med.com",
"password": "-",
"role": "DOCTOR",
"metadata": {
"first_name": "Juan",
"last_name": "Pérez",
"professional_prefix": "DR",
"license_number": "12345",
"primary_specialty": "id-cardio"
}
}
8. Casos de Borde y Manejo de Errores (QA)
Esta sección define el comportamiento del sistema ante situaciones excepcionales, asegurando que el equipo de QA tenga criterios claros de prueba y el Backend capture las excepciones correctamente.
| Escenario de Error | Causa Técnica | Acción del Sistema | Mensaje para el Usuario (UX) |
|---|---|---|---|
| Token Expirado | Han pasado >15 min desde la generación del código en REG-200. | Invalida el token en Redis/DB y muestra opción de re-envío. | "El código ha expirado. Por seguridad, solicita uno nuevo." |
| Email Duplicado | Intento de registro con correo ya existente en la tabla users. | Bloquea la creación del registro en REG-200. | "Este correo ya está registrado. ¿Deseas iniciar sesión?" |
| ID Duplicado (Médico/Entidad) | license_number o tax_id ya existen en sus respectivas tablas. | Bloquea el PATCH de perfil en REG-600/700. | "Este identificador ya está vinculado a otra cuenta médica/legal." |
| Abandono de Flujo | El usuario cierra la sesión tras validar token pero sin elegir perfil. | Al re-ingresar (Login), el sistema detecta role_id NULL y fuerza retorno a REG-400. | "Completa tu perfil para poder continuar." |
| Falla en Proveedor de Email | El servicio SMTP o API de correos no responde. | Registra error en logs y permite re-intento tras 30s. | "No pudimos enviar el código. Reintenta en unos segundos." |
| Google Auth sin Email | La cuenta de Google no tiene un email público asociado. | Cancela el flujo de Google y solicita registro manual. | "No pudimos obtener tu correo de Google. Por favor, regístrate manualmente." |
9. Mermaid: Flujo de Navegación
Este diagrama representa la navegación entre las pantallas de Figma (REG-XXX) y los puntos de decisión lógica.
10. Secuencia de Registro (referencial)
11. Requerimientos No Funcionales (NFR)
- P95 por paso: REG-200 < 300ms (sin envío), REG-300 < 350ms, REG-400 < 200ms.
- OTP delivery rate > 98% en < 30s; reintentos máximo 3.
- Tasa de finalización (verify → rol) objetivo > 80%.
- Logs y trazas con
trace_id,user_id,email,ipen eventos de registro.
11.1 SLIs/SLOs y Alertas
| Métrica | SLO | Alerta |
|---|---|---|
register_p95 | < 300ms | Warn > 400ms 5m |
verify_p95 | < 350ms | Warn > 450ms 5m |
otp_delivery_success | > 98% en <30s | Warn < 95% o latencia >45s |
conversion_verify_to_role | > 80% | Crit < 70% |
duplicate_email_rate | < 2% | Warn > 5% |
12. Checklist de Seguridad
- OTP/token siempre hashed en BD; solo el último token OTP emitido es válido.
- Valores exactos de TTL, cooldown, intentos y rate limits: ver tabla "Parámetros exactos de seguridad (AUTH-CTR-004/005)".
- Invalidar refresh tokens previos al reset de password/verify y rotar tras la primera verificación exitosa.
- No incluir PHI/PII en logs; mascarar email/phone en mensajes de error.
- CORS restringido a dominios oficiales; cookies de sesion (
accessToken,refreshToken) enHttpOnlyySecure/SameSitepor entorno. - Detectar reuse de refresh token post-verify y forzar re-login.
13. Pendientes y Notas Adicionales
13.1 UX/UI
- Validación de Pantallas: Confirmar si REG-600 requiere múltiples pasos (Stepper) si el número de campos aumenta.
- Mobile Responsive: Revisar que la tabla de selección de perfiles (REG-400) se adapte correctamente a una sola columna en dispositivos móviles.
13.2 Ingeniería y Seguridad
- Cifrado de Token: Asegurar que el token de 6 dígitos se guarde con un hash temporal en la base de datos y no en texto plano.
- Rate Limiting: Implementar un límite de peticiones al endpoint
/auth/registerpor IP para evitar ataques de denegación de servicio o spam de cuentas. - Auditoría Legal: Confirmar que el texto de "Términos y Condiciones" en REG-200 cubra explícitamente el manejo de datos sensibles según la legislación regional.
13.3 Documentación Relacionada
- Modelo de Base de Datos: Ver Esquema de DB para la estructura de las tablas
usersyprofiles. - Glosario: Ver Definiciones para entender los términos "Colegiado", "NIT" y "Entidad".
14. Criterios de Aceptación por Paso
| Paso | Criterios de Aceptación (CA) |
|---|---|
| REG-200 | Valida email único, password cumple reglas; muestra error inline; crea usuario UNVERIFIED y dispara OTP en menos de 30s. |
| REG-300 | Acepta solo último token; 5 intentos máx; bloquea 30 min tras 5 fallos; mensaje genérico de error. |
| REG-400 | Solo roles Paciente/Profesional; botón continuar deshabilitado si no hay selección. |
| REG-500 | Campos requeridos (nombre, apellido, birth_date, género, phone, geo); errores bajo cada campo; formatea fechas a YYYY-MM-DD. |
| REG-600 | Requiere license_number y especialidad; marca perfil en PENDING_VALIDATION; no publica en buscador. |
15. Checklist de QA / Testing
- Registro éxito (email/password) → verify → rol → perfil profesional/paciente.
- Token expirado → 401/422 esperado.
- Rate-limit register (5 intentos/15min) → devuelve 429/captcha.
- Google Auth sin email → bloquea y solicita registro manual.
- Duplicado de email/licencia → 409 con mensaje.
- Logs incluyen
trace_id,user_id,ip. - Refresh token rotation tras verify; reuse detectado → sesión invalidada.
- Captcha adaptativo se dispara tras múltiples fallos de OTP o register.
16. Variables de Entorno (Front)
API_BASE=https://api.example.com/api/v1- Usar cliente HTTP con
credentials: includepara enviar cookies HttpOnly. - El frontend debe operar con cookies HttpOnly (
credentials: include) y no persistir tokens en storage.
17. Accesibilidad (A11y)
- Campos OTP con
aria-labely foco automático secuencial. - Estados de error con texto y color contrastado (AA) y
aria-livepara mensajes. - Navegación por teclado completa; indicador de foco visible.
18. Control de Abuso/Fraude
- Bloqueo por IP/email tras 5 intentos fallidos en verify; captcha requerido.
- Rechazar dominios de email desechables conocidos (lista configurable).
- Registrar
device_fingerprintopcional para monitoreo de abuso (sin bloquear flujo). - Detectar reuse de refresh token post-verify y forzar re-login.
18.1 Uso de Captcha / reCAPTCHA
- Cuándo dispararlo:
- Registro: tras 5 intentos fallidos en
/auth/registero patrones de bot (mismo IP + múltiples correos). - Verify OTP: tras 5 códigos fallidos o más de 3 reenvíos en 15 min.
- Resend token: si el cooldown se viola repetidamente.
- Registro: tras 5 intentos fallidos en
- Cómo validarlo:
- Front envía
captcha_tokenenX-Captcha-Token; backend valida con el proveedor y bloquea si score < 0.5.
- Front envía
- UX: mensaje claro “Completa la verificación para continuar”; mantener email y campos persistidos.
- Observabilidad: registrar
captcha_required,captcha_passed, score y motivo (register,verify,resend).
19. Fallback de Proveedor de Email
- Retries exponenciales (3 intentos) y cola de notificaciones; si falla email, ofrecer reenviar pasado cooldown.
- Alertar a soporte si
otp_delivery_successcae por debajo de 95% en 15 min. - Fallback SMTP/SES si el proveedor principal falla; registrar incidente.
20. Métricas de Producto (Funnel)
| Paso | Evento | Objetivo |
|---|---|---|
| Inicio registro | REGISTER_STARTED | 100% base |
| OTP enviado | OTP_SENT | 98% |
| OTP verificado | OTP_VERIFIED | >= 80% |
| Rol seleccionado | ROLE_SELECTED | >= 80% |
| Perfil completo (profesional/paciente) | PROFILE_COMPLETED | >= 70% |
21. Enlaces y Trazabilidad
- Swagger UI:
/swagger.html(acceso desde/swagger) y contrato YAML en/openapi.yaml. - Matriz de trazabilidad: ver
- Observabilidad (SLIs/SLOs): en este doc y
arquitectura-y-seguridad.md(5.8)