[
  {
    "id": "EMAIL-001",
    "name": "Startup Welcome",
    "fn": "sendStartupWelcomeEmail",
    "trigger": "Registro de startup en /registro-startup (formulario completado)",
    "dest": "Email del CEO que registra la startup",
    "cta": "Confirmar mi cuenta y ver mi registro → /auth/confirm (magic link Supabase)",
    "condiciones": "Se envía siempre al completar el registro. La startup queda en estado \"pendiente\" hasta que el CEO confirme. Si no confirma en 7 días → se activan EMAIL-003, EMAIL-004 y eventualmente EMAIL-005.",
    "tyc": "SÍ — el formulario de registro (/registro-startup) tiene checkbox obligatorio de TyC y Política de Tratamiento de Datos ANTES de enviar. El consent se graba en consent_log con flow=\"FS\". El CTA del correo (confirmar cuenta) NO vuelve a pedir TyC porque ya se aceptaron en el formulario."
  },
  {
    "id": "EMAIL-002",
    "name": "Startup Followup Score",
    "fn": "sendStartupFollowupEmail",
    "trigger": "Cron automático /api/cron/startup-followup (~2 días después del registro, si score < 100)",
    "dest": "Email del CEO de la startup",
    "cta": "Aumentar mi score → /dashboard (perfil de la startup)",
    "condiciones": "Solo se envía si: (1) la startup está confirmada (email_confirmed=true), (2) el score es menor a 100, (3) han pasado ~2 días desde el registro. No se envía si la startup ya tiene score 100 o si fue eliminada.",
    "tyc": "NO — el CTA lleva al dashboard. El usuario ya aceptó TyC durante el registro (EMAIL-001). No se requiere nueva aceptación."
  },
  {
    "id": "EMAIL-003",
    "name": "Startup Reminder (día 3)",
    "fn": "sendStartupReminderEmail (isUrgent=false)",
    "trigger": "Cron /api/cron/startup-welcome-reminders — día 3 sin confirmar email",
    "dest": "Email del CEO de la startup",
    "cta": "Confirmar mi cuenta → /auth/confirm (magic link)",
    "condiciones": "Se envía si: (1) la startup lleva 3 días sin confirmar email, (2) NO ha sido eliminada. Muestra días restantes (4 días). Si el CEO confirma antes del día 6, no se envía EMAIL-004.",
    "tyc": "NO — el CTA es confirmar la cuenta (magic link). TyC ya fueron aceptados en el registro (EMAIL-001). No se requiere nueva aceptación."
  },
  {
    "id": "EMAIL-004",
    "name": "Startup Reminder URGENTE (día 6)",
    "fn": "sendStartupReminderEmail (isUrgent=true)",
    "trigger": "Cron /api/cron/startup-welcome-reminders — día 6 sin confirmar email",
    "dest": "Email del CEO de la startup",
    "cta": "Confirmar mi cuenta → /auth/confirm (magic link)",
    "condiciones": "Se envía si: (1) la startup lleva 6 días sin confirmar, (2) NO confirmó tras EMAIL-003. Incluye banner urgente amarillo \"tu cuenta expira en menos de 24 horas\". Si no confirma → día 8 se purga (EMAIL-005).",
    "tyc": "NO — mismo caso que EMAIL-003. TyC ya aceptados en registro."
  },
  {
    "id": "EMAIL-005",
    "name": "Startup Purged (expiración)",
    "fn": "sendStartupPurgedEmail",
    "trigger": "Cron /api/cron/startup-welcome-reminders — día 8+ sin confirmar",
    "dest": "Email del CEO de la startup",
    "cta": "Registrarme de nuevo → /registro-startup",
    "condiciones": "Se envía si: (1) pasaron 7+ días sin confirmar, (2) NO hay miembros del equipo con permiso de edición que ya hayan confirmado (regla LAP-336: \"si al menos un editor confirmó, la startup NO se purga\"). La startup se marca como eliminada con delete_scheduled_for = 30 días.",
    "tyc": "NO — el CTA es re-registrarse. Si se registra de nuevo, se pedirán TyC en el nuevo formulario de registro."
  },
  {
    "id": "EMAIL-006",
    "name": "Contact Welcome (usuario nuevo)",
    "fn": "sendContactWelcomeEmail (userExists=false)",
    "trigger": "ICG registra contacto de compañía en /registro-icg o /dashboard/icg/nuevo — el contacto NO tiene cuenta LPDI",
    "dest": "Email del contacto designado por el ICG",
    "cta": "Establecer nueva contraseña → /auth/reset (recovery link Supabase)",
    "condiciones": "Se envía cuando: (1) el ICG designa un contacto durante registro, (2) el email del contacto NO existe como usuario en Supabase Auth. Se crea cuenta automática con contraseña temporal visible en el correo. Variante: si isNewIcg=false, dice \"ha actualizado su perfil\" en vez de \"se ha registrado\".",
    "tyc": "SÍ — aunque el correo no incluye checkboxes, el flujo destino (/auth/reset-password) detecta 0 registros en consent_log y muestra checkboxes obligatorios de TyC y Tratamiento de Datos. El contacto NO puede operar sin aceptar. Backup: guard en /dashboard redirige a /aceptar-terminos si no hay consent."
  },
  {
    "id": "EMAIL-007",
    "name": "Contact Welcome (usuario existente)",
    "fn": "sendContactWelcomeEmail (userExists=true)",
    "trigger": "ICG registra contacto de compañía — el contacto YA tiene cuenta LPDI",
    "dest": "Email del contacto designado por el ICG",
    "cta": "Ver mi registro → /dashboard",
    "condiciones": "Se envía cuando: (1) el ICG designa un contacto, (2) el email del contacto ya existe como usuario en Supabase Auth. NO se muestra contraseña temporal (ya tiene cuenta). El botón lleva directo al dashboard.",
    "tyc": "NO — el usuario ya tiene cuenta y ya aceptó TyC previamente. Guard en /dashboard verifica consent_log como red de seguridad."
  },
  {
    "id": "EMAIL-008",
    "name": "CEO Welcome (usuario nuevo)",
    "fn": "sendCeoWelcomeEmail (userExists=false)",
    "trigger": "Registro de startup → el email del CEO NO existe como usuario en Supabase Auth",
    "dest": "Email del CEO designado durante registro de startup",
    "cta": "Confirmar mi cuenta y ver mi registro → /auth/confirm (recovery link)",
    "condiciones": "Se envía cuando el registrante de la startup designa un CEO cuyo email no tiene cuenta en LPDI. Incluye contraseña temporal visible. Solo ocurre cuando el CEO es persona distinta al registrante.",
    "tyc": "NO — el correo NO incluye aceptación de TyC. ⚠️ HALLAZGO: Si el CEO es persona distinta al registrante, recibe credenciales sin aceptar TyC explícitamente. Los TyC los aceptó el registrante, no el CEO. El consent del CEO se graba como parte del flow del registrante."
  },
  {
    "id": "EMAIL-009",
    "name": "CEO Welcome (usuario existente)",
    "fn": "sendCeoWelcomeEmail (userExists=true)",
    "trigger": "Registro de startup → el email del CEO YA existe como usuario",
    "dest": "Email del CEO",
    "cta": "Ver mi registro → /dashboard",
    "condiciones": "Se envía cuando el CEO designado ya tiene cuenta LPDI. No se muestra contraseña. Botón directo al dashboard.",
    "tyc": "NO — el CEO ya tiene cuenta y aceptó TyC previamente."
  },
  {
    "id": "EMAIL-010",
    "name": "Team Invitation (usuario nuevo + TyC)",
    "fn": "sendTeamInvitationEmail (userExists=false, requiresTyC=true)",
    "trigger": "Un miembro con privilegio de edición agrega miembro en Panel 6 → el email NO existe como usuario + NO tiene consent previo",
    "dest": "Email del miembro invitado (ingresado por quien tiene privilegio de edición)",
    "cta": "Confirmar mi vinculación (verde) / No hago parte de la compañía (rojo)",
    "condiciones": "Se envía cuando: (1) un miembro con privilegio de edición agrega miembro desde Panel 6, (2) el email no tiene cuenta LPDI, (3) no tiene entradas en consent_log. Muestra tabla con datos registrados (nombre, email, cargo, permiso edición). Incluye bloque TyC si requiresTyC=true.",
    "tyc": "SÍ — el flujo de confirmación incluye checkboxes obligatorios de TyC y Tratamiento de Datos que el usuario debe marcar explícitamente antes de confirmar su vinculación. El consent se graba en consent_log con flow=\"team_invitation\"."
  },
  {
    "id": "EMAIL-011",
    "name": "Team Invitation (usuario existente)",
    "fn": "sendTeamInvitationEmail (userExists=true)",
    "trigger": "Un miembro con privilegio de edición agrega miembro en Panel 6 → el email YA existe como usuario",
    "dest": "Email del miembro invitado al equipo",
    "cta": "Confirmar mi vinculación (verde) / No hago parte de la compañía (rojo)",
    "condiciones": "Se envía cuando: (1) un miembro con privilegio de edición agrega miembro, (2) el email ya tiene cuenta LPDI. NO muestra bloque TyC porque requiresTyC se calcula como false (ya tiene consent previo en consent_log). Muestra datos registrados.",
    "tyc": "NO — el usuario ya aceptó TyC previamente (tiene entradas en consent_log). El sistema consulta consent_log antes de enviar y omite el bloque de TyC si ya existe consent."
  },
  {
    "id": "EMAIL-012",
    "name": "Team Welcome CON edición",
    "fn": "sendTeamWelcomeWithEditEmail",
    "trigger": "Miembro hace clic en \"Confirmar mi vinculación\" + tiene canEdit=true",
    "dest": "Email del miembro que confirmó su vinculación",
    "cta": "Establecer nueva contraseña → /auth/reset (recovery link)",
    "condiciones": "Se envía solo si: (1) el miembro confirmó vía EMAIL-010/011, (2) el CEO le otorgó permiso de edición (canEdit=true). Incluye credenciales de acceso y nota \"tu CEO te otorgó permisos para editar\".",
    "tyc": "NO — TyC ya fueron aceptados en EMAIL-010 (si era usuario nuevo) o en su registro original (si era existente). El consent ya quedó grabado."
  },
  {
    "id": "EMAIL-013",
    "name": "Team Welcome SIN edición",
    "fn": "sendTeamWelcomeNoEditEmail",
    "trigger": "Miembro confirma vinculación + tiene canEdit=false",
    "dest": "Email del miembro que confirmó su vinculación",
    "cta": "Establecer nueva contraseña → /auth/reset (recovery link)",
    "condiciones": "Idéntico a EMAIL-012 pero para miembros sin permiso de edición (canEdit=false). La nota dice \"solo tu CEO o a quien éste haya autorizado puede editar\".",
    "tyc": "NO — mismo caso que EMAIL-012. TyC ya aceptados previamente."
  },
  {
    "id": "EMAIL-014",
    "name": "Rechazo de invitación (confirmación al miembro)",
    "fn": "sendTeamRejectionConfirmationEmail",
    "trigger": "Miembro hace clic en \"No hago parte de la compañía\" desde EMAIL-010/011",
    "dest": "Email del miembro que rechazó la invitación",
    "cta": "Confirmar mi vinculación (si fue error) → enlace de confirmación original",
    "condiciones": "Se envía inmediatamente tras el rechazo. Incluye botón de \"segunda oportunidad\" para confirmar si fue error, pero con confirmAgainUrl=null el botón no aparece. El enlace hereda la expiración de 7 días del email original.",
    "tyc": "NO — es un correo informativo de confirmación de rechazo. No requiere aceptación de nada."
  },
  {
    "id": "EMAIL-015",
    "name": "Notificación al CEO: miembro confirmó",
    "fn": "sendCeoMemberConfirmationEmail",
    "trigger": "Miembro acepta invitación (hace clic en \"Confirmar mi vinculación\")",
    "dest": "Email del CEO que envió la invitación",
    "cta": "Ir al dashboard → /dashboard",
    "condiciones": "Se envía siempre que un miembro confirma. Informa al CEO: quién confirmó, su email, y los permisos asignados (con/sin edición). El CEO puede ver y modificar el equipo desde Panel 6.",
    "tyc": "NO — es un correo informativo al CEO. No requiere acción de aceptación."
  },
  {
    "id": "EMAIL-016",
    "name": "Notificación al CEO: miembro rechazó",
    "fn": "sendCeoMemberRejectionEmail",
    "trigger": "Miembro rechaza invitación (hace clic en \"No hago parte de la compañía\")",
    "dest": "Email del CEO que envió la invitación",
    "cta": "Ir al dashboard → /dashboard",
    "condiciones": "Se envía siempre que un miembro rechaza. Informa al CEO y sugiere comunicarse con la persona si fue un error. El CEO puede volver a invitar desde Panel 6.",
    "tyc": "NO — es un correo informativo al CEO."
  },
  {
    "id": "EMAIL-017",
    "name": "Cuenta de usuario eliminada",
    "fn": "sendAccountDeletedEmail",
    "trigger": "Usuario elimina su cuenta desde /api/account/delete",
    "dest": "Email del usuario que eliminó su cuenta",
    "cta": "Registrarme de nuevo → eco.lpdi.co",
    "condiciones": "Se envía a TODOS los usuarios asociados a la cuenta cuando se ejecuta la eliminación. La eliminación es voluntaria (el usuario la inicia). Los datos se marcan para eliminación.",
    "tyc": "NO — es un correo informativo de confirmación de eliminación. Si se registra de nuevo, se pedirán TyC en el nuevo registro."
  },
  {
    "id": "EMAIL-018",
    "name": "Entidad eliminada (notificación a asociados)",
    "fn": "sendEntityDeletedEmail",
    "trigger": "Usuario elimina startup o ICG desde /api/entities/delete",
    "dest": "TODOS los miembros asociados a la entidad (CEO, equipo, contacto)",
    "cta": "Restaurar → /dashboard (sección papelera)",
    "condiciones": "Se envía a todos los emails asociados a la entidad eliminada. Incluye quién dio la orden de eliminar (deletedBy, campo LAP-336). Informa que los datos se eliminan permanentemente en 30 días. El botón \"Restaurar\" lleva a la papelera del dashboard.",
    "tyc": "NO — es un correo informativo. La restauración desde la papelera no requiere nueva aceptación de TyC."
  },
  {
    "id": "EMAIL-019",
    "name": "ICG Purged (expiración automática)",
    "fn": "sendIcgPurgedEmail",
    "trigger": "Cron /api/cron/purge-entities → RPC purge_expired_entities elimina ICGs no confirmados",
    "dest": "Email del contacto y usuarios asociados al ICG",
    "cta": "Registrarme de nuevo → eco.lpdi.co",
    "condiciones": "Se envía cuando el cron de purga elimina un ICG que no fue confirmado en el plazo establecido. Se notifica a todos los emails asociados al ICG (contacto principal + otros usuarios vinculados). La purga se ejecuta vía RPC de Supabase.",
    "tyc": "NO — si se re-registra, se pedirán TyC en el nuevo formulario de registro ICG."
  },
  {
    "id": "AUTH-001",
    "name": "Confirmación de correo (Supabase)",
    "fn": "Supabase Auth — Confirm signup template",
    "trigger": "Supabase Auth dispara tras signup o signInWithOtp",
    "dest": "Email del usuario nuevo",
    "cta": "Confirmar correo → magic link generado por Supabase",
    "condiciones": "Template personalizado en Supabase Dashboard → Auth → Email Templates → Confirm signup. Se envía automáticamente por Supabase cuando se crea un usuario con email/password. El diseño exacto depende de la configuración del template en el dashboard de Supabase.",
    "tyc": "NO — es un correo de verificación de identidad de Supabase. Los TyC se aceptan en el formulario de la aplicación ANTES de que Supabase envíe este correo."
  },
  {
    "id": "AUTH-002",
    "name": "Recuperación de contraseña (Supabase)",
    "fn": "Supabase Auth — Reset password template",
    "trigger": "Usuario solicita reset de contraseña vía /auth/reset",
    "dest": "Email del usuario",
    "cta": "Restablecer contraseña → magic link Supabase",
    "condiciones": "Template personalizado en Supabase Dashboard → Auth → Email Templates → Reset password. Se activa cuando se llama a supabase.auth.resetPasswordForEmail(). El link expira según la configuración de Supabase (por defecto 24h).",
    "tyc": "NO — es una acción de seguridad/recuperación. No requiere aceptación de TyC."
  },
  {
    "id": "AUTH-003",
    "name": "Invitación / Magic Link (Supabase)",
    "fn": "Supabase Auth — Magic link template",
    "trigger": "Admin invita usuario vía supabase.auth.admin.inviteUserByEmail()",
    "dest": "Email del usuario invitado",
    "cta": "Acceder → magic link Supabase",
    "condiciones": "Template personalizado. Se usa cuando un admin invita directamente a un usuario. Actualmente NO se usa en el flujo principal del sistema (las invitaciones van por EMAIL-010/011). Podría usarse para invitaciones administrativas manuales desde Supabase Dashboard.",
    "tyc": "NO — es un magic link de acceso. TyC deberían validarse en la aplicación al llegar, pero actualmente este template no se usa en flujo normal."
  },
  {
    "id": "AUTH-004",
    "name": "Cambio de correo electrónico (Supabase)",
    "fn": "Supabase Auth — Change email template",
    "trigger": "Usuario cambia su email desde configuración de cuenta",
    "dest": "Email nuevo del usuario",
    "cta": "Confirmar nuevo correo → magic link Supabase",
    "condiciones": "Template personalizado. Se activa cuando el usuario cambia su email vía supabase.auth.updateUser({email: nuevo}). Se envía al nuevo email para verificación. El email anterior sigue activo hasta que se confirme el nuevo.",
    "tyc": "NO — es verificación de identidad para cambio de email. No requiere nueva aceptación de TyC."
  }
]