01En producción140h invertidas

TECI∞ Préstamos

Plataforma fintech de originación y gestión de préstamos (LOS + LMS) para una financiera argentina.

Next.jsTypeScriptSupabasePostgreSQLResendVercelTailwindRadix UITanStack TableRecharts
El problema

Una financiera de Córdoba se lanzaba desde cero y no tenía ningún canal digital: sin landing, sin captura de leads, sin evaluación crediticia y sin forma de gestionar préstamos más allá de un Excel y WhatsApp informal. La alternativa del mercado era alquilar un software de gestión para financieras con licencia mensual y contrato de permanencia — pagando por integraciones con terceros que en realidad se pueden contratar directo.

La idea

Construir a medida la plataforma completa en vez de alquilarla: originación (LOS) —landing que simula el préstamo, captura el lead y corre un filtro crediticio automático— y gestión/servicing (LMS) —alta de préstamos, cronograma de cuotas, cobranza y mora. Con un motor de decisión crediticia que consulta la Central de Deudores del BCRA (API pública y gratuita) para pre-aprobar o rechazar en el momento, y un diseño de cobros agnóstico de proveedor para no quedar atado a ningún gateway.

El resultado

Plataforma en producción en teciprestamos.com.ar. Originación: landing con simulador, captura de leads y filtro crediticio BCRA que auto-rutea cada solicitud (rechaza situación 4-5, deriva a revisión, deja pasar) y le responde al cliente al instante. Gestión: generación de préstamos con cronograma de cuotas, cobranza con seguimiento de mora (cron diario), caja con saldo real y registro de desembolso, más un portal donde el solicitante retoma su onboarding si quedó pendiente. Panel admin con dashboard de KPIs (gráficos con Recharts), tabla de leads en Realtime, tablas con TanStack Table, exports CSV/Excel/PDF, emails transaccionales y páginas legales publicadas. Como el sistema pasó a manejar dinero real y datos sensibles, se hizo una auditoría de seguridad completa y una segunda pasada de hardening: todas las lecturas del panel dejaron de usar el service_role y pasan por RLS real, el cobro de cuotas se volvió atómico (cerraba una condición de carrera que permitía cobrar la misma cuota dos veces), guardar la Configuración del sistema pide un segundo factor TOTP en el momento (no solo al loguearse), y los tokens de onboarding quedan hasheados en la base y expiran — antes vivían en texto plano sin vencimiento. Reemplazó una cotización de software de terceros por un sistema propio, sin costo de licencia mensual ni lock-in.

Arquitectura

Next.js 16 App Router con Server Components puros en la landing y Client Components solo donde hay interactividad. Supabase (PostgreSQL + Auth + Realtime) como backend completo. Módulos separados de originación (LOS) y gestión de préstamos (LMS).

Landing (RSC)Server Components puros, zero JS en el HTML inicial
Credit DecisioningFiltro BCRA Central de Deudores: construye el CUIL desde DNI+sexo, consulta la API pública y auto-rutea el lead. Corre sincrónico con fallback seguro para responder al cliente en el momento
Loan ManagementFunción SQL atómica genera préstamo + cronograma de cuotas. Campos de cobro agnósticos de gateway (metodo_cobro / gateway) para no atarse a un proveedor
API RoutesPOST /api/solicitud con rate limiting por IP; /api/prestamos y /api/cuotas con service client + auth sobre tablas con RLS sin políticas públicas
Supabase RealtimePanel admin actualiza la tabla en tiempo real con setAuth fix
EmailsResend con templates extraídos en lib/emails/, enviados en after() para no sumar latencia
Seguridad & Auditoría2FA (TOTP) obligatorio para el panel admin, log de auditoría inmutable por cada acción sensible, libro de caja append-only (las anulaciones se revierten con un asiento nuevo, nunca se borra), CAPTCHA anti fuerza-bruta en el login
Decisiones técnicas

¿Comprar un software de gestión para financieras o construirlo a medida?

elegido

Construir a medida y contratar los proveedores externos (buró, débito, firma) directo

descartado

Alquilar un software de gestión para financieras del mercado, con licencia mensual y contrato de permanencia

El 'sistema' que venden es en gran parte un caño hacia terceros (Nosis, procesadoras, AFIP). Construyendo el software propio y contratando a esos proveedores directo, se elimina el margen del intermediario, el lock-in, y se gana control total del dato.

¿Dónde correr la evaluación crediticia: en la landing o en el panel?

elegido

Filtro BCRA gratis y sincrónico en la captura + informe pago (Nosis) recién en revisión manual

descartado

Correr el informe pago automáticamente en cada submit de la landing

Un informe pago por cada submit sangra plata en tráfico no calificado y abre la puerta a abuso. El BCRA es gratis y oficial: filtra los casos malos sin costo; el informe caro queda para los leads que valen la pena.

¿Cómo hacer rate limiting en Vercel serverless?

elegido

Contar rows por IP en Supabase en la última hora

descartado

In-memory Map

Las Vercel Functions son stateless — cada deploy es una instancia nueva. Un Map en memoria no persiste entre requests.

¿Cómo blindar el acceso a datos financieros antes de escalar el negocio?

elegido

Auditoría de seguridad completa apenas el sistema empezó a manejar dinero y datos de clientes reales

descartado

Confiar en que la validación de la aplicación (Next.js) alcanza como única barrera de autorización

La auditoría encontró una brecha real entre lo que la aplicación validaba y lo que la base de datos permitía por debajo: un flujo quedaba protegido en la capa de app pero no en la capa de datos. La autorización tiene que garantizarse en cada capa, no asumirse desde una sola.

Errores reales · lo que salió mal
01

createClient() a nivel módulo causaba 'supabaseUrl is required' en build time. Fix: moverlo dentro del handler.

02

Supabase Realtime no actualizaba porque faltaba setAuth(session.access_token) antes de suscribir al canal.

03

El pre-filtro crediticio corría en after() (post-respuesta), así que no podía avisarle al cliente en el momento. Fix: moverlo a sincrónico con timeout y fallback que nunca rechaza ante una falla del BCRA.

04

La lógica de 2FA obligatorio solo detectaba 'falta completar el segundo factor', no 'todavía no hay ningún factor cargado' — dejaba pasar cuentas sin enrolar. Fix: chequear explícitamente si existe un factor verificado, no solo comparar niveles de autenticación.

05

El cobro de una cuota no era atómico: dos requests casi simultáneos (doble click, retry de red) podían leer el mismo estado 'pendiente' y cobrarla dos veces antes de que el primero terminara de escribir. Fix: la operación de cobro pasó a ser atómica en la base, no un read-then-write desde la aplicación.

Qué mejoraría

Integrar Nosis/Veraz como capa de scoring paga sobre el filtro BCRA gratuito. Enchufar el gateway de débito recurrente (el diseño ya es agnóstico) y firma electrónica para el onboarding. CMS headless para que el cliente edite tasas sin código.