Diseñé y desarrollé GasBrain de cero: una plataforma SaaS completa con arquitectura multi-tenant, desde la base de datos hasta el diseño de la landing. Incluye una API REST con 30+ módulos en NestJS, WebSocket para tiempo real, y un frontend en Next.js 16 con App Router — todo en producción en gasbrain.com.ar. Autenticación JWT con 2FA, integración con MercadoPago para suscripciones, y un sistema de planes con feature flags y límites configurables por organización.
API REST con 30+ módulos y arquitectura multi-tenant — aislamiento total por organizationId en cada query, tenantId embebido en JWT, sin exposición en URL
Autenticación JWT dual token (access + refresh con rotación y blacklist), 2FA TOTP compatible con Google Authenticator, PIN login para cajeros y brute force protection (5 intentos → bloqueo 10 min)
Transacciones atómicas en ventas: sale + items + payments + descuento de inventario en una única operación Prisma con rollback automático
Integración MercadoPago con webhooks idempotentes, validación de firma HMAC y tabla ProcessedWebhookEvent para prevenir duplicados
WebSocket gateway con Socket.io y auth JWT — eventos sale.created, stock.low, notification en tiempo real
Sistema de planes FREE / PRO / ENTERPRISE con feature flags booleanos y límites numéricos verificados en backend con guard @RequireFeature() y en cliente con Zustand
Cron jobs automáticos: verificación de suscripciones expiradas (9am), limpieza de refresh tokens (3am), purga de audit logs >90 días (domingos 4am)
Audit logging automático en módulos críticos: acción, recurso, valores anterior/nuevo, userId, IP, userAgent
Rate limiting en endpoints críticos (auth, billing, reset password) con ThrottlerModule
Panel SuperAdmin con métricas de plataforma, gestión de organizaciones, cambio de plan, suspensión de cuentas e impersonación
POS con escáner de barcode por cámara del dispositivo (sin hardware extra), búsqueda por nombre/código, carrito con múltiples ítems, descuentos, 4 métodos de pago (efectivo / tarjeta / transferencia / QR) y cálculo de vuelto automático
Dashboard con métricas del día, tendencia de revenue vs. ayer y badges de sesión de caja activa por sucursal
Gestión completa: productos, categorías, inventario multi-sucursal con ajuste rápido desde tabla, stock bajo filtrable y alertas automáticas
Historial de ventas con filtros por fecha / sede / cajero / método de pago, cancelación por Owner
Sesiones de caja con apertura/cierre, movimientos manuales CASH_IN/CASH_OUT y cálculo de diferencias
Reportes de ventas con export a Excel (PRO) y analytics avanzado con gráficos Recharts (ENTERPRISE): ventas por hora, performance por cajero y análisis de clientes
Clientes con historial de compras, descuentos con scopes múltiples y toggle activo/inactivo
Notificaciones in-app en tiempo real: stock bajo, plan por vencer, diferencias de caja
Wizard de onboarding de 3 pasos post-registro, i18n ES/EN en landing, diseño responsive mobile-first
Billing con plan actual, uso vs. límites, upgrade vía MercadoPago y banner de trial con countdown
FLUJO — Venta en POS: [Cajero] escanea barcode con cámara → [Frontend] busca producto por código en cache local → agrega al carrito → selecciona método de pago (efectivo/tarjeta/transferencia/QR) → si efectivo: ingresa monto recibido, calcula vuelto → confirma venta → POST /sales {items[], payments[], discountId?} → [SaleService] inicia transacción Prisma → crea Sale → crea SaleItems → crea Payments → descuenta stock de cada producto → si stock < umbral: emite evento stock.low via WebSocket → commit transacción → response con saleId y receipt → [Frontend] muestra comprobante
FLUJO — Login con 2FA: [Usuario] POST /auth/login {email, password} → [AuthService] verifica brute force (< 5 intentos en 10 min) → BCrypt.verify → si usuario tiene 2FA habilitado: response {requires2FA: true, tempToken} → [Frontend] muestra input TOTP → [Usuario] ingresa código de Google Authenticator → POST /auth/2fa/verify {tempToken, totpCode} → [AuthService] Speakeasy.verify(secret, code) → si válido: genera accessToken (15min) + refreshToken (7d) con claims {userId, orgId, role} → response {accessToken, refreshToken}
FLUJO — Suscripción MercadoPago: [Owner] click "Upgrade a PRO" → [Frontend] POST /billing/checkout {planId: PRO} → [BillingService] crea preferencia en MercadoPago SDK con items, back_urls y notification_url → response {checkoutUrl} → redirect a MercadoPago → [Usuario paga] → [MercadoPago] POST /webhooks/mercadopago {type: payment, data.id} → [WebhookController] valida firma HMAC del header → busca en ProcessedWebhookEvent (idempotencia) → si es nuevo: actualiza plan de la org a PRO, setea expiración, activa feature flags → persiste webhook procesado → response 200
FLUJO — Aislamiento multi-tenant: [Request] GET /products → [JWT Guard] extrae token → decodifica claims {userId, organizationId, role} → [TenantInterceptor] inyecta orgId en el contexto → [ProductService] findMany({where: {organizationId: ctx.orgId}}) → Prisma filtra automáticamente por tenant → response solo con productos de ESA organización. Ningún endpoint expone orgId en la URL — siempre viene del token
FLUJO — Notificaciones en tiempo real: [Venta completada] → [SaleService] emite evento sale.created via Socket.io gateway → [WebSocket Gateway] valida JWT del socket conectado → broadcast a todos los sockets de la misma organizationId → [Dashboard] TanStack Query invalida cache de métricas → actualiza revenue del día en tiempo real. Mismo flujo para stock.low (alerta de inventario) y notification (genérica)
FLUJO — Feature gating por plan: [Request] POST /reports/export-excel → [@RequireFeature("excel_export") Guard] extrae orgId del JWT → carga plan de la organización → verifica featureFlags.excel_export == true → si FREE: 403 "Upgrade a PRO para exportar Excel" → si PRO/ENTERPRISE: ejecuta handler → genera Excel → response con archivo. En frontend: Zustand store tiene planFeatures → componente ExportButton chequea features.excel_export → si false: muestra badge "PRO" y abre modal de upgrade