Saltar a contenido
v26.3

Self-Service-Onboarding (arquitectura)

El Self-Service-Onboarding permite a los interesados configurar por sí mismos una instancia en la nube de DiKAS sin contacto comercial — a elección como prueba gratuita (Trial) o directamente como instancia de pago en producción. Esta página describe la arquitectura técnica, la configuración y los mecanismos de seguridad. La perspectiva del usuario final se describe en Registro en línea.

Desactivado por defecto (Dark-Rollout)

El embudo público está protegido mediante el flag SelfServiceSignupEnabled y viene desactivado en el estado de entrega. Mientras el flag sea false, todos los endpoints públicos devuelven 404. Antes de una activación deben cumplirse los puntos indicados en Antes de la activación.

Resumen

El proceso consta de un asistente de frontend público y una serie de endpoints de backend anónimos. El aprovisionamiento propiamente dicho pasa por el mismo ILicenseProvisioningService que también utilizan la vía del portal y la vía de prueba (Trial).

Área Ubicación
Asistente de frontend Ruta /signup (PublicOnboardingWizardComponent, app dikas-web)
Confirmación por enlace mágico Ruta /signup/verify
Endpoints de backend /api/v1/onboarding/public/* y /api/v1/trial/start
Paquete de funciones Dikas.Features.Licensing

El asistente guía a través de siete pasos: PaqueteTSE (nube frente a Swissbit) → Cuenta (correo electrónico, sin contraseña mediante enlace mágico) → Datos de la empresaNombre en línea (subdominio) → Aspectos legales y pagoListo (URL de la instancia y datos de acceso).

Flag de función SelfServiceSignupEnabled

El flag es una propiedad del documento singleton OperationalConfig (ID fija operationalconfig) y solo se puede modificar mediante la base de datos o la interfaz de administración — no existe una variable de entorno para ello.

OperationalConfig.SelfServiceSignupEnabled  (bool, Default: false)

Cada endpoint público llama primero a CheckSelfServiceEnabledAsync() y responde con 404 Not Found mientras el flag sea false. Así, el embudo permanece invisible hasta que se activa de forma deliberada.

Endpoints públicos

Todos los endpoints son [AllowAnonymous] y están protegidos por el flag y por las medidas contra el abuso.

Método y ruta Finalidad
POST /api/v1/onboarding/public/orders Crear un pedido borrador anónimo (devuelve un token de pedido secreto)
PUT /api/v1/onboarding/public/orders/{id} Actualizar el borrador (vinculado al token)
POST /api/v1/onboarding/public/orders/{id}/reserve-name Reservar temporalmente el nombre en línea
POST /api/v1/onboarding/public/register Crear un cliente sin contraseña y enviar el enlace mágico
POST /api/v1/onboarding/public/orders/{id}/bind Vincular el pedido a la cuenta verificada mediante el enlace mágico ([Authorize])
POST /api/v1/onboarding/public/payment/set Crear un SetupIntent/PaymentIntent de Stripe (devuelve ClientSecret)
POST /api/v1/onboarding/public/payment/webhook Webhook de Stripe (confirmación de pago)
POST /api/v1/onboarding/public/orders/{id}/submit Aprovisionar la instancia
GET /api/v1/onboarding/public/payment-config Clave publicable de Stripe para el frontend
POST /api/v1/trial/start Prueba (Trial) directa de autoservicio (sin pedido/cuenta de portal)

Seguridad / anti-abuso

Dado que cada aprovisionamiento genera costes reales (COGS), hay activas varias capas de protección independientes entre sí:

  • Honeypot — un campo de formulario oculto; si se rellena, se rechaza silenciosamente con 202 Accepted (sin aprovisionamiento).
  • Limitador de errores por IP — retardo exponencial, bloqueo tras 10 errores (1 h) o 20 errores (24 h).
  • Cuota de aprovisionamiento por IP y 24 h (MaxPublicProvisionsPerIpPer24h, por defecto 3). Se aplica tanto en el envío público como en el inicio del Trial, y no se reinicia en caso de éxito. Si se supera la cuota, el endpoint responde con 429 (code: SIGNUP_RATE_LIMITED).
  • Cuota de envío de correo por IP y hora (MaxPublicEmailSendsPerIpPerHour, por defecto 5) contra el bombardeo de enlaces mágicos.
  • Enlace mágico en lugar de la confirmación clásica por correo electrónico; al hacer clic se verifica la dirección y se obtiene un JWT del portal con el que se vincula el pedido.
  • IP de cliente real — detrás del Ingress, la IP de origen se determina mediante ForwardedHeaders. Las redes de confianza (KnownNetworks) deben configurarse en el despliegue con el CIDR del clúster; de lo contrario, la cuota por IP deja de funcionar.

Cuotas en memoria

Las cuotas se mantienen en memoria (ventana de tiempo móvil). Con varias instancias detrás de un balanceador de carga, cada instancia cuenta por separado; en ese caso hay que prever una sesión persistente (sticky session) o una caché compartida.

Configuración

Las opciones se cargan desde la sección Onboarding (OnboardingOptions). Todos los valores tienen valores por defecto razonables en el código; se pueden sobrescribir mediante variables de entorno con doble guion bajo.

Clave Por defecto Significado
Onboarding__MaxPublicProvisionsPerIpPer24h 3 Máx. de aprovisionamientos por IP / 24 h (envío + Trial)
Onboarding__MaxPublicEmailSendsPerIpPerHour 5 Máx. de correos de enlace mágico por IP / hora
Onboarding__RequireEmailVerifyBeforeProvision true (portal) Exigir confirmación de correo antes del aprovisionamiento
Onboarding__RequireOnlinePaymentForNonTrial false (portal) Exigir un pago en línea real cuando no es Trial

Pago

El pago se procesa a través de Stripe en una cuenta central de DiKAS (no por inquilino).

Clave Significado
Signup__Stripe__SecretKey Clave secreta de Stripe (activa el adaptador de pago real)
Signup__Stripe__PublishableKey Clave publicable para el frontend
Signup__Stripe__WebhookSecret Secreto de firma para el webhook

Sin una SecretKey configurada, está activo un adaptador nulo (dev/test). Los valores de OnboardingPaymentMethod: SepaLastschrift = 1, StripeSetupIntent = 2 (Trial primero, registrar la forma de pago), StripePaymentIntent = 3 (pago primero, pago inmediato).

Ciclo de vida y limpieza

Dos servicios en segundo plano mantienen limpio el embudo:

Pedidos abandonados

OnboardingCleanupService (diario) elimina los pedidos abandonados/no pagados que llevan más de 14 días (CleanupAbandonedOnboardingsCommand, configurable) inactivos — incluidos los borradores públicos anónimos huérfanos (sin cliente vinculado) — y libera de nuevo su reserva de nombre en línea. Los pedidos aprovisionados/pagados permanecen intactos.

Trials caducados (dry-run, oculto)

TrialDeprovisioningService es un servicio construido de forma deliberadamente cautelosa:

  • Encuentra los Trials caducados cuyo periodo de gracia (GraceDays, por defecto 30) ha transcurrido tras el final del Trial (IsTrial = true y EndDate más allá del plazo; las licencias convertidas/pagadas con IsTrial = false nunca se incluyen).
  • En DRY-RUN solo registra qué bases de datos de inquilino ({DatabasePrefix}_maindb, {DatabasePrefix}_gastrocurrent) eliminaría una ejecución real posterior — no elimina nada.
  • Está completamente desactivado por defecto y solo se ejecuta con TrialDeprovision__Enabled=true.
Clave Por defecto Significado
TrialDeprovision__Enabled false Interruptor principal; false = el servicio no se ejecuta en absoluto
TrialDeprovision__GraceDays 30 Periodo de gracia en días tras el final del Trial

La eliminación real de la BD no está implementada

La eliminación real de las bases de datos de los inquilinos está deliberadamente sin implementar. Requiere una autorización explícita y un mapeo verificado de nombres de bases de datos, y debería coordinarse con la aplicación del vencimiento (fin del Trial → bloqueo → exportación).

Auditoría

Cada aprovisionamiento se registra mediante IAuditLogger y es visible en la vista de auditoría del operador (GET /api/v1/audit/logs/{date}, solo rol Admin):

Evento Disparador
TRIAL_PROVISIONED Inicio correcto de un Trial (con nombre en línea, ID de licencia, duración)
TRIAL_CONVERTED_PAID Conversión de un Trial en una licencia de pago

La marca de tiempo y la IP del cliente proceden de la solicitud; en los Trials anónimos, el usuario figura como -. Los datos de acceso no se escriben en la auditoría.

Antes de la activación

Antes de poner SelfServiceSignupEnabled en true:

  • ForwardedHeaders:KnownNetworks configurado en el despliegue de producción con el CIDR real del clúster (de lo contrario, la cuota por IP no tiene efecto).
  • Claves de Stripe (Signup__Stripe__*) configuradas — de lo contrario, un pago «en vivo de inmediato» con un proveedor real sería gratuito.
  • Envío del enlace mágico y /signup/verify completamente implementados.
  • Flag activado en OperationalConfig.