Saltar a contenido

21 — Sistema de invitaciones pre-launch

Por qué está incluido

Este feature es value-add real del SaaS framework. Permite al comprador lanzar con beta cerrada (waitlist) y pasar a registro abierto con un toggle — sin escribir código.

"Lanza con waitlist o abre registro público cambiando un switch. Códigos de invitación, panel de aprobación, 3 emails en 5 idiomas — built-in."

Costo si el comprador lo tuviera que construir: 1-2 semanas. Aquí ya está.

Modos de operación

Modo Comportamiento
Pre-launch OFF (default) Registro abierto en /signup (solo requiere código prelaunch si lo configuras en el gate)
Pre-launch ON Formulario de solicitud de invitación; superadmin aprueba/rechaza

Toggle: POST /api/sa/prelaunch-mode/ (superadmin) o SystemSetting(key='prelaunch_mode').

Flujo completo

Visitante → /signup (prelaunch ON)
    ├─ Ve formulario "Solicitar invitación"
    │     POST /api/auth/invitation-request/
    │       { email, full_name, company, locale, ... }
    ├─ Email #1: "Recibimos tu solicitud" (idioma del formulario)
Superadmin → /superadmin/prelaunch
    ├─ Aprueba → genera código + Email #2: "Tu código: XXXX" (locale de la solicitud)
    └─ Rechaza → Email #3: "Solicitud no aprobada" (locale de la solicitud)
Visitante → /signup?invitation_code=XXXX
    └─ Registro normal → Email verificación (locale del signup)

Endpoints

Públicos

Método Endpoint Descripción
POST /api/auth/invitation-request/ Enviar solicitud (rate limit: 3/h por IP)
GET /api/auth/prelaunch-status/ { "enabled": true/false }

Superadmin

Método Endpoint Descripción
GET /api/sa/invitation-requests/ Lista solicitudes pendientes
GET /api/sa/invitation-requests/<id>/ Detalle
POST /api/sa/invitation-requests/<id>/action/ { "action": "approve" \| "reject" }
POST /api/sa/prelaunch-mode/ Toggle ON/OFF
GET /api/sa/prelaunch-codes/ Lista códigos generados

Modelos de datos

invitation_requests

id, email, full_name, company_name, locale, status (pending|approved|rejected),
ip_address, user_agent, created_at, reviewed_at, reviewed_by

prelaunch_codes

code (varchar unique), active, used_count, created_at, created_by, request_id (FK)

Emails (3)

Implementados en authentication/emails_invitation.py. Todos usan el locale de la solicitud (campo del formulario, no el del superadmin).

Email Función Cuándo
Confirmación recepción send_invitation_request_confirmation() Tras POST invitation-request
Código aprobado send_invitation_code_email() Superadmin approve
Rechazo send_invitation_request_rejected_email() Superadmin reject

El código aprobado incluye link: {FRONTEND_URL}/signup?invitation_code={code}.

Frontend

  • Dashboard signup: SignupPage.tsx — envía locale desde i18n al registrarse.
  • Superadmin: InvitationsPage.tsx — lista, aprueba, rechaza.
  • El formulario de solicitud de invitación debe incluir campo locale (usar idioma actual de i18n).

Seguridad

  • Rate limit: 3 solicitudes/hora por IP en invitation-request.
  • Honeypot field en el serializer (bots no pasan).
  • Deduplicación: no crea otra solicitud pending si ya existe una para el mismo email.

Cómo activar en tu deploy

  1. Superadmin → Pre-launch → activar modo.
  2. Opcional: sembrar códigos iniciales en prelaunch_codes.
  3. El frontend de signup detecta GET /api/auth/prelaunch-status/ y muestra el formulario de waitlist.

Cómo desactivar (registro abierto)

  1. Superadmin → Pre-launch → desactivar.
  2. /signup vuelve al flujo normal de registro.

No hay que tocar código ni redeploy — solo el toggle.

Extender

Para añadir campos al formulario de solicitud:

  1. Añade columna o usa JSON en invitation_requests.
  2. Actualiza InvitationRequestCreateSerializer.
  3. Actualiza el frontend del signup/waitlist form.
  4. Opcional: incluye el dato en el email de confirmación.