Docs

Arquitectura del Sistema

Informacion del Documento

CampoValor
Version1.1
FechaMarzo 2026
EstadoPublicado
ProyectoNvito Platform

Tabla de Contenidos

  1. Arquitectura de Alto Nivel (C4 Context)
  2. Arquitectura de Contenedores (C4 Container)
  3. Flujo de Request HTTP
  4. Multi-Tenancy
  5. Comunicacion entre Servicios
  6. Patrones Arquitectonicos

1. Arquitectura de Alto Nivel (C4 Context)

La plataforma Nvito esta compuesta por cuatro aplicaciones principales que trabajan en conjunto para ofrecer la experiencia completa de gestion de eventos sociales. Cada aplicacion tiene un proposito especifico y se comunica con servicios externos especializados.

1.1 Aplicaciones del Sistema

AplicacionTecnologiaProposito
nvito-apiNestJSAPI REST centralizada con toda la logica de negocio, autenticacion y datos
nvito-adminNext.js 16Panel de administracion para anfitriones: gestion de eventos, invitados, invitaciones y configuracion
nvito-invitationsNext.js 16Micrositios publicos de invitaciones renderizados con SSG/ISR para maximo rendimiento
nvito-clientReact Native / ExpoApp movil nativa (iOS/Android) para interaccion en tiempo real: check-in QR, galeria, audio guestbook, push notifications

1.2 Servicios Externos

ServicioProposito
ClerkAutenticacion, gestion de identidad y JWT
PostgreSQLBase de datos principal con Row Level Security (RLS)
RedisCache, rate limiting, almacenamiento de sesiones y broker de colas
R2 / MinIOAlmacenamiento de objetos (imagenes, audio, archivos)
SMTP (Resend)Envio de correos electronicos transaccionales y notificaciones
TwilioEnvio de mensajes por WhatsApp para notificaciones a invitados

1.3 Actores del Sistema

ActorDescripcion
Anfitrion (Host)Crea eventos y gestiona invitaciones a traves de nvito-admin. El dia del evento, usa nvito-client para check-in y monitoreo en vivo
Invitado (Guest)Visualiza la invitacion publica via nvito-invitations y confirma RSVP. Usa nvito-client para QR pass, galeria y audio guestbook
Super AdministradorOperador de la plataforma con acceso global completo a todos los tenants
Platform AdminAdministrador de plataforma con lectura cross-org y escritura en orgs asignadas. Accede al panel admin con restricciones (no puede eliminar usuarios/orgs ni gestionar SA/PA)
Staff del EventoPersonal que realiza check-in de invitados el dia del evento

1.4 Diagrama C4 de Contexto


2. Arquitectura de Contenedores (C4 Container)

Cada aplicacion tiene una estructura interna compuesta por capas y componentes especializados. A continuacion se detalla la composicion interna de cada contenedor.

2.1 nvito-api (NestJS) - Componentes Internos

El backend esta construido con NestJS y sigue una arquitectura modular por capas:

Capa / ComponenteResponsabilidad
Guards GlobalesClerkAuthGuard (JWT), UserThrottlerGuard (rate limit), RoleGuard (RBAC)
TenantMiddlewareEstablece contexto de tenant via SET LOCAL app.current_tenant_id. Soporta X-Organization-Id para Platform Admins
AdminPanelGuardPermite acceso al panel admin para Super Admins y Platform Admins
PermissionsGuardValida permisos granulares por accion (events:create:organization)
Controllers56 controladores REST organizados por dominio (incluye mobile controllers y external-invitation controller)
ServicesLogica de negocio, validaciones, orquestacion de operaciones
Prisma ORMAcceso a datos con queries tipados y migraciones
AuditInterceptorRegistra operaciones de modificacion en audit_log de forma asincrona
Queue ProcessorsWorkers Bull para tareas asincronas (email, whatsapp, push notifications)
Sub-Services56 sub-servicios en directorios services/ con responsabilidad unica (SRP)
Modulos de Dominio39 modulos: Events, Guests, Invitations, RSVP, Locations, Tables, QR Passes, AI, Templates, Payments, Mobile, Clients, etc.

Modulos registrados en AppModule (39 de dominio + 5 de infraestructura = 44 total):

  • Core: AuthModule, OrganizationsModule, UsersModule, RolesModule, AdminModule, PackagesModule, HealthModule
  • Eventos: EventsModule, EventTypesModule, EventServicesModule, ContractsModule
  • Invitaciones: InvitationsModule, TemplatesModule, HtmlGenerationModule
  • Invitados: GuestsModule, GuestGroupsModule, RsvpModule, TablesModule
  • Clientes: ClientsModule
  • Features: LocationsModule, ItineraryModule, QRPassesModule, GiftRegistryModule, AccommodationModule, BackgroundMusicModule, MusicModule
  • Media: MediaModule, StorageModule, CustomDomainModule
  • IA: AIGenerationModule
  • Comunicaciones: NotificationsModule, NotificationChannelsModule, CommunicationsModule, QueueModule, SchedulerModule
  • Pagos: PaymentsModule
  • Movil: MobileModule, MobileAuthModule
  • Analitica: AnalyticsModule
  • Infraestructura: PrismaModule, CommonModule, ActivityLogModule, PermissionsModule, ConfigModule

2.2 nvito-admin (Next.js 16) - Componentes Internos

Capa / ComponenteResponsabilidad
App RouterEnrutamiento basado en carpetas de Next.js 16 con layouts anidados
API ClientCliente HTTP centralizado con interceptores para Bearer token (Clerk) y response validation (Zod)
Server Actions17 archivos de server actions con validacion Zod y ActionResult tipado
React QueryCache del lado del cliente, invalidacion automatica, optimistic updates
React CompilerMemoizacion automatica de componentes y hooks (habilitado en next.config.ts)
Componentes UI41+ componentes Shadcn/UI + componentes custom con accesibilidad (ARIA)
Clerk ProviderContexto de autenticacion, proteccion de rutas, session management
Validacion Zod16 esquemas de validacion para formularios y server actions
CSP HeadersContent Security Policy configurado para Clerk, Mapbox, CDN

2.3 nvito-client (React Native / Expo) - Componentes Internos

Capa / ComponenteResponsabilidad
Expo RouterNavegacion file-based con layouts anidados y grupos de rutas por rol
API ClientFetch wrapper con interceptores para Bearer token (JWT movil)
React QueryCache del lado del cliente con invalidacion automatica
AuthContextEstado de autenticacion con useReducer, tokens en SecureStore
MobileAuthGuardGuard en (app)/_layout.tsx que redirige a login si no autenticado
Push NotificationsRegistro de Expo Push Token y handlers de notificaciones
QR Scannerexpo-camera CameraView para escaneo de codigos QR en check-in
Media UploadsUpload de fotos y audio via presigned URLs a R2/MinIO
NativeWindTailwind CSS compilado a StyleSheet nativo para estilos

2.4 nvito-invitations (Next.js 16) - Componentes Internos

Aplicacion minimalista con solo 7 dependencias de produccion. Agnostica al origen: renderiza invitaciones de forma identica sin importar si fueron creadas con el motor de templates de Nvito (INTERNAL) o subidas como HTML externo (EXTERNAL).

Capa / ComponenteResponsabilidad
Route HandlersLogica principal en route handlers (/i/[slug], /preview/[token], /api/revalidate)
ISR (Revalidation)Regeneracion incremental cuando el contenido cambia via webhook
Servicios SOLID4 servicios con responsabilidad unica: invitation-fetcher, html-processor, cdn-validator, analytics-script
DOM Utilitiesfont-injector (Google Fonts) y html-sanitizer (DOMPurify whitelist)
InvitationRendererClient component que renderiza HTML sanitizado con tracking de analytics
Analytics TrackerRegistro de visitas, interacciones y metricas de engagement (Web Vitals)
SeguridadTiming-safe secrets, escape XSS context-aware, validacion SSRF, rate limiting, CSP headers

2.5 Diagrama C4 de Contenedores


3. Flujo de Request HTTP

Cada peticion HTTP que llega a nvito-api atraviesa una cadena de middleware, guards e interceptors antes de llegar al controlador. El orden de ejecucion es critico para la seguridad y el aislamiento de datos.

3.1 Cadena de Ejecucion

El flujo completo de un request autenticado es el siguiente:

  1. HTTP Request - La peticion llega al servidor NestJS (puerto configurable, default 3000)
  2. Helmet + CORS + Compression - Middleware de seguridad y rendimiento configurados en main.ts
  3. ValidationPipe - Validacion global de DTOs con whitelist y forbidNonWhitelisted
  4. ClerkAuthGuard - Verifica el JWT de Clerk, busca el usuario en la BD, resuelve roles desde user_roles, valida que el usuario este activo y no eliminado
  5. UserThrottlerGuard - Rate limiting por usuario autenticado (100 req/min) o por IP para rutas publicas, almacenado en Redis
  6. TenantMiddleware - Extrae el organizationId del usuario autenticado y ejecuta SET LOCAL app.current_tenant_id en PostgreSQL para activar RLS
  7. RoleGuard - Verifica que el rol del usuario (owner, admin, member, super_admin) cumple con el minimo requerido por la ruta
  8. PermissionsGuard - Valida permisos granulares definidos con @RequirePermission('resource:action:scope')
  9. Controller - Recibe la peticion validada, extrae parametros y delega al servicio
  10. Service - Ejecuta la logica de negocio, validaciones de dominio y operaciones
  11. Prisma - Ejecuta queries contra PostgreSQL con RLS activo (filtrado automatico por tenant)
  12. AuditInterceptor - Tras una respuesta exitosa en rutas criticas (POST/PATCH/PUT/DELETE), registra la accion en audit_log de forma asincrona
  13. Response - Se envia la respuesta al cliente con compresion gzip

3.2 Diagrama de Secuencia del Request

3.3 Notas sobre el Flujo

  • Orden de guards: El orden en AppModule importa. ClerkAuthGuard va primero para que req.user este disponible para UserThrottlerGuard
  • Rutas excluidas de TenantMiddleware: webhooks/* y health no pasan por el middleware de tenant
  • Auditoria asincrona: El AuditInterceptor no bloquea la respuesta HTTP; el registro en audit_log se ejecuta en background
  • Rate limiting con Redis: El RedisThrottlerStorage usa Redis compartido para funcionar correctamente con multiples instancias del API

4. Multi-Tenancy

Nvito implementa multi-tenancy a nivel de base de datos utilizando PostgreSQL Row Level Security (RLS). Cada organizacion es un tenant aislado, y el mecanismo garantiza que un tenant nunca pueda acceder a los datos de otro.

4.1 Concepto General

AspectoImplementacion
EstrategiaRow Level Security (RLS) - una BD, un schema, multiples tenants
Boundary del tenantLa entidad Organization es la frontera del tenant
Columna de filtradoorganizationId (UUID) presente en todas las tablas principales
Variable de sesionapp.current_tenant_id configurada via SET LOCAL por transaccion
EnforcementPoliticas RLS en PostgreSQL que filtran automaticamente por organization_id

4.2 Como Funciona el TenantMiddleware

El TenantMiddleware en /nvito-api/src/database/tenant.middleware.ts es el componente central del sistema multi-tenant:

// Extracto simplificado del TenantMiddleware
async use(req: Request, res: Response, next: NextFunction) {
  const user = req.user as AuthenticatedUser;

  if (user && user.organizationId) {
    // SECURITY: Usar $executeRaw con tagged template para prevenir SQL injection
    await this.prisma
      .$executeRaw`SELECT set_config('app.current_tenant_id', ${user.organizationId}, true)`;
  }

  next();
}

Puntos clave:

  • Usa set_config con el tercer parametro true para que sea local a la transaccion (SET LOCAL)
  • El organizationId ya fue resuelto y validado por ClerkAuthGuard desde la tabla user_roles
  • Previene SQL injection usando tagged templates de Prisma ($executeRaw)
  • Solo se aplica si el usuario esta autenticado y tiene una organizacion asignada
  • Las rutas de webhooks y health estan excluidas

4.3 Politica RLS en PostgreSQL

-- Ejemplo de politica RLS aplicada a la tabla events
CREATE POLICY tenant_isolation_policy ON events
  USING (organization_id = current_setting('app.current_tenant_id')::uuid);

-- Cuando el usuario ejecuta:
SELECT * FROM events WHERE status = 'published';

-- PostgreSQL realmente ejecuta (RLS transparente):
SELECT * FROM events
WHERE status = 'published'
AND organization_id = 'uuid-de-la-org';  -- Anadido automaticamente por RLS

4.4 Diagrama de Secuencia Multi-Tenancy

4.5 Garantias de Aislamiento

GarantiaMecanismo
Aislamiento de datosRLS filtra todas las queries automaticamente por organization_id
Prevencion de cross-tenantNo es posible acceder a datos de otra organizacion, ni siquiera con queries manuales desde el codigo
Super AdminLos super admins tienen organizationId = null, lo que les permite operar sin restriccion de RLS cuando es necesario
Platform AdminLos platform admins tienen lectura cross-org (sin RLS). Para escritura, el TenantMiddleware usa activeOrganizationId del header X-Organization-Id para establecer el contexto de la org donde operan
TransaccionalSET LOCAL asegura que el contexto del tenant se limita a la transaccion actual
Sin SQL injectionTagged templates de Prisma previenen inyeccion en el set_config

5. Comunicacion entre Servicios

La comunicacion entre las cuatro aplicaciones y los servicios externos sigue patrones especificos segun el tipo de interaccion.

5.1 Admin a API (Sincrono)

AspectoDetalle
ProtocoloHTTPS REST
AutenticacionBearer token (JWT emitido por Clerk)
Prefijo/v1/ (versionado de API)
FormatoJSON
Cache clienteReact Query con invalidacion automatica
CORSOrigenes configurados explicitamente, sin wildcard en produccion

El flujo tipico es:

  1. nvito-admin obtiene el JWT del usuario autenticado via Clerk Provider
  2. El API Client adjunta el token como Authorization: Bearer <jwt>
  3. nvito-api valida el token, resuelve el usuario y aplica el contexto de tenant
  4. La respuesta se cachea en React Query con keys basadas en el recurso

5.2 Invitations a API (Sincrono - Parcialmente Publico)

AspectoDetalle
ProtocoloHTTPS REST
AutenticacionSin autenticacion (rutas @Public()) para RSVP y visualizacion
Server-sideFetch de metadata en getStaticProps / generateStaticParams
DatosMetadata de invitacion, datos del evento, configuracion de RSVP

5.3 App Movil a API (Sincrono - JWT Movil)

AspectoDetalle
ProtocoloHTTPS REST
AutenticacionBearer token (JWT firmado con MOBILE_JWT_SECRET, independiente de Clerk)
Prefijo/v1/mobile/ (endpoints dedicados para la app)
GuardMobileAuthGuard (valida JWT movil, extrae rol HOST/GUEST)
FormatoJSON
Cache clienteReact Query con invalidacion automatica
PushRegistro de Expo Push Token para notificaciones

El flujo tipico es:

  1. El usuario se autentica con codigo de evento + PIN (host) o access token (guest)
  2. nvito-api genera un JWT de 15 min + refresh token de 30 dias
  3. Los tokens se almacenan en expo-secure-store (almacenamiento encriptado nativo)
  4. El API Client inyecta el Bearer token en cada request
  5. Si recibe 401, intenta renovar el JWT con el refresh token automaticamente

5.4 API a Invitations (Webhook ISR)

Cuando un anfitrion modifica una invitacion en nvito-admin, el API notifica a nvito-invitations para que regenere la pagina estatica:

AspectoDetalle
MecanismoWebhook HTTP POST a la ruta de revalidacion de Next.js
TriggerPublicacion/despublicacion de invitacion (internas y externas), cambio de estado
EfectoISR regenera la pagina estatica de la invitacion afectada
SeguridadToken secreto compartido para validar el webhook

5.5 API a Queue (Asincrono)

Las tareas que no requieren respuesta inmediata se procesan a traves de colas BullMQ:

Cola / JobProcessorProposito
emailEmailProcessorEnvio de correos electronicos via SMTP (nodemailer)
whatsappWhatsAppProcessorEnvio de mensajes WhatsApp via Twilio
pushPushProcessorNotificaciones push via Expo Push API a dispositivos moviles

5.6 Webhooks Entrantes

OrigenEndpointProposito
Clerk/webhooks/clerkSincronizacion de usuarios: creacion, actualizacion, eliminacion
Twilio/webhooks/twilioStatus de entrega de mensajes WhatsApp
Stripe/webhooks/stripeEventos de pago: checkout completado, pago fallido, reembolsos

Estas rutas estan excluidas del TenantMiddleware y utilizan verificacion de firma propia del servicio externo (Svix para Clerk, Twilio signature, Stripe signature).

5.7 Invitations a CDN

Las invitaciones publicas se sirven desde el edge de la CDN:

AspectoDetalle
Build-timeSSG genera HTML/CSS/JS estatico por invitacion
RuntimeCDN sirve el contenido pre-compilado con latencia minima
RevalidacionISR regenera paginas individuales cuando cambia el contenido
AssetsImagenes y audio se cargan desde R2/MinIO via URLs firmadas

6. Patrones Arquitectonicos

6.1 Multi-Repo

Nvito utiliza una estrategia de multiples repositorios independientes:

RepositorioTecnologiaDespliegue Independiente
nvito-apiNestJSSi
nvito-adminNext.js 16Si
nvito-invitationsNext.js 16Si
nvito-clientReact Native / ExpoSi (Expo Go / TestFlight)

Ventajas de este enfoque:

  • CI/CD independiente: Cada aplicacion tiene su propio pipeline de build, test y deploy
  • Versionado independiente: Las versiones de cada aplicacion avanzan a su propio ritmo
  • Equipos autonomos: Diferentes desarrolladores pueden trabajar en cada repositorio sin conflictos
  • Deployment aislado: Un deploy de nvito-admin no afecta a nvito-api ni a nvito-invitations
  • Tecnologias especializadas: Cada repo puede tener sus propias dependencias y configuraciones

6.2 Arquitectura por Capas (Layered Architecture)

El backend sigue una arquitectura estrictamente por capas con dependencias unidireccionales:

Controller --> Service --> Repository (Prisma)
CapaResponsabilidadEjemplo
ControllerRecibir HTTP, validar DTOs, delegar al servicioEventsController.create()
ServiceLogica de negocio, validaciones de dominio, orquestacionEventsService.createEvent()
RepositoryAcceso a datos via Prisma ORM, queries a PostgreSQLprisma.event.create()

Reglas:

  • Los controllers nunca acceden directamente a Prisma
  • Los services pueden inyectar otros services para orquestacion
  • La capa de datos (Prisma) es la unica que interactua con PostgreSQL

6.3 CQRS-Lite (Command Query Responsibility Segregation)

Nvito aplica una version simplificada de CQRS donde las operaciones se separan por semantica HTTP:

TipoMetodo HTTPSemanticaEjemplo
QueryGETLectura de datos, sin efectos secundariosGET /v1/events
CommandPOSTCreacion de recursosPOST /v1/events
CommandPATCH / PUTActualizacion de recursos existentesPATCH /v1/events/:id
CommandDELETEEliminacion de recursosDELETE /v1/events/:id

Diferencias con CQRS completo:

  • No hay modelos de lectura y escritura separados
  • No hay event store ni event sourcing
  • La separacion es a nivel de convencion HTTP, no de infraestructura
  • El AuditInterceptor solo registra Commands (POST/PATCH/PUT/DELETE), no Queries (GET)

6.4 Event-Driven para Tareas Asincronas (BullMQ)

Las operaciones que no requieren respuesta inmediata se delegan a colas de trabajo:

Service --> QueueModule.add(jobName, payload) --> Redis (BullMQ) --> Worker/Processor
CaracteristicaImplementacion
BrokerRedis como backend de BullMQ
Produccion de jobsLos services encolan jobs con datos del contexto actual
Consumo de jobsWorkers dedicados procesan jobs de forma asincrona
ReintentosConfiguracion por cola con backoff exponencial
MonitoreoDashboards de BullMQ para observar estado de colas

Casos de uso tipicos:

  • Envio de email de confirmacion tras RSVP
  • Generacion de HTML compilado de invitacion
  • Procesamiento de generacion de contenido con IA
  • Envio de recordatorios programados
  • Procesamiento batch de metricas de analytics

6.5 ISR (Incremental Static Regeneration) para Paginas Publicas

Las invitaciones publicas usan ISR para combinar el rendimiento de paginas estaticas con la capacidad de actualizar contenido:

FaseDescripcion
Build-timeSe genera HTML estatico para cada invitacion publicada
Request-timeEl CDN sirve la pagina pre-renderizada con latencia minima
RevalidacionCuando nvito-api detecta un cambio, envia un webhook a Next.js para regenerar solo la pagina afectada
FallbackPara invitaciones nuevas que no existian en build-time, se genera on-demand y se cachea

Beneficios:

  • Tiempo de carga < 1 segundo (servido desde CDN edge)
  • Core Web Vitals optimizados (LCP, FID, CLS)
  • Costo de infraestructura bajo (no requiere servidor activo para cada request)
  • Actualizacion en tiempo casi-real cuando el anfitrion modifica la invitacion

6.6 Seguridad en Capas

La seguridad se implementa como multiples capas que un request debe atravesar:

CapaComponenteNivel de Proteccion
1. RedHelmet + CORSHeaders de seguridad, proteccion de origenes
2. Rate LimitingUserThrottlerGuard100 req/min por usuario/IP via Redis
3. AutenticacionClerkAuthGuardVerificacion JWT, usuario activo, no eliminado
4. TenantTenantMiddlewareAislamiento de datos por organizacion (RLS)
5. AutorizacionRoleGuard + PermissionsGuardRBAC con permisos granulares
6. ValidacionValidationPipeDTOs con whitelist, forbidNonWhitelisted
7. AuditoriaAuditInterceptorRegistro de todas las acciones de modificacion
8. Base de datosPostgreSQL RLSFiltrado automatico por tenant a nivel de query

Referencias

Esta pagina fue util?