Arquitectura Funcional de Lana Bank
Tabla de Contenidos
- Descripción General
- Arquitectura de la Aplicación
- Flujos de Comunicación
- Integraciones con Sistemas Externos
- Flujos de Autenticación y Seguridad
- Segmentación de Red por Entorno
- Zonas de Seguridad
- Auditoría
- Flujo de Préstamo Respaldado por Bitcoin
- Portabilidad y Dependencia de Proveedor
- Servidores / Instancias
- Sistemas Operativos
- Bases de Datos
- Middleware / Integración
- Servicios Externos
1. Descripción General
Este documento describe la arquitectura lógica de Lana Bank, incluyendo la arquitectura interna de la aplicación, integraciones con sistemas externos, flujos de autenticación y seguridad, segmentación de red por entorno y zonas de seguridad.
1.1 Visión General
Lana Bank es una aplicación de core bancario especializada en préstamos respaldados por Bitcoin. La arquitectura sigue los principios de Domain-Driven Design (DDD) y Arquitectura Hexagonal, separando claramente las capas de dominio, aplicación e infraestructura.
El backend está desarrollado en Rust, utilizando PostgreSQL como base de datos principal y Cala Ledger como motor de contabilidad de partida doble con garantías de consistencia fuerte. Los frontends web están construidos con Next.js y TypeScript, consumiendo APIs GraphQL expuestas por el backend. Para reportes y analítica, existe un pipeline de datos basado en Meltano que extrae información a BigQuery, donde los datos se transforman con dbt.
2. Arquitectura de la Aplicación
2.1 Módulos del Core Bancario
Los módulos del core implementan la lógica de negocio del banco, siguiendo principios de Event Sourcing donde cada entidad mantiene su estado como una secuencia de eventos inmutables.
2.1.1 Crédito
El módulo de crédito es el corazón del sistema, gestionando el ciclo de vida completo de préstamos respaldados por Bitcoin. Una facilidad de crédito pasa por un ciclo de vida bien definido que comienza cuando un operador crea una CreditFacilityProposal para un cliente. Esta propuesta automáticamente ingresa a un proceso de aprobación gestionado por el módulo de gobernanza; los miembros del comité asignado deben votar para aprobarla.
Una vez aprobada, la propuesta se transforma en una PendingCreditFacility. En esta etapa, el cliente debe depositar el colateral en Bitcoin requerido. Si la facilidad tiene un custodio asignado, los webhooks del custodio mantienen automáticamente sincronizado el balance del colateral. Si no hay custodio (modo manual), un operador puede actualizar el colateral directamente. El sistema monitorea continuamente la ratio de colateralización (CVL - Collateral Value to Loan) comparándola con el precio actual del Bitcoin.
La facilidad se activa automáticamente cuando el CVL alcanza el umbral inicial configurado en los términos. Los TermValues definen todos los parámetros del préstamo: la tasa de interés anual, la duración (clasificada como corto o largo plazo dependiendo de si excede 12 meses), los intervalos de acumulación de intereses (diarios o mensuales), la comisión inicial (cargo único), y tres umbrales críticos de CVL que deben mantener una jerarquía estricta: el CVL inicial debe ser mayor que el CVL de margin call, que a su vez debe ser mayor que el CVL de liquidación. También se configura la política de desembolso, que puede ser única o múltiple.
Con la CreditFacility activa, el cliente puede solicitar Disbursals. Cada desembolso pasa por su propio proceso de aprobación. Cuando se ejecuta, los fondos se acreditan en la cuenta de depósito del cliente y se crea una Obligation que representa la deuda. Las obligaciones tienen un ciclo de estados: comienzan como "no vencidas", pasan a "vencidas" en la fecha de vencimiento, pueden convertirse en "morosas" si no se pagan a tiempo, entran en "liquidación" si la morosidad persiste, y finalmente pueden marcarse como "en default".
El sistema ejecuta trabajos periódicos para la acumulación de intereses. Los InterestAccrualCycles calculan intereses según los intervalos configurados y generan nuevas obligaciones por intereses acumulados. Cuando el cliente realiza un Payment, el sistema asigna automáticamente los fondos a las obligaciones pendientes en orden de prioridad a través de PaymentAllocation, típicamente priorizando las obligaciones más antiguas y los intereses sobre el principal.
Si el CVL cae por debajo del umbral de margin call, la facilidad entra en estado de alerta. Si cae por debajo del umbral de liquidación, se inicia un LiquidationProcess donde el banco puede ejecutar el colateral para recuperar la deuda. El sistema implementa un buffer de histéresis para evitar oscilaciones frecuentes entre estados cuando el CVL está cerca de los umbrales.
2.1.2 Depósito
El módulo de depósitos gestiona las cuentas donde los clientes mantienen sus fondos en USD. Cuando se crea una DepositAccount para un cliente, el sistema genera automáticamente las cuentas contables correspondientes en el libro mayor. La categorización contable depende del tipo de cliente: las cuentas para individuos, entidades gubernamentales, empresas privadas, bancos, instituciones financieras y empresas no domiciliadas se agrupan bajo diferentes nodos del plan de cuentas.
Los Deposits representan ingresos de fondos a la cuenta y se registran inmediatamente. Los Withdrawals siguen un flujo más controlado: cuando se inician, los fondos se reservan contablemente y se crea un proceso de aprobación. El comité asignado debe aprobar el retiro antes de que se ejecute. Si se aprueba, los fondos salen de la cuenta; si se rechaza o cancela, la reserva se revierte. También existe la posibilidad de revertir depósitos ya registrados cuando sea necesario.
Las cuentas pueden estar en diferentes estados que afectan las operaciones permitidas. Una cuenta activa permite todas las operaciones normales. Una cuenta congelada impide nuevas operaciones pero mantiene el balance visible; esto es útil para situaciones de cumplimiento donde los fondos necesitan ser bloqueados temporalmente. Una cuenta cerrada es permanente y solo se permite si el balance es cero. El módulo también soporta la actualización masiva del estado de todas las cuentas de un cliente, por ejemplo cuando cambia su verificación KYC.
El historial de la cuenta puede consultarse a través del libro mayor, mostrando todas las transacciones que han afectado el balance. El módulo calcula el balance disponible considerando los retiros pendientes de aprobación.
2.1.3 Cliente
Este módulo gestiona la información de los clientes del banco y es fundamental para el cumplimiento regulatorio. Cada cliente se crea con un tipo específico que determina su tratamiento contable y regulatorio: Individual para personas naturales, GovernmentEntity para entidades gubernamentales, PrivateCompany para empresas privadas, Bank para bancos, FinancialInstitution para otras instituciones financieras, ForeignAgencyOrSubsidiary para agencias extranjeras, y NonDomiciledCompany para empresas no domiciliadas.
El proceso de verificación KYC se integra con SumSub. Un cliente comienza en estado PendingVerification. Cuando SumSub notifica vía webhook que la verificación fue exitosa, el cliente pasa a Verified con un nivel de KYC (Basic o Advanced). Si la verificación falla, permanece en estado Rejected. El sistema puede configurarse para requerir verificación antes de permitir la creación de cuentas de depósito o facilidades de crédito.
El módulo gestiona documentos asociados al cliente, almacenándolos en la nube y permitiendo la generación de enlaces de descarga temporales. Los documentos pueden archivarse o eliminarse según sea necesario.
Para el cumplimiento de regulaciones sobre cuentas inactivas, el sistema rastrea la última actividad de cada cuenta de depósito. Un trabajo periódico clasifica automáticamente las cuentas de depósito según su actividad: Active si han tenido actividad reciente (menos de un año), Inactive si han estado entre uno y diez años sin actividad, y Escheatable si exceden diez años. Esta clasificación es independiente del estado operacional de la cuenta y no congela ni cierra la cuenta por sí misma.
2.1.4 Custodia
El módulo de custodia proporciona una abstracción sobre múltiples proveedores de custodia de Bitcoin, permitiendo al banco trabajar con diferentes custodios según sus necesidades operativas y regulatorias. El sistema está diseñado con un patrón de plugins donde cada Custodian implementa una interfaz común. Se implementan BitGo, Komainu y una opción de Self-Custody basada en xpub, y la arquitectura permite agregar nuevos custodios sin modificar el resto del sistema.
En cada despliegue, se pueden configurar y activar múltiples custodios simultáneamente. Cuando se crea una facilidad de crédito, se puede especificar qué custodio gestionará el colateral de esa facilidad particular. Esto permite, por ejemplo, usar diferentes custodios para diferentes segmentos de clientes o jurisdicciones.
Cada custodio gestiona Wallets que se asignan a facilidades de crédito para recibir colateral en Bitcoin. Los custodios alojados notifican al sistema sobre cambios en los balances de las billeteras a través de webhooks. La opción de autocustodia almacena solo un xpub de cuenta en el backend, deriva una nueva dirección de recepción para cada préstamo recién creado, y consulta un backend esplora para cambios de balance confirmados. La URL base de esplora se selecciona al inicio desde lana.yml según la red de autocustodia configurada. El flujo de autocustodia soporta configuraciones de cuentas en mainnet, testnet3, testnet4 y signet. En ambos casos, Lana actualiza el Collateral asociado con la facilidad correspondiente y recalcula el CVL automáticamente.
Los webhooks de custodios se reciben en endpoints específicos por proveedor y se validan criptográficamente antes de procesarse. La configuración para custodios alojados incluye las credenciales de API necesarias y las claves para verificar la autenticidad de los webhooks, y esos valores sensibles se almacenan cifrados. Para autocustodia, el backend solo guarda el xpub; el xpriv correspondiente se genera y retiene fuera del backend, mientras que las URLs de esplora específicas de la red se proporcionan a través de la configuración de inicio.
2.1.5 Contabilidad
El módulo de contabilidad implementa un sistema completo de contabilidad de partida doble, fundamental para cualquier institución financiera regulada. Utiliza Cala Ledger como motor subyacente, un crate especializado de Rust que proporciona plantillas de transacciones predefinidas y garantías de consistencia ACID para todas las operaciones contables.
El ChartOfAccounts define la estructura jerárquica de cuentas del banco. Puede importarse desde archivos CSV y soporta una estructura de árbol con múltiples niveles. Cada nodo del árbol puede ser una cuenta individual o un grupo que agrega las cuentas de sus hijos. El plan de cuentas se integra con otros módulos: las cuentas de depósito de clientes, facilidades de crédito y cuentas de colateral se crean automáticamente como hijos de los nodos apropiados según el tipo de cliente y producto.
Cada LedgerAccount tiene un tipo de balance normal (débito o crédito) y puede mantener balances en múltiples monedas (USD y BTC). Las LedgerTransactions representan movimientos contables que siempre mantienen el balance: el total de débitos es igual al total de créditos. El sistema registra automáticamente transacciones para cada operación de negocio: depósitos, retiros, desembolsos, pagos de préstamos, acumulación de intereses y actualizaciones de colateral.
Para reportes financieros, el módulo genera el TrialBalance que lista todas las cuentas con sus balances de débito y crédito, útil para verificar que los libros cuadren. El BalanceSheet presenta la posición financiera del banco organizando activos, pasivos y patrimonio. El ProfitAndLoss muestra los ingresos (principalmente intereses de préstamos) menos los gastos para calcular el resultado del período.
El sistema soporta múltiples FiscalYears y permite consultar balances y reportes para rangos de fechas específicos. También permite ManualTransactions para ajustes contables que no provienen de operaciones automatizadas del sistema.
2.1.6 Gobernanza
El sistema de gobernanza proporciona un marco flexible para implementar flujos de aprobación multi-firma en operaciones sensibles. Está diseñado para adaptarse a diferentes estructuras organizacionales y requisitos regulatorios.
Los Committees representan grupos de personas autorizadas para tomar decisiones sobre ciertos tipos de operaciones. Un comité puede tener cualquier número de miembros, típicamente usuarios del sistema con roles específicos. El mismo usuario puede pertenecer a múltiples comités.
Las Policies definen las reglas de aprobación para cada tipo de proceso. Una política especifica qué comité es responsable de aprobar ese tipo de operación y cuál es el umbral requerido: el número mínimo de votos afirmativos necesarios para aprobar. Por ejemplo, una política para aprobación de desembolsos podría requerir 2 de 3 miembros del comité de crédito.
Cuando se inicia una operación que requiere aprobación, el sistema crea automáticamente un ApprovalProcess vinculado a la política correspondiente. El proceso comienza en estado pendiente y registra los votos de los miembros del comité. Un miembro puede votar para aprobar o para denegar (con una razón obligatoria). Cuando se alcanza el umbral de aprobación, el proceso se marca como aprobado y se emite un evento ApprovalProcessConcluded. Si algún miembro deniega, el proceso termina inmediatamente como rechazado.
Los eventos de conclusión del proceso de aprobación son consumidos por trabajos que ejecutan la operación aprobada o manejan el rechazo. Este diseño desacopla el flujo de aprobación de la ejecución, permitiendo que las aprobaciones se procesen de forma asíncrona.
2.1.7 Acceso
El módulo de acceso implementa control de acceso basado en roles (RBAC) para todos los operadores del sistema. Los Users representan a las personas que operan el banco a través del Panel de Administración. Cada usuario tiene un identificador único que se vincula con el sistema de autenticación externo.
Los Roles agrupan conjuntos de permisos y se asignan a los usuarios. Un usuario puede tener múltiples roles, y sus permisos efectivos son la unión de los permisos de todos sus roles. Los PermissionSets son colecciones nombradas de permisos específicos que facilitan la configuración de roles comunes.
El sistema de permisos es granular: cada operación en cada módulo tiene un permiso asociado. Por ejemplo, existen permisos separados para leer clientes, crear clientes, aprobar KYC, ver facilidades de crédito, iniciar desembolsos, etc. Antes de ejecutar cualquier operación, el sistema verifica que el usuario tenga el permiso correspondiente y registra la acción en el log de auditoría.
El sistema de autorización utiliza Casbin, un motor flexible de control de acceso, con políticas almacenadas en PostgreSQL para persistencia y sincronización entre instancias. El modelo RBAC sigue una estructura de tres niveles: Usuario → Rol → PermissionSet → Permisos (Objeto + Acción).
Cada módulo define sus propios conjuntos de permisos que agrupan acciones relacionadas. Los conjuntos de permisos típicos siguen un patrón viewer/writer. El sistema incluye roles predefinidos como Admin (acceso completo), Bank Manager (similar a admin pero sin acceso a gestión de acceso o custodia), y Accountant (enfocado en contabilidad y funciones de visualización).
Los permisos se gestionan dinámicamente a través de la API y los cambios persisten inmediatamente en la base de datos, recargándose en cada verificación de permisos, asegurando que las actualizaciones sean efectivas sin reiniciar el sistema.
2.1.8 Precio
Este módulo obtiene y gestiona precios de Bitcoin, una función crítica para un banco que ofrece préstamos colateralizados con BTC. El sistema se integra con Bitfinex para obtener precios en tiempo real a través de su API.
Cuando se obtiene un nuevo precio, el módulo publica un CorePriceEvent que otros módulos consumen. El módulo de crédito es el consumidor principal: utiliza el precio para calcular el CVL de todas las facilidades activas y determinar si alguna ha caído por debajo de los umbrales de margin call o liquidación. Los cambios de precio pueden desencadenar actualizaciones de estado en las facilidades y potencialmente iniciar procesos de liquidación.
2.1.9 Reporte
El módulo de reportes coordina la generación de reportes regulatorios y operacionales. Define tipos de Report que especifican qué datos incluir y en qué formato. Cada ejecución de reporte se registra como un ReportRun con su estado (pendiente, ejecutando, completado, fallido) y archivos generados.
La generación de reportes se integra con el pipeline de datos: los datos transformados en BigQuery alimentan los reportes finales. El sistema puede integrarse con sistemas de reportes externos según las necesidades regulatorias de cada jurisdicción donde opera el banco.
2.1.10 Módulos de Soporte
Además de los módulos principales, existen módulos de soporte: document-storage para almacenamiento de documentos en la nube, public-id para generar identificadores públicos legibles para entidades, y core-money que define primitivas monetarias (UsdCents, Satoshis) utilizadas en todo el sistema.
2.2 Capa de Aplicación
El directorio lana/ contiene la capa de aplicación que orquesta los módulos del core y expone la funcionalidad externamente.
2.2.1 Servidores GraphQL
El sistema expone dos servidores GraphQL independientes. El admin-server sirve al panel de administración utilizado por los operadores del banco, mientras que el customer-server sirve al portal de clientes. Ambos servidores incluyen un playground integrado para desarrollo y reciben webhooks de servicios externos.
2.2.2 Servicios de Aplicación
El servicio principal lana-app orquesta la inicialización de todos los módulos y proporciona el punto de entrada unificado. lana-cli ofrece una interfaz de línea de comandos para operaciones administrativas.
Existen servicios especializados para diferentes funciones: notification maneja el envío de correos electrónicos, contract-creation genera contratos en PDF, customer-sync y deposit-sync sincronizan datos con sistemas externos, user-onboarding gestiona el registro de operadores, y dashboard calcula métricas agregadas.
2.2.3 Sistema de Eventos
El módulo lana-events define el enum unificado LanaEvent que agrupa todos los eventos de dominio del sistema, permitiendo que el sistema de outbox y los trabajos procesen eventos de cualquier módulo de manera uniforme.
2.3 Frontends Web
2.3.1 Panel de Administración
El Panel de Administración es la interfaz principal para operadores y personal del banco. Permite gestionar clientes y sus procesos de KYC, administrar facilidades de crédito en todas sus etapas, aprobar desembolsos y retiros, y gestionar cuentas de depósito. También proporciona acceso a la visualización contable completa (balance, estado de resultados, balance de comprobación), configuración de comités y políticas de aprobación, gestión de usuarios y roles, y generación de reportes regulatorios.
2.3.2 Portal de Clientes
El Portal de Clientes está orientado a los clientes del banco. Actualmente ofrece funcionalidad de solo lectura, permitiendo la visualización de facilidades de crédito, estado de desembolsos e historial de transacciones. La arquitectura permite extenderlo en el futuro para soportar operaciones del lado del cliente.
2.3.3 Shared Web
El módulo shared-web contiene componentes de UI compartidos entre ambos portales, asegurando consistencia visual y reduciendo la duplicación de código.
3. Flujos de Comunicación
3.1 Event Sourcing y Eventos de Dominio
El sistema utiliza Event Sourcing como patrón arquitectónico central. Cada entidad recibe comandos que generan eventos, estos eventos se persisten en la base de datos como la única fuente de verdad, y el estado actual de la entidad se reconstruye aplicando la secuencia de eventos.
Este diseño proporciona auditabilidad completa (cada cambio queda registrado), la capacidad de reconstruir el estado en cualquier punto en el tiempo, y la posibilidad de agregar nuevas proyecciones sobre datos históricos.
La comunicación entre módulos ocurre a través de eventos públicos. Cada módulo define sus propios eventos en un enum específico (por ejemplo, CoreCreditEvent para el módulo de crédito). Un Publisher asociado a cada módulo transforma los eventos internos de entidad en eventos públicos que otros módulos pueden consumir.
Los eventos públicos típicos incluyen: creación y aprobación de propuestas de crédito, activación y finalización de facilidades, cambios de colateralización, desembolsos liquidados, acumulación de intereses, creación y transición de obligaciones entre estados (vencida, morosa, en default), pagos registrados y procesos de liquidación. Cada evento incluye marcas de tiempo de cuándo se registró y cuándo fue efectivo, permitiendo reconstrucciones precisas del estado en cualquier momento.
3.2 Patrón Outbox
Para integraciones con sistemas externos que requieren garantías de entrega, el sistema implementa el Patrón Outbox. Cuando un módulo necesita publicar un evento, lo persiste en una tabla outbox dentro de la misma transacción de base de datos que la operación de negocio. Esto garantiza atomicidad: o ambos (la operación y el evento) persisten, o ninguno.
PostgreSQL NOTIFY informa inmediatamente a los listeners cuando hay nuevos eventos, evitando la necesidad de polling.
El sistema soporta dos tipos de eventos en el outbox. Los eventos persistentes tienen un identificador único, un número de secuencia global monotónicamente creciente, el payload serializado como JSON, contexto de tracing para correlación distribuida, y marca de tiempo de cuándo se registró. Los eventos efímeros no tienen secuencia y se utilizan para notificaciones en tiempo real que no necesitan durabilidad.
Este diseño garantiza entrega al menos una vez: un sistema externo puede consumir eventos con la certeza de que no perderá ninguno, aunque podría recibir duplicados que debe manejar de forma idempotente.
3.3 Sistema de Trabajos Asíncronos
Las operaciones que no deben bloquear el flujo principal se ejecutan a través de un sistema de trabajos asíncronos. Los workers se ejecutan como procesos separados del servidor principal, permitiendo escalar el procesamiento independientemente de los servidores de API.
Los trabajos pueden programarse de varias maneras: ejecutar inmediatamente, programar para una fecha/hora futura específica, o reprogramarse al completarse para ejecutarse de nuevo. Esta flexibilidad es esencial para los flujos temporales del sistema bancario. Por ejemplo, cuando se crea una obligación, se programa un trabajo para la fecha de vencimiento. Cuando ese trabajo se ejecuta, si la obligación no está pagada, la marca como "vencida" y programa el siguiente trabajo para la fecha de morosidad. La cadena continúa: vencida → morosa → liquidación → en default, cada transición programada con precisión según los términos de la facilidad.
Para la acumulación de intereses, un trabajo procesa cada acumulación diaria y se reprograma automáticamente para el día siguiente. Cuando un período de acumulación termina (típicamente a fin de mes), programa un trabajo de ciclo de acumulación que consolida los intereses y crea la obligación correspondiente.
Otros trabajos procesan flujos de eventos del outbox continuamente, manteniendo su estado de ejecución (el último evento procesado) y reprogramándose inmediatamente cuando no hay nuevos eventos para continuar escuchando.
3.4 Webhooks Entrantes
Los servicios externos notifican al sistema a través de webhooks. SumSub envía notificaciones sobre el ciclo de vida de la verificación KYC a /webhook/sumsub. Cuando un cliente completa su verificación, SumSub notifica el resultado (aprobado o rechazado). El sistema procesa esta notificación y actualiza el estado de KYC del cliente, lo que puede desbloquear la creación de cuentas de depósito o facilidades de crédito según la configuración.
Los custodios de Bitcoin (BitGo, Komainu) notifican eventos de billetera a /webhook/custodian/[provider]. Cada proveedor tiene su propio formato de webhook que el sistema normaliza. Los eventos típicos incluyen depósitos de Bitcoin en billeteras de colateral. Cuando llega una notificación, el sistema verifica su autenticidad (típicamente vía HMAC), identifica la billetera afectada, actualiza el balance de colateral correspondiente, y recalcula el CVL de la facilidad de crédito asociada. Si el nuevo CVL cruza algún umbral configurado, el estado de colateralización se actualiza y se publican los eventos correspondientes.
Este flujo de webhooks es crítico para la gestión de riesgo en tiempo real. Sin él, el sistema dependería de polling periódico y podría tener visibilidad retrasada de los cambios en el colateral, aumentando el riesgo durante caídas del precio de Bitcoin.
3.5 Flujo de la API GraphQL
Las solicitudes de clientes web siguen este flujo: el cliente envía una solicitud GraphQL con un token JWT. El middleware extrae el sujeto del token y lo inyecta en el contexto. El resolver invoca el caso de uso correspondiente en lana-app, que primero verifica los permisos RBAC y luego ejecuta la operación en el módulo del core apropiado. Los eventos generados se publican y la respuesta retorna al cliente.
4. Integraciones con Sistemas Externos
La aplicación está diseñada para integrarse con varios servicios externos que proporcionan funcionalidades especializadas. Estos servicios no son parte de la infraestructura desplegada pero son componentes críticos del ecosistema operacional.
Es importante enfatizar que estos servicios deben ser configurados externamente por el cliente o el equipo de operaciones. La aplicación simplemente espera recibir las credenciales, tokens, endpoints y otra información de configuración necesaria para integrarse con estos servicios. La aplicación no gestiona la creación, configuración o administración de cuentas en estos servicios externos; solo consume sus APIs y servicios una vez que están configurados y disponibles.
4.1 KYC/KYB y AML (Conozca a su Cliente / Conozca su Negocio / Anti-Lavado de Dinero)
4.1.1 Sumsub
Sumsub se utiliza para gestionar los procesos y datos de KYC (Know Your Customer) y KYB (Know Your Business). Este servicio externo maneja la verificación de identidad de clientes y empresas, incluyendo:
- Validación de documentos de identidad
- Verificación biométrica
- Verificación de documentos corporativos
- Cumplimiento regulatorio
- Incorporación de clientes y empresas
- Verificación continua
Sumsub también satisface las necesidades de AML (Anti-Money Laundering) además de proporcionar capacidades de KYC/KYB. Sumsub incluye funcionalidades de detección y prevención de lavado de dinero, tales como:
- Verificación de listas de sanciones (OFAC, ONU, etc.)
- Análisis de transacciones sospechosas
- Monitoreo de patrones de comportamiento
- Reportes regulatorios automáticos
- Integración con sistemas de cumplimiento
La aplicación se integra con Sumsub a través de su API REST. Para configurar la integración, es necesario configurar una cuenta en el servicio de Sumsub, obtener credenciales de API (API key, API secret), configurar los endpoints correspondientes (pueden variar según la región) y proporcionar estas credenciales y endpoints como parte de la configuración del entorno.
El flujo de integración funciona de la siguiente manera: la aplicación envía solicitudes de verificación a Sumsub a través de su API. Sumsub procesa las solicitudes y realiza las verificaciones necesarias. Los resultados de los procesos de incorporación y verificación continua se reciben vía webhooks en el endpoint /webhook/sumsub. Cuando un cliente completa su verificación, SumSub notifica el resultado (aprobado o rechazado), y el sistema procesa esta notificación actualizando el estado de KYC del cliente, lo que puede desbloquear la creación de cuentas de depósito o facilidades de crédito según la configuración.
La arquitectura también está preparada para integrar sistemas AML adicionales si es necesario. Las integraciones AML típicamente incluyen las funcionalidades mencionadas anteriormente. La aplicación puede integrarse con proveedores de servicios AML a través de APIs REST o mediante integración con sistemas de terceros. La configuración seguiría el mismo patrón que otras integraciones externas: las credenciales y endpoints se proporcionan como parte de la configuración del entorno.
4.2 Pasarelas de Pago
Nota importante: Las integraciones con pasarelas de pago no están implementadas en la versión actual de Lana. Sin embargo, debido a que Lana es modular en su diseño, la arquitectura anticipa que estos elementos se agregarán eventualmente según las necesidades del negocio.
La aplicación está diseñada para integrarse con pasarelas de pago externas para procesar transacciones financieras. Aunque las pasarelas específicas pueden variar según el cliente y la región, la arquitectura soporta la integración con múltiples proveedores.
La aplicación está diseñada para soportar varios tipos de integración:
- Procesamiento de pagos con tarjeta (débito/crédito)
- Transferencias bancarias (ACH, transferencias electrónicas, etc.)
- Procesamiento de pagos móviles
- Integración con sistemas de compensación y liquidación
Las pasarelas de pago se integrarían vía APIs REST o SOAP. Las credenciales de API, endpoints y configuraciones específicas se proporcionarían como parte de la configuración del entorno. La aplicación está diseñada para soportar múltiples pasarelas simultáneamente, permitiendo el enrutamiento de transacciones según reglas de negocio.
Todas las comunicaciones con pasarelas de pago utilizarían TLS/SSL para cifrado en tránsito. Las credenciales sensibles se almacenarían como secrets en Kubernetes e se inyectarían en los contenedores de la aplicación vía variables de entorno o volúmenes montados.
4.3 BCR (Banco Central de Reserva)
Nota importante: La integración con el Banco Central de Reserva (BCR) no está implementada en la versión actual de Lana. Sin embargo, debido a que Lana es modular en su diseño, la arquitectura anticipa que esta integración se agregará eventualmente según las necesidades del negocio.
La aplicación está diseñada para incluir soporte para operaciones con el Banco Central de Reserva (BCR), que es el banco central de El Salvador. Esta integración sería crítica para las operaciones bancarias regulatorias.
El sistema está diseñado para soportar varios tipos de operaciones con el BCR:
- Depósitos en el BCR (moneda local y extranjera)
- Operaciones de repo con el BCR
- Operaciones de financiamiento con el BCR
- Reportes regulatorios y cumplimiento
- Operaciones de liquidez
La integración con el BCR se haría a través de sistemas estándar de comunicación bancaria (típicamente SWIFT, sistemas de mensajería financiera o APIs específicas del BCR). La configuración incluiría credenciales de acceso a los sistemas del BCR, endpoints de comunicación, certificados digitales para autenticación y configuración de formato de mensajes (ISO 20022, formatos propietarios, etc.).
Las operaciones del BCR se procesarían a través de workers dedicados que manejarían la comunicación asíncrona y el procesamiento de respuestas. Los datos de operaciones se registrarían en la base de datos principal y se integrarían con el sistema contable.
4.4 Fuentes de Datos Regulatorios
Nota importante: Las integraciones con fuentes de datos regulatorios no están implementadas en la versión actual de Lana. Sin embargo, debido a que Lana es modular en su diseño, la arquitectura anticipa que estos elementos se agregarán eventualmente según las necesidades del negocio.
La aplicación está diseñada para integrarse con múltiples fuentes de datos regulatorios para cumplimiento y reportes. Estas incluirían:
- Sistemas de reportes del banco central
- Sistemas de información crediticia
- Registros públicos (registro mercantil, registro de propiedad, etc.)
- Sistemas gubernamentales de verificación de identidad
- Sistemas de intercambio de información financiera
Las integraciones con fuentes de datos regulatorios se harían a través de:
- APIs REST o SOAP proporcionadas por organismos regulatorios
- Sistemas de mensajería financiera (SWIFT, sistemas propietarios)
- Archivos batch para intercambio de datos
- Portales web con autenticación y scraping automatizado (cuando sea necesario)
Los workers de la aplicación procesarían las integraciones con sistemas regulatorios de forma asíncrona. Los datos recibidos se validarían, transformarían y almacenarían en la base de datos. Los reportes regulatorios se generarían automáticamente según los requisitos y se enviarían a través de los canales apropiados.
4.5 Observabilidad
4.5.1 Honeycomb
Honeycomb se utiliza para la agregación y explotación de datos de OpenTelemetry, así como para la generación de alertas que se integran con software de gestión de pager/on-call. El sistema utiliza el protocolo OpenTelemetry (OTEL) para enviar métricas, logs y trazas desde el OpenTelemetry Collector hacia Honeycomb.
El OpenTelemetry Collector se configura con la API key y el dataset de Honeycomb. Los datos se envían automáticamente vía el protocolo OTEL. Aunque actualmente se utiliza Honeycomb, la aplicación usa el protocolo estándar OTEL, lo que permite migrar a otros proveedores compatibles (Datadog, New Relic, Grafana Cloud, etc.) sin modificaciones significativas.
El sistema está instrumentado para proporcionar visibilidad completa de su comportamiento en producción. OpenTelemetry captura trazas de todas las operaciones, desde la recepción de una solicitud HTTP hasta la respuesta final. Cada operación significativa crea un span con atributos relevantes. Los spans se propagan a través de llamadas asíncronas y entre servicios, permitiendo reconstruir el flujo completo de una operación.
Las trazas se exportan a Honeycomb, donde pueden analizarse para identificar cuellos de botella, errores y patrones de uso. La propagación del contexto de tracing a través del outbox permite correlacionar la operación original con su procesamiento asíncrono posterior.
El logging utiliza el crate tracing de Rust, que proporciona logs estructurados con niveles (error, warn, info, debug, trace) y campos tipados. Los logs se emiten en formato JSON en producción, facilitando su indexación y búsqueda. Cada entrada de log incluye automáticamente el contexto del span actual, conectándola con la traza distribuida.
4.6 Almacenamiento de Datos de Reportes
4.6.1 BigQuery
BigQuery se utiliza como almacenamiento de datos analíticos y de reportes. El sistema utiliza BigQuery para almacenar datos transformados desde las bases de datos operacionales de PostgreSQL, permitiendo análisis y reportes sin impactar el rendimiento de la base de datos transaccional.
La aplicación utiliza BigQuery en conjunto con herramientas ETL (Meltano) y transformación de datos (dbt) para cargar y transformar datos desde PostgreSQL a BigQuery. Meltano extrae datos de múltiples fuentes: el extractor principal tap-postgres obtiene eventos y entidades del core bancario, y extractores adicionales obtienen precios históricos de Bitfinex y datos de verificación KYC de SumSub.
Los datos se cargan en BigQuery, donde dbt los transforma a través de capas: staging (limpieza de datos crudos), intermediate (lógica de negocio) y outputs (reportes finales). El sistema genera reportes regulatorios que pueden integrarse con sistemas externos según las necesidades de cada jurisdicción.
La configuración incluye JSON de cuenta de servicio, ID de proyecto y nombres de datasets. Es importante notar que, aunque actualmente se utiliza BigQuery, la aplicación puede refactorizarse para realizar el mismo trabajo en otras bases de datos analíticas. El código ETL y de transformación puede adaptarse para trabajar con alternativas como Amazon Redshift, Snowflake, Azure Synapse Analytics, o incluso bases de datos analíticas on-premise.
5. Flujos de Autenticación y Seguridad
5.1 IAM (Gestión de Identidad y Acceso)
5.1.1 Keycloak
Keycloak actúa como el servidor central de identidad y acceso (IAM) integrado con la aplicación. Proporciona:
- Gestión de usuarios y roles
- Autenticación a través de múltiples métodos (usuario/contraseña, OAuth2, OIDC)
- Autorización basada en roles (RBAC)
- Single Sign-On (SSO)
- Gestión de sesiones
- Integración con proveedores de identidad externos (Google, etc.)
Naturaleza Federada y Autenticación Externa de Empleados:
Debido a su naturaleza federada, Keycloak está diseñado para delegar la autenticación de usuarios internos (empleados) a sistemas de identidad externos. Se espera que el backend de autenticación de empleados provenga externamente. Por ejemplo, si la institución utiliza Azure Active Directory (Azure AD), Keycloak debería integrarse con Azure AD para que Keycloak delegue la autenticación a Azure AD. Este es un detalle de despliegue que debe abordarse en cada caso según las necesidades de la institución y los sistemas de identidad existentes.
Configurabilidad:
Keycloak es altamente configurable y la configuración descrita a continuación es una sugerencia que puede adaptarse a las necesidades de cada despliegue. Los realms, clientes, flujos de autenticación y proveedores de identidad pueden configurarse según los requisitos específicos de cada cliente.
Como sugerencia, se configuran tres realms:
- Realm Interno: Para usuarios internos y servicios de la aplicación
- Realm de Clientes: Para los clientes de la aplicación
- Realm Data-Dagster: Para acceso a herramientas de datos (Dagster)
De manera similar, se sugieren tres clientes de aplicación:
- internal-service-account: Para servicios internos de la aplicación
- customer-service-account: Para el portal de clientes
- oauth2-proxy: Para autenticación con OAuth2 Proxy
El flujo de autenticación para usuarios internos funciona de la siguiente manera: cuando un usuario accede al Panel de Administración (admin.{domain}), la aplicación redirige a Keycloak para autenticación. Keycloak puede delegar la autenticación a un proveedor de identidad externo (por ejemplo, Azure AD, LDAP, etc.) o validar credenciales directamente. Después de una autenticación exitosa, Keycloak genera tokens JWT utilizados para autenticar solicitudes a la API GraphQL. Finalmente, Oathkeeper valida los tokens JWT antes de permitir acceso a los recursos.
Para clientes, el flujo de autenticación es similar: cuando un cliente accede al Portal de Clientes (app.{domain}), la aplicación redirige a Keycloak (Realm de Clientes) para autenticación. Keycloak valida las credenciales y genera tokens JWT, que se utilizan para autenticar solicitudes a la API pública. Oathkeeper valida los tokens JWT antes de permitir acceso a los recursos.
Los flujos de autenticación descritos son ejemplos y pueden variar según la configuración específica de cada despliegue, especialmente en lo que respecta a la integración con proveedores de identidad externos para usuarios internos.
5.1.2 Oathkeeper
Oathkeeper actúa como proxy de autenticación y autorización, proporcionando:
- Validación de tokens JWT
- Enrutamiento de solicitudes autenticadas
- Mutación de tokens (transformación de claims)
- Reglas de acceso basadas en URL y método HTTP
- Alta disponibilidad (2 réplicas por defecto)
Se configuran varias reglas de acceso:
- admin-api: Protege el endpoint GraphQL del Panel de Administración, requiere autenticación JWT
- admin-ui: Protege la interfaz del Panel de Administración, permite acceso sin autenticación (la autenticación la maneja la aplicación)
- customer-ui: Protege el Portal de Clientes, permite acceso sin autenticación (la autenticación la maneja la aplicación)
- customer-api: Protege la API pública del Portal de Clientes, requiere autenticación JWT
El flujo de validación funciona de la siguiente manera: cuando un cliente envía una solicitud con un token JWT en el header Authorization, Oathkeeper extrae y valida el token JWT contra el JWKS de Keycloak. Oathkeeper verifica que el token no haya expirado y que el emisor sea válido, luego aplica reglas de autorización según URL y método. Si la autorización es exitosa, Oathkeeper muta el token (opcional) y reenvía la solicitud al servicio upstream.
5.1.3 OAuth2 Proxy
OAuth2 Proxy proporciona autenticación OAuth2/OIDC para aplicaciones que no soportan autenticación nativa. Se utiliza principalmente para proteger el acceso a Dagster.
El flujo de autenticación con OAuth2 Proxy funciona así: cuando un usuario accede a Dagster (dagster.{domain}), OAuth2 Proxy intercepta la solicitud y verifica si existe una sesión válida. Si no hay sesión, OAuth2 Proxy redirige a Keycloak para autenticación. El usuario se autentica en Keycloak (puede usar Google como proveedor de identidad), y Keycloak redirige de vuelta a OAuth2 Proxy con un código de autorización. OAuth2 Proxy intercambia el código por tokens y crea una sesión, finalmente permitiendo el acceso a Dagster con headers de autenticación.
5.2 WAF (Web Application Firewall)
El sistema utiliza NGINX Ingress Controller como punto de entrada, que proporciona capacidades de WAF a través de varias funcionalidades.
Geo-blocking: Permite bloquear países no soportados configurados vía GeoIP2. La base de datos GeoIP2 se actualiza automáticamente desde un bucket de GCS, y las reglas de bloqueo se configuran vía mapas de NGINX.
Rate Limiting: Incluye limitación de solicitudes por minuto por host, limitación de conexiones simultáneas, y configuración por host (portal de clientes, panel de administración, dagster).
Protección Adicional: Existe la posibilidad de configurar WAF vía anotaciones de NGINX, integración con servicios WAF externos (Cloudflare, AWS WAF, Azure WAF, etc.), y protección contra ataques comunes (DDoS, SQL injection, XSS, etc.).
5.3 Firewalls
5.3.1 Reglas de Firewall en GCP
Las reglas de firewall en GCP incluyen:
- Egress Intra-cluster: Permite comunicación entre pods y con el master (protocolos TCP, UDP, ICMP, SCTP, ESP, AH) hacia CIDR del Master, Subred del Cluster, Rango de Pods y Rango de Servicios
- Ingress de Webhooks: Permite al master llamar webhooks en pods (puertos 8443, 443) desde CIDR del Master
- DMZ a Nodos: Permite acceso desde el bastión a nodos del cluster (todos los protocolos) desde la subred DMZ
5.3.2 Network Security Groups en Azure
Los Network Security Groups (NSG) en Azure proporcionan reglas de firewall por subred:
- NSG de PostgreSQL: Permite solo tráfico desde VirtualNetwork al puerto 5432
- NSG del Cluster: Controla tráfico hacia y desde nodos de Kubernetes
- NSG de DMZ: Controla acceso a hosts bastión
5.4 Cifrado en Tránsito
Para comunicaciones externas, todos los servicios expuestos públicamente utilizan HTTPS/TLS. Los certificados SSL/TLS son gestionados automáticamente por cert-manager, que puede usar Let's Encrypt (para certificados públicos) o una CA interna (para certificados privados). Los certificados se renuevan automáticamente antes de su expiración.
Para comunicaciones internas, las bases de datos PostgreSQL requieren SSL/TLS para todas las conexiones (sslmode = "require" en Azure). Las comunicaciones entre servicios dentro del cluster pueden usar mTLS (mutual TLS) vía service mesh (opcional). Las comunicaciones con servicios externos (Sumsub, pasarelas de pago, etc.) utilizan HTTPS/TLS.
Se utilizan protocolos y versiones seguros: TLS 1.2 o superior para todas las conexiones, cipher suites seguros configurados en NGINX Ingress, y Perfect Forward Secrecy (PFS) habilitado.
5.5 Cifrado en Reposo
Las bases de datos gestionadas (Cloud SQL, Azure PostgreSQL) utilizan cifrado en reposo proporcionado por el proveedor de nube. En GCP, Cloud SQL utiliza cifrado automático de datos en reposo. En Azure, Azure PostgreSQL Flexible Server utiliza cifrado automático con claves gestionadas por Microsoft o claves gestionadas por el cliente (CMK). Los respaldos también están cifrados.
Los objetos almacenados en buckets de GCS (documentos, reportes, etc.) utilizan cifrado en reposo. El cifrado puede ser gestionado por Google o vía claves gestionadas por el cliente (CMEK).
Los secrets de Kubernetes se almacenan cifrados en etcd. En GCP, etcd se cifra vía claves gestionadas por Google. En Azure, etcd se cifra vía claves gestionadas por Microsoft. Los secrets sensibles (contraseñas, API keys, etc.) se almacenan como Kubernetes Secrets y se inyectan en los contenedores.
Los volúmenes persistentes utilizan cifrado proporcionado por el proveedor de nube. En GCP, los Persistent Volumes utilizan cifrado automático. En Azure, los Managed Disks utilizan cifrado automático.
5.6 VPN (Red Privada Virtual)
Nota importante: La configuración de VPN es un detalle de despliegue, no parte de la aplicación Lana. Lo que se presenta a continuación son sugerencias y opciones arquitectónicas que pueden ser útiles para diferentes escenarios. Es responsabilidad del operador tomar las decisiones y diseños finales que se ajusten a las necesidades específicas de su despliegue, incluyendo requisitos de seguridad, cumplimiento y organizacionales.
El sistema puede soportar múltiples opciones de VPN para acceso administrativo y de empleados, dependiendo de la configuración elegida por el operador.
5.6.1 VPN Site-to-Site
Una opción es configurar VPN entre la oficina/red corporativa y la VPC/VNet vía Cloud VPN o Partner VPN en GCP, o VPN Gateway (Site-to-Site) en Azure. Las ventajas incluyen acceso directo a recursos internos sin exponer servicios a Internet, no se requieren IPs públicas para servicios internos, y control de acceso centralizado. Los empleados conectados a la red corporativa accederían automáticamente.
5.6.2 VPN Cliente (Point-to-Site)
Otra opción es la configuración de VPN cliente para acceso remoto, que presenta diferencias según el proveedor de nube: Cloud VPN no soporta P2S nativamente en GCP, requiriendo una solución de terceros, mientras que en Azure se puede usar VPN Gateway (Point-to-Site) con OpenVPN o IKEv2. Las ventajas incluyen acceso desde cualquier ubicación, autenticación por certificado o usuario/contraseña, y no se requiere red corporativa. Los empleados remotos se conectarían vía cliente VPN.
5.6.3 Host Bastión con VPN
Una alternativa es la configuración de VPN al host bastión con reenvío de puertos, que funcionaría así: el empleado se conecta al VPN, el VPN termina en el host bastión, y el empleado accede a servicios internos a través del bastión. Las ventajas incluyen control de acceso granular, auditoría centralizada, y no se requieren cambios en la infraestructura principal.
5.6.4 Acceso vía Bastión (SSH Tunneling)
Otra opción es la configuración de túnel SSH a través del host bastión para acceso administrativo y depuración. Por ejemplo, tunneling a la base de datos PostgreSQL vía ssh -L localhost:5432:db-internal-ip:5432 bastion-host. Las ventajas incluyen acceso seguro a recursos internos sin exponerlos a Internet.
El operador debe evaluar estas opciones y seleccionar o diseñar la solución de acceso remoto que mejor se ajuste a sus requisitos específicos de seguridad, cumplimiento y operación.
5.7 Certificados
cert-manager gestiona automáticamente los certificados SSL/TLS. Los certificados se crean como recursos de Kubernetes (Certificates), cert-manager solicita certificados a Let's Encrypt o CA interna según la configuración, los certificados se renuevan automáticamente antes de su expiración, y se almacenan como Kubernetes Secrets.
Los certificados para comunicación con bases de datos y servicios internos pueden ser gestionados por cert-manager o proporcionados manualmente. Los certificados para autenticación con servicios externos (BCR, sistemas regulatorios) se proporcionan como parte de la configuración del entorno.
6. Segmentación de Red por Entorno
La arquitectura implementa aislamiento completo entre diferentes entornos (DEV, QA, UAT, PROD). Los entornos no comparten ningún recurso de infraestructura.
Cada entorno tiene:
- Su propia VPC/VNet completamente aislada
- Su propio cluster de Kubernetes
- Sus propias instancias de base de datos
- Sus propios balanceadores de carga e IPs públicas
- Sus propias credenciales y secrets
- Sus propios dominios y certificados SSL/TLS
No hay conectividad de red directa entre entornos. No hay peering de VPC/VNet entre entornos. No hay rutas de red que permitan comunicación entre entornos. Cada entorno es completamente independiente y aislado de los demás.
7. Zonas de Seguridad
La arquitectura implementa un modelo de zonas de seguridad que segmenta la infraestructura según el nivel de exposición y los requisitos de seguridad.
7.1 Zona Pública
La zona pública contiene servicios que están expuestos a Internet y son accesibles públicamente.
Componentes:
- Balanceador de Carga: IP pública proporcionada por el proveedor de nube
- NGINX Ingress Controller: Punto de entrada para todo el tráfico HTTP/HTTPS
- Portal de Clientes: Frontend accesible públicamente (
app.{domain}) - Certificados SSL/TLS: Gestionados por cert-manager (Let's Encrypt o CA interna)
Características de Seguridad:
- TLS/SSL requerido para todas las conexiones (HTTPS)
- Geo-blocking configurado para bloquear países no soportados
- Rate limiting configurado por host
- Capacidades de WAF vía NGINX o servicios externos
- Monitoreo y alertas de tráfico anómalo
- Autenticación requerida para acceso a funcionalidades sensibles
El flujo de tráfico sigue esta ruta:
Cliente de Internet → Balanceador de Carga (IP Pública) → NGINX Ingress Controller → Servicios de Aplicación
7.2 Zona Privada
La zona privada contiene servicios que no están expuestos a Internet y solo son accesibles desde dentro de la VPC/VNet.
Componentes:
- Cluster de Kubernetes: Nodos y pods de aplicación
- Servicios Backend: APIs internas, workers, servicios de procesamiento
- Panel de Administración: Panel administrativo (accesible solo vía VPN o red privada)
- Bases de Datos PostgreSQL: Instancias de base de datos con acceso solo privado
Características de Seguridad:
- Sin IPs públicas (nodos sin IPs públicas, enable_private_nodes = true en GCP)
- Acceso solo desde dentro de la VPC/VNet
- Network Policies habilitadas (Calico en GCP, Azure Network Policy en Azure)
- Reglas de firewall restringiendo comunicación entre componentes
- TLS/SSL para comunicaciones internas
- Autenticación y autorización vía Keycloak y Oathkeeper
El flujo de tráfico sigue esta ruta:
Servicios Internos → Network Policies → Servicios de Aplicación → Bases de Datos (PostgreSQL)
7.3 Zona de Administración
La zona de administración contiene recursos para acceso administrativo y gestión de infraestructura.
Componentes:
- Hosts Bastión: Hosts en subred DMZ para acceso administrativo
- API de Kubernetes: Endpoint privado del cluster (no accesible desde Internet)
- Herramientas de Gestión: Helm, kubectl, herramientas de CI/CD
Características de Seguridad:
- Hosts bastión en subred DMZ aislada
- Acceso a API de Kubernetes restringido a hosts bastión y redes autorizadas
- Autenticación fuerte requerida (claves SSH, certificados)
- Auditoría de acceso administrativo
- Acceso vía VPN o SSH tunneling
- Rotación regular de credenciales y claves
El flujo de acceso sigue esta ruta:
Administrador → VPN/SSH → Host Bastión → API de Kubernetes / Servicios Internos
7.4 Zona de Respaldos
La zona de respaldos contiene sistemas y almacenamiento para respaldos de datos.
Componentes:
- Respaldos de Base de Datos: Respaldos automáticos gestionados por el proveedor de nube
- Almacenamiento de Respaldos: Buckets de GCS o Azure Blob Storage para respaldos
- Recuperación Point-in-Time: Habilitada para bases de datos críticas
Características de Seguridad:
- Respaldos cifrados en reposo
- Respaldos geo-redundantes (multirregión) para redundancia crítica
- Retención configurable (7-35 días según el entorno)
- Acceso restringido a respaldos (solo servicios autorizados)
- Rotación automática de respaldos antiguos
- Pruebas de restauración periódicas
En GCP Cloud SQL, los respaldos automáticos están habilitados, la recuperación point-in-time está habilitada, y los respaldos son multirregión. En Azure PostgreSQL, los respaldos automáticos tienen retención configurable y los respaldos geo-redundantes son opcionales.
7.5 Zona de Monitoreo
La zona de monitoreo contiene sistemas de observabilidad, logging y alertas.
Componentes:
- OpenTelemetry Collector: Recopila métricas, logs y trazas
- Honeycomb: Agregación y análisis de datos de telemetría
- Sistemas de Alertas: Integración con sistemas de pager/on-call (Zenduty, PagerDuty, etc.)
- Logs de Aplicación: Logs de pods y servicios de Kubernetes
Características de Seguridad:
- Comunicación cifrada con servicios de monitoreo externos (TLS/SSL)
- API keys almacenadas como Kubernetes Secrets
- Acceso restringido a dashboards y datos de monitoreo
- Retención de logs configurable
- Anonimización de datos sensibles en logs
El flujo de datos sigue esta ruta:
Aplicaciones → OpenTelemetry Collector → Honeycomb → Alertas → Sistemas de Pager/OnCall
7.6 Comunicación Entre Zonas
Nota importante: Muchos de los detalles sobre comunicación entre zonas, acceso administrativo, almacenamiento de respaldos y monitoreo son detalles de despliegue, no parte de la aplicación Lana. Lo que se presenta a continuación son sugerencias y consideraciones arquitectónicas. El diseño, implementación y operación final de estos aspectos es responsabilidad del operador de despliegue, quien debe adaptarlos a sus requisitos específicos de seguridad, cumplimiento y operación.
7.6.1 Definiciones de Zonas
Zona Pública: Contiene aplicaciones web e integraciones/APIs accesibles desde WAN (Wide Area Network). El acceso a estas aplicaciones se controla desde INGRESS, que actúa como punto de entrada y aplica reglas de autenticación, autorización y seguridad.
Zona Privada: Todos los servicios de aplicación están en la red privada. Estos servicios no están expuestos directamente a Internet y solo son accesibles desde dentro de la VPC/VNet o a través de mecanismos de acceso controlado.
7.6.2 Comunicación de Zona Pública a Zona Privada
La comunicación de la Zona Pública a la Zona Privada se realiza vía tráfico HTTP/HTTPS desde Internet pasando por el Balanceador de Carga, luego el NGINX Ingress Controller, y finalmente los Servicios de Aplicación. La autenticación y autorización se realiza vía Oathkeeper antes de acceder a los servicios privados.
7.6.3 Acceso a Zona Privada (Detalle de Despliegue)
Cómo organizar el acceso administrativo y de empleados a la Zona Privada (vía hosts bastión, VPN, SSH tunneling, etc.) es un detalle de despliegue que debe ser diseñado e implementado por el operador según sus necesidades específicas. El operador debe considerar factores como requisitos de seguridad, políticas organizacionales, cumplimiento y preferencias de acceso remoto.
7.6.4 Almacenamiento de Respaldos (Detalle de Despliegue)
Cómo almacenar respaldos de forma segura y privada es un detalle de despliegue. El operador debe diseñar e implementar la estrategia de respaldos que mejor se ajuste a sus requisitos, incluyendo consideraciones sobre cifrado, redundancia geográfica, retención y acceso restringido.
7.6.5 Monitoreo (Detalle de Despliegue)
La configuración y operación de sistemas de monitoreo, observabilidad y alertas es un detalle de despliegue. El operador debe seleccionar e implementar las herramientas y servicios de monitoreo que mejor se ajusten a sus necesidades, incluyendo consideraciones sobre dónde almacenar métricas y logs, cómo configurar alertas, y qué nivel de observabilidad se requiere.
7.6.6 Restricciones de Comunicación
Existen restricciones importantes en el diseño de zonas: típicamente no hay comunicación directa de la zona pública a la zona de administración, no hay comunicación directa de la zona pública a la zona de respaldos, y la comunicación entre zonas se controla mediante reglas de firewall y políticas de red. Sin embargo, el diseño específico de estas restricciones y controles es responsabilidad del operador de despliegue.
8. Auditoría
El sistema de auditoría es un componente transversal que registra todas las acciones realizadas en el sistema, proporcionando trazabilidad completa para el cumplimiento regulatorio y la investigación de incidentes.
8.1 Estructura de Entrada de Auditoría
Cada entrada de auditoría captura cuatro dimensiones fundamentales:
-
Sujeto: Quién realizó la acción. Puede ser un usuario identificado por su UUID (cuando opera a través del Panel de Administración) o el propio sistema (para operaciones automáticas como trabajos de acumulación de intereses o procesamiento de webhooks).
-
Objeto: Sobre qué se realizó la acción. Los objetos son tipados y pueden referirse a entidades específicas (un cliente particular, una facilidad de crédito específica) o categorías completas (todos los clientes, todas las facilidades). El formato incluye el tipo de entidad y su identificador, por ejemplo
customer/550e8400-e29b-41d4-a716-446655440000ocredit-facility/all. -
Acción: Qué tipo de operación se intentó. Las acciones se categorizan por módulo y entidad, siguiendo un formato como
customer:read,credit-facility:create,withdrawal:approve. Cada módulo define sus propias acciones posibles. -
Autorizado: Si la operación fue permitida o denegada. El sistema registra incluso los intentos de acceso fallidos, lo que permite detectar patrones de intentos no autorizados.
Adicionalmente, cada entrada tiene una marca de tiempo de cuándo se registró y un identificador secuencial único.
8.2 Integración con el Flujo de Operaciones
El sistema de auditoría está directamente integrado en el flujo de autorización. Cuando un usuario intenta realizar una operación, el sistema de permisos (RBAC) verifica si tiene los permisos necesarios y simultáneamente registra la entrada de auditoría. Esta integración garantiza que ninguna operación, exitosa o fallida, escape del registro.
Para operaciones que ocurren dentro de transacciones de base de datos, el sistema soporta el registro de auditoría transaccional: la entrada de auditoría se inserta en la misma transacción que la operación de negocio, garantizando consistencia. Si la transacción falla, la entrada de auditoría también se revierte.
Las operaciones del sistema (no iniciadas por usuarios) se registran con un sujeto especial "system", permitiendo distinguir entre acciones humanas y automatizadas. Esto es importante para operaciones como la transición automática de obligaciones a estado "vencida" o "morosa", la sincronización de colateral desde webhooks de custodios, o la acumulación de intereses.
8.3 Correlación con Tracing
El sistema de auditoría se integra con el contexto de tracing distribuido. Cuando se registra una entrada de auditoría, se asocia con el span actual de OpenTelemetry. Esto permite correlacionar una entrada de auditoría específica con la traza completa de la operación, incluyendo todas las llamadas internas, consultas a base de datos y comunicaciones con servicios externos que ocurrieron como parte de esa operación.
8.4 Consulta del Log de Auditoría
El log de auditoría es consultable a través de la API GraphQL del Panel de Administración, permitiendo a los operadores autorizados (con el permiso audit:list) buscar y filtrar entradas. La paginación es basada en cursor para manejar eficientemente grandes volúmenes de datos. Las entradas se ordenan por ID descendente, mostrando las más recientes primero.
9. Flujo de Préstamo Respaldado por Bitcoin
Para ilustrar cómo interactúan los módulos, este es el flujo típico de un préstamo:
9.1 1. Propuesta y Aprobación
-
PROPUESTA: El cliente solicita una propuesta de crédito, que ingresa a un proceso de aprobación gestionado por el módulo de gobernanza.
-
APROBACIÓN: El comité asignado vota para aprobar la propuesta. Cuando se alcanza el umbral de aprobación, se crea una PendingCreditFacility.
9.2 2. Colateralización y Activación
-
COLATERALIZACIÓN: El cliente deposita Bitcoin como colateral a través del custodio configurado. Los webhooks del custodio mantienen automáticamente sincronizado el balance del colateral, y el sistema recalcula el CVL.
-
ACTIVACIÓN: Cuando el CVL alcanza el umbral inicial configurado en los términos, la facilidad se activa automáticamente.
9.3 3. Desembolsos y Vida del Préstamo
-
DESEMBOLSO: El cliente puede solicitar desembolsos, cada uno pasando por su propio proceso de aprobación. Cuando se ejecuta, los fondos se acreditan en la cuenta de depósito del cliente y se crea una Obligation que representa la deuda.
-
VIDA DEL PRÉSTAMO: Trabajos periódicos calculan y registran los intereses acumulados según los intervalos configurados, generando nuevas obligaciones por intereses acumulados.
-
PAGOS: Cuando el cliente realiza un Payment, el sistema asigna automáticamente los fondos a las obligaciones pendientes en orden de prioridad vía PaymentAllocation, típicamente priorizando las obligaciones más antiguas y los intereses sobre el principal.
-
CIERRE: Cuando todas las obligaciones están liquidadas, la facilidad puede cerrarse y el colateral en Bitcoin se libera al cliente.
9.4 4. Monitoreo de CVL y Gestión de Riesgo
A lo largo de todo el ciclo de vida, el sistema monitorea continuamente el CVL. Si cae por debajo del umbral de margin call, la facilidad entra en estado de alerta. Si cae por debajo del umbral de liquidación, se inicia un LiquidationProcess donde el banco puede ejecutar el colateral para recuperar la deuda.
9.5 Notas Adicionales
9.5.1 Configuración por Cliente
Diferentes clientes pueden tener configuraciones específicas de integraciones externas, zonas de seguridad y segmentación de red según sus requisitos regulatorios y de negocio.
9.5.2 Actualizaciones y Mantenimiento
Las actualizaciones de componentes de seguridad (Keycloak, Oathkeeper, cert-manager, etc.) se gestionan vía Helm charts y se aplican de manera controlada en cada entorno.
9.5.3 Cumplimiento Regulatorio
La arquitectura está diseñada para cumplir con requisitos regulatorios bancarios, incluyendo:
- Aislamiento de datos por entorno
- Cifrado de datos en tránsito y en reposo
- Auditoría y logging de acceso
- Respaldos y recuperación ante desastres
- Integración con sistemas regulatorios
10. Portabilidad y Dependencia de Proveedor
10.1 Portabilidad del Cluster de Kubernetes
La aplicación está diseñada para desplegarse en un cluster de Kubernetes agnóstico a cualquier proveedor de nube. No hay dependencia de proveedor por usar servicios propietarios de ningún proveedor, ya que la arquitectura utiliza componentes y servicios estándar de Kubernetes que pueden ser reemplazados por alternativas equivalentes. Algunos servicios no gestionados vía Kubernetes, como bases de datos Postgres, pueden desplegarse en hosts genéricos.
La aplicación puede desplegarse on-premise sin modificaciones significativas. Sin embargo, el gestor de infraestructura física necesitará abordar aspectos críticos que los proveedores de nube gestionan automáticamente: implementar estrategias de respaldo equivalentes, asegurar alta disponibilidad mediante redundancia de hardware y componentes, implementar replicación de datos a ubicaciones geográficamente separadas (replicación offsite), y gestionar mantenimiento, actualizaciones y monitoreo de hardware.
Los componentes principales son portables y pueden ejecutarse en cualquier entorno compatible con Kubernetes:
- Cluster de Kubernetes (cualquier distribución: GKE, AKS, EKS, Rancher, k3s, etc.)
- PostgreSQL (Cloud SQL, Azure PostgreSQL, o instancias gestionadas on-premise)
- Ingress Controller (NGINX Ingress)
- Helm Charts (estándar de Kubernetes)
- Aplicaciones containerizadas (Docker)
Los componentes específicos del proveedor pueden reemplazarse: los Balanceadores de Carga con soluciones on-premise o alternativas, los Persistent Volumes pueden usar cualquier clase de almacenamiento compatible con Kubernetes, y las VPC/VNet pueden reemplazarse por redes físicas o SDN (Software Defined Networking).
11. Servidores / Instancias
11.1 Tipos de Instancias
Actualmente, la infraestructura se despliega en dos proveedores de nube: Google Cloud Platform (GCP) y Microsoft Azure. Para estos dos proveedores podemos ofrecer asesoramiento muy específico y configuraciones detalladas, ya que son los entornos en los que tenemos experiencia operativa directa. Sin embargo, la arquitectura es portable y la aplicación puede ajustarse para otros proveedores (como AWS, Oracle Cloud, etc.) o sistemas on-premise.
11.1.1 Instancias de Aplicación (Nodos de Kubernetes)
En GCP, los nodos de Kubernetes utilizan el tipo de máquina n2-standard-4 por defecto, proporcionando 4 vCPUs, 16 GB de RAM y 100 GB de disco (pd-standard). El cluster se configura con autoescalado permitiendo entre 1 y 3 nodos (configurable por entorno). Los nodos utilizan la imagen COS_CONTAINERD (Container-Optimized OS con containerd) y se distribuyen automáticamente a través de múltiples zonas dentro de la región para redundancia.
En Azure, los nodos utilizan Standard_DS2_v2 por defecto (2 vCPUs, 7 GB RAM, disco SSD premium) o Standard_B1s para entornos de desarrollo/staging (1 vCPU, 1 GB RAM). El autoescalado también permite entre 1 y 3 nodos según la configuración.
11.1.2 Instancias de Base de Datos
Las bases de datos utilizan una arquitectura de instancia única por base de datos, diseñada para escalado vertical (aumentar CPU, RAM y almacenamiento) en lugar de escalado horizontal. Se recomienda activar las opciones de autoescalado del proveedor de nube para expandir el almacenamiento proporcionalmente al crecimiento de la base de datos.
En GCP, las instancias utilizan Cloud SQL para PostgreSQL (Enterprise Edition) con un tier por defecto de db-custom-1-3840 (1 vCPU, 3.75 GB RAM). El almacenamiento comienza en 100 GB y debe expandirse según el uso. La alta disponibilidad es configurable vía highly_available = true/false, permitiendo modo ZONAL (sin redundancia) o REGIONAL (con redundancia entre zonas).
En Azure, las instancias utilizan Azure Database for PostgreSQL Flexible Server con SKU por defecto GP_Standard_D2s_v3 (2 vCPUs, 8 GB RAM). El almacenamiento también comienza en 100 GB y es expandible. La alta disponibilidad se configura vía geo_redundant_backup_enabled y las instancias se ubican en Zona 1 por defecto (configurable).
11.1.3 Instancias Bastión
Los hosts bastión proporcionan acceso administrativo seguro a la infraestructura. En GCP utilizan el tipo de máquina e2-small (2 vCPUs compartidas, 2 GB RAM) con Ubuntu 22.04 LTS. En Azure utilizan Standard_DS1_v2 (1 vCPU, 3.5 GB RAM, 7 GB SSD) también con Ubuntu 22.04 LTS.
11.1.4 Instancias de Aplicación (Stateless)
Los elementos stateless (servidor backend, servidor de autenticación, servidores de frontend de aplicación, workers, etc.) se ejecutan como pods en Kubernetes y pueden escalar horizontalmente. Se recomienda comenzar con 1 réplica por servicio y aumentar el número de réplicas según la carga necesaria.
Los workers tienen recursos configurados con requests de 1000m CPU (1 core) y 1000Mi-1500Mi de memoria, con limits de 2000m-3000m CPU y 3000Mi-4000Mi de memoria, dependiendo del entorno.
11.2 Almacenamiento Estimado
Los nodos de Kubernetes utilizan 100 GB de disco de sistema por nodo (pd-standard en GCP), resultando en un almacenamiento total estimado de 100-300 GB dependiendo del número de nodos.
Para bases de datos, se recomienda comenzar con 100 GB por instancia. El almacenamiento es proporcional al crecimiento de la base de datos, y se recomienda activar las opciones de autoescalado del proveedor de nube para expandir el almacenamiento automáticamente con el uso de la aplicación. En GCP Cloud SQL no hay un límite específico configurado en código (depende del tier), mientras que en Azure PostgreSQL es configurable comenzando con 100 GB.
Los volúmenes persistentes se crean según sea necesario para aplicaciones específicas (por ejemplo, Meltano). Es importante notar que toda la persistencia se gestiona con PostgreSQL; no se utilizan otros sistemas de almacenamiento persistente como Redis o MongoDB.
11.3 Redundancia
Los clusters de Kubernetes en GCP distribuyen automáticamente los nodos a través de múltiples zonas dentro de la región. En Azure, los nodos se distribuyen en Availability Sets/Zones según la configuración. Ambos proveedores tienen auto-repair habilitado, pero auto-upgrade está deshabilitado para permitir actualizaciones manuales controladas.
Para bases de datos, es crítico activar respaldos redundantes multirregión para evitar pérdida de datos que podría ser desastrosa para las operaciones del banco. En GCP, esto se logra mediante alta disponibilidad con availability_type = "REGIONAL" (cuando está habilitada), recuperación point-in-time habilitada, respaldos automáticos habilitados, y configuración de respaldos multirregión para redundancia crítica. En Azure, debe habilitarse geo_redundant_backup_enabled = true, con retención de respaldos configurable entre 7-35 días.
Los servicios de aplicación se ejecutan como deployments de Kubernetes con múltiples réplicas cuando es necesario. Por ejemplo, Oathkeeper tiene 2 réplicas por defecto para alta disponibilidad.
12. Sistemas Operativos
12.1 Versiones Compatibles y Certificadas
El sistema está diseñado para ejecutarse en entornos Linux. Todo se gestiona con imágenes Docker que utilizan Nix para crear entornos determinísticos, asegurando reproducibilidad y consistencia entre diferentes entornos.
Los nodos de Kubernetes en GCP utilizan Container-Optimized OS (COS) con containerd, con versión específica gestionada por GKE y compatible con Kubernetes 1.32.9-gke.1548000 (versión por defecto). En Azure, los nodos utilizan Ubuntu (versión gestionada por AKS) compatible con Kubernetes 1.30.9 (versión por defecto).
Los hosts bastión utilizan Ubuntu 22.04 LTS (Jammy Jellyfish), certificado y probado en ambos proveedores. En GCP se utiliza la imagen ubuntu-2204-lts y en Azure 0001-com-ubuntu-server-jammy.
Los contenedores de CI/CD utilizan Ubuntu como base (sin especificar versión LTS específica en Dockerfile) y también utilizan Docker con Nix para entornos determinísticos.
13. Bases de Datos
13.1 Tipo y Versión
El sistema utiliza exclusivamente PostgreSQL como sistema de gestión de bases de datos. La versión recomendada varía según el proveedor: en GCP se utiliza PostgreSQL 17 (POSTGRES_17) como versión por defecto, aunque PostgreSQL 15 (POSTGRES_15) se utiliza en el staging de Lana Bank. En Azure, la versión por defecto es PostgreSQL 16 (16), aunque PostgreSQL 14 también es soportado.
En GCP se utiliza Cloud SQL para PostgreSQL (Enterprise Edition), mientras que en Azure se utiliza Azure Database for PostgreSQL Flexible Server.
13.2 Parámetros de Seguridad
Todas las instancias de base de datos se configuran con acceso solo privado. El acceso público IPv4 está deshabilitado (ipv4_enabled = false) y todas las instancias están conectadas a VPC/VNet privada. SSL/TLS es requerido para todas las conexiones (sslmode = "require" en Azure).
Los usuarios administradores se generan automáticamente con contraseñas aleatorias de 20 caracteres. Los usuarios de aplicación se crean por base de datos con permisos específicos, y por defecto no tienen permisos para crear bases de datos (user_can_create_db = false).
El logging detallado es opcional (enable_detailed_logging). Cuando está habilitado, se configura log_statement = "all" (registra todas las sentencias SQL) y log_lock_waits = "on" (registra esperas de bloqueo). El logging estándar está habilitado por defecto.
13.3 Replicación
La replicación lógica puede habilitarse vía replication = true. En GCP requiere cloudsql.logical_decoding = "on" y cloudsql.enable_pglogical = "on", mientras que en Azure requiere wal_level = "logical".
No es estrictamente necesario usar réplicas de lectura, pero se aconseja en caso de que aparezcan necesidades de consulta de datos desde aplicaciones externas, con el objetivo de no sobrecargar las instancias de escritura de la base de datos. En GCP, las réplicas de lectura se soportan vía provision_read_replica = true, que pueden ser públicas o privadas (public_read_replica). En Azure no hay configuración explícita de réplica de lectura en el código actual.
13.4 Respaldos
En GCP Cloud SQL, los respaldos automáticos están habilitados por defecto (enabled = true), junto con la recuperación point-in-time habilitada (point_in_time_recovery_enabled = true). La retención es gestionada por GCP (típicamente 7 días para respaldos automáticos) y la frecuencia es diaria.
En Azure PostgreSQL, los respaldos automáticos están habilitados con retención configurable entre 7-35 días vía backup_retention_days. Los respaldos geo-redundantes son opcionales vía geo_redundant_backup_enabled, y la frecuencia es gestionada por Azure.
13.5 Bases de Datos por Aplicación
Toda la persistencia se gestiona con PostgreSQL.
Para Lana Bank, las bases de datos principales incluyen lana-bank (base de datos principal de la aplicación), meltano (para ETL y pipelines de datos), airflow (para orquestación de flujos de trabajo), dagster (para gestión de datos), y keycloak (para autenticación y autorización).
Cada aplicación puede tener múltiples instancias de PostgreSQL: una instancia para Lana Bank, una instancia para Meltano (que puede incluir múltiples bases de datos), y una instancia para Keycloak.
14. Middleware / Integración
14.1 Kubernetes y Orquestación
El sistema utiliza Kubernetes para la orquestación de contenedores. En GCP se utiliza la versión 1.32.9-gke.1548000 (por defecto) y en Azure la versión 1.30.9 (por defecto). Las Network Policies están habilitadas (Calico en GCP, Azure Network Policy en Azure). En GCP, también se habilitan Binary Authorization y Shielded Nodes (Secure Boot e Integrity Monitoring). Helm versión 3.x se instala en hosts bastión para la gestión de charts.
14.2 Ingress y Balanceo de Carga
El sistema utiliza NGINX Ingress Controller (chart ingress-nginx versión 4.14.0 del repositorio https://kubernetes.github.io/ingress-nginx) para proporcionar ingress controller para Kubernetes. El servicio de ingress se configura como tipo LoadBalancer, exponiendo una IP pública que recibe tráfico HTTP/HTTPS desde Internet.
14.3 Certificados SSL/TLS
Los certificados SSL/TLS se gestionan automáticamente por cert-manager (chart versión v1.19.1 del repositorio https://charts.jetstack.io), que puede usar Let's Encrypt o una CA interna según la configuración.
14.4 Autenticación y Autorización
El sistema utiliza Keycloak (chart keycloakx versión 7.1.1 del repositorio https://codecentric.github.io/helm-charts) como servidor de identidad y acceso (IAM), con una base de datos PostgreSQL dedicada.
Oathkeeper (chart versión 0.49.2 del repositorio https://k8s.ory.sh/helm/charts) actúa como proxy de autenticación y autorización con 2 réplicas por defecto para alta disponibilidad.
OAuth2 Proxy (chart versión 7.13.0 del repositorio https://oauth2-proxy.github.io/manifests) proporciona proxy de autenticación OAuth2.
14.5 Observabilidad y Monitoreo
OpenTelemetry Collector (chart versión 0.138.1 del repositorio https://open-telemetry.github.io/opentelemetry-helm-charts) recopila métricas, logs y trazas, integrado con Honeycomb para análisis de datos.
14.6 Pipeline de Datos y ETL
Dagster (chart versión 1.12.1 del repositorio https://dagster-io.github.io/helm) orquesta pipelines de datos con una base de datos PostgreSQL dedicada.
Meltano proporciona ETL y gestión de datos, también con una base de datos PostgreSQL dedicada e integración con Airflow para orquestación.
Airflow orquesta flujos de trabajo utilizando PostgreSQL (compartido con Meltano o dedicado según la configuración).
14.7 PostgreSQL (Helm Chart)
Para PostgreSQL in-cluster (a diferencia de instancias gestionadas de Cloud SQL/Azure PostgreSQL), se utiliza el chart Bitnami PostgreSQL versión 16.4.13 (repositorio https://charts.bitnami.com/bitnami) con la imagen bitnamilegacy/postgresql:14.5.0-debian-11-r35.
14.8 Dependencias de Aplicación
El proyecto utiliza Semantic Versioning (SemVer) para todas las versiones de aplicación, charts y dependencias.
Para Lana Bank, la versión de aplicación es 0.12.3 con versión de chart 0.1.1-dev. Las dependencias incluyen PostgreSQL (Bitnami) 16.4.13, Oathkeeper 0.49.2, Keycloakx 7.1.1, Dagster 1.12.1, y OAuth2 Proxy 7.13.0.
Para Galoy Dependencies, la versión de chart es 0.10.20-dev con dependencias que incluyen cert-manager v1.19.1, ingress-nginx 4.14.0, kube-monkey 1.5.2, y opentelemetry-collector 0.138.1.
14.9 Configuración Recomendada
Los recursos de pods varían según el componente. Los workers tienen recursos definidos en la sección 11.1.4. El Ingress Controller tiene recursos definidos en ingress-scaling.yml, el OpenTelemetry Collector en otel-scaling.yml, y Kube Monkey utiliza recursos mínimos (5m CPU, 25Mi de memoria).
14.10 Arquitectura de Red (Networking)
14.10.1 Topología de Red
En GCP, la red privada (VPC) utiliza modo de enrutamiento REGIONAL con nombre {name_prefix}-vpc y creación automática de subredes deshabilitada para control manual. La subred DMZ ({name_prefix}-dmz) utiliza CIDR {network_prefix}.0.0/24 (ejemplo: 10.1.0.0/24) para hosts bastión y acceso administrativo, con Private Google Access habilitado. La subred del cluster ({name_prefix}-cluster) utiliza CIDR {network_prefix}.0.0/17 (ejemplo: 10.1.0.0/17) para nodos de Kubernetes, con rangos de IP secundarios para pods (192.168.0.0/18) y servicios (192.168.64.0/18), también con Private Google Access habilitado. Opcionalmente hay una subred para Docker Host ({name_prefix}-docker-host) con CIDR 10.2.0.0/24 para hosts Docker de CI/CD.
En Azure, la red virtual (VNet) utiliza nombre {name_prefix}-vnet con espacio de direcciones {network_prefix}.0.0/15 (ejemplo: 10.1.0.0/15). La subred DMZ ({name_prefix}-dmz) utiliza CIDR {network_prefix}.0.0/24 para hosts bastión. La subred del cluster ({name_prefix}-cluster) aloja nodos de Kubernetes (AKS) con Service CIDR 192.168.64.0/18 y DNS Service IP 192.168.64.10. La subred PostgreSQL ({name_prefix}-postgres) utiliza CIDR {network_prefix}.3.0/24 (ejemplo: 10.1.3.0/24) con delegación a Microsoft.DBforPostgreSQL/flexibleServers y un Network Security Group asociado con reglas para PostgreSQL (puerto 5432).
14.10.2 Conectividad y NAT
En GCP, Cloud NAT está habilitado para permitir tráfico de salida a Internet desde subredes privadas. El router (nombrado {name_prefix}-router) utiliza NAT IP Allocation AUTO_ONLY y se aplica a ALL_SUBNETWORKS_ALL_IP_RANGES con BGP ASN 64514. VPC Peering está configurado para servicios gestionados de GCP con un rango /16 reservado para servicios de Google vía servicenetworking.googleapis.com.
En Azure, los Network Security Groups (NSG) proporcionan reglas de firewall para controlar el tráfico, con NSG de PostgreSQL permitiendo tráfico desde VirtualNetwork al puerto 5432. Se utilizan Private DNS Zones para resolución de nombres de servicios gestionados, incluyendo privatelink.postgres.database.azure.com para PostgreSQL.
14.10.3 Reglas de Firewall
En GCP, las reglas de firewall incluyen Egress Intra-cluster que permite comunicación entre pods y con el master (protocolos TCP, UDP, ICMP, SCTP, ESP, AH) hacia CIDR del Master, Subred del Cluster, Rango de Pods y Rango de Servicios. Ingress de Webhooks permite al master llamar webhooks en pods (puertos 8443, 443) desde CIDR del Master. DMZ a Nodos permite acceso desde el bastión a nodos del cluster (todos los protocolos) desde la subred DMZ.
En Azure, los Network Security Groups proporcionan reglas de seguridad por subred, con PostgreSQL permitiendo solo tráfico desde VirtualNetwork.
14.10.4 Clusters Privados
La API de Kubernetes utiliza endpoints privados (no accesibles desde Internet). En GCP se configura con enable_private_endpoint = true y en Azure con private_cluster_enabled = true. El acceso a la API se restringe a hosts bastión (subred DMZ) y redes autorizadas (master authorized networks en GCP). Los nodos no tienen IPs públicas: en GCP con enable_private_nodes = true y en Azure vía nodos en subred privada.
14.11 Acceso desde WAN y VPN
14.11.1 Acceso Público a Frontends (WAN)
La arquitectura de Ingress utiliza NGINX Ingress Controller con tipo de servicio LoadBalancer, exponiendo una IP pública proporcionada por el proveedor de nube que recibe tráfico HTTP/HTTPS desde Internet.
El flujo de tráfico WAN sigue esta secuencia:
Cliente de Internet → Balanceador de Carga (IP Pública) → Ingress Controller (NGINX) → Servicios de Aplicación (según reglas de enrutamiento)
La configuración de Ingress incluye TLS/SSL con certificados gestionados por cert-manager (Let's Encrypt o CA interna). Los hosts configurados incluyen Portal de Clientes (por ejemplo, app.example.com), Panel de Administración (por ejemplo, admin.example.com), y Dagster (por ejemplo, dagster.example.com). La autenticación está integrada con OAuth2 Proxy y Oathkeeper, y el rate limiting está configurado por host (solicitudes por minuto, conexiones).
La seguridad de acceso WAN incluye geo-blocking (bloqueo de países no soportados configurado en NGINX), autenticación OAuth2/OIDC para acceso a paneles administrativos, TLS para todas las conexiones (HTTPS), y posibilidad de configurar WAF vía anotaciones de NGINX o servicios externos.
14.11.2 Acceso vía VPN (Empleados)
Existen varias opciones para acceso VPN:
Opción 1: VPN Site-to-Site - Configuración de VPN entre la oficina/red corporativa y la VPC/VNet. En GCP se utiliza Cloud VPN o Partner VPN, y en Azure VPN Gateway (Site-to-Site). Las ventajas incluyen acceso directo a recursos internos sin exponer servicios a Internet, no se requieren IPs públicas para servicios internos, y control de acceso centralizado. Los empleados conectados a la red corporativa acceden automáticamente.
Opción 2: VPN Cliente (Point-to-Site) - Configuración de VPN cliente para acceso remoto. En GCP, Cloud VPN no soporta P2S nativamente y requiere una solución de terceros. En Azure se utiliza VPN Gateway (Point-to-Site) con OpenVPN o IKEv2. Las ventajas incluyen acceso desde cualquier ubicación, autenticación por certificado o usuario/contraseña, y no se requiere red corporativa. Los empleados remotos se conectan vía cliente VPN.
Opción 3: Host Bastión con VPN - Configuración de VPN al host bastión con reenvío de puertos. El flujo es: el empleado se conecta al VPN, el VPN termina en el host bastión, y el empleado accede a servicios internos a través del bastión. Las ventajas incluyen control de acceso granular, auditoría centralizada, y no se requieren cambios en la infraestructura principal.
Opción 4: Acceso vía Bastión (SSH Tunneling) - Configuración de túnel SSH a través del host bastión para acceso administrativo y depuración. Por ejemplo, tunneling a la base de datos PostgreSQL vía ssh -L localhost:5432:db-internal-ip:5432 bastion-host.
14.11.3 Recomendaciones de Seguridad
Para acceso WAN, se recomienda siempre usar HTTPS/TLS, implementar rate limiting, configurar WAF (Web Application Firewall), monitorear y alertar sobre tráfico anómalo, e implementar autenticación fuerte (2FA) para paneles administrativos.
Para acceso VPN, se recomienda usar autenticación fuerte (certificados + 2FA), implementar segmentación de red (acceso solo a recursos necesarios), monitorear conexiones VPN, rotar credenciales y certificados regularmente, y considerar Zero Trust Network Access (ZTNA) para acceso más granular.
La arquitectura híbrida recomendada expone solo servicios que requieren acceso público (portal de clientes) como frontends públicos. Los backends y paneles de administración tienen acceso solo vía VPN o red privada. Las bases de datos nunca se exponen a Internet, con acceso solo desde aplicaciones dentro del cluster y administradores vía VPN + bastión.
15. Servicios Externos
La aplicación está diseñada para integrarse con varios servicios externos que proporcionan funcionalidades especializadas. Estos servicios no son parte de la infraestructura desplegada pero son componentes críticos del ecosistema operacional.
Es importante enfatizar que estos servicios deben ser configurados externamente por el cliente o el equipo de operaciones. Lana Bank simplemente espera recibir las credenciales, tokens, endpoints y otra información de configuración necesaria para integrarse con estos servicios. La aplicación no gestiona la creación, configuración o administración de cuentas en estos servicios externos; solo consume sus APIs y servicios una vez que están configurados y disponibles.
15.1 Sumsub para KYC/KYB
Sumsub se utiliza para gestionar los procesos y datos de KYC (Know Your Customer) y KYB (Know Your Business). Este servicio externo maneja la verificación de identidad de clientes y empresas, incluyendo validación de documentos, verificación biométrica y cumplimiento regulatorio.
Para integrar Sumsub, es necesario configurar una cuenta en el servicio de Sumsub y obtener credenciales de API (API key, API secret), así como los endpoints correspondientes. Lana Bank espera recibir estas credenciales y endpoints como parte de la configuración del entorno, y se integra con Sumsub a través de su API para enviar solicitudes de verificación y recibir resultados de los procesos de incorporación y verificación continua.
15.2 Honeycomb para Observabilidad
Honeycomb se utiliza para la agregación y explotación de datos de OpenTelemetry, así como para la generación de alertas que se integran con software de gestión de pager/on-call. El sistema utiliza el protocolo OpenTelemetry (OTEL) para enviar métricas, logs y trazas desde el OpenTelemetry Collector hacia Honeycomb.
Para integrar Honeycomb, es necesario configurar una cuenta en el servicio y obtener la API key y el dataset correspondiente. Lana Bank espera recibir estas credenciales como parte de la configuración del entorno. Una vez configurado, el OpenTelemetry Collector envía automáticamente datos de telemetría al servicio.
Es importante notar que, aunque actualmente se utiliza Honeycomb, la aplicación usa el protocolo estándar OTEL, lo que permite migrar a otros proveedores que soporten OpenTelemetry sin modificaciones significativas a la aplicación. Los proveedores alternativos compatibles incluyen Datadog, New Relic, Grafana Cloud, y otros servicios que soporten el protocolo OTEL. En todos los casos, la configuración del servicio externo (creación de cuenta, obtención de credenciales, configuración de datasets, etc.) debe hacerse externamente antes de proporcionar las credenciales a Lana Bank.
Honeycomb proporciona capacidades de análisis de datos a través de consultas avanzadas, detección de anomalías y creación de dashboards personalizados. Adicionalmente, el sistema de alertas de Honeycomb se integra con sistemas de gestión de pager/on-call (como PagerDuty, Opsgenie o Zenduty) para notificar al equipo de operaciones sobre incidentes y anomalías detectadas. La configuración de estas integraciones de alertas también debe hacerse externamente en el servicio de Honeycomb.
15.3 BigQuery para Almacenamiento de Datos de Reportes
BigQuery se utiliza como almacenamiento de datos analíticos y de reportes. El sistema utiliza BigQuery para almacenar datos transformados desde las bases de datos operacionales de PostgreSQL, permitiendo análisis y reportes sin impactar el rendimiento de la base de datos transaccional.
La aplicación utiliza BigQuery en conjunto con herramientas ETL (Meltano) y transformación de datos (dbt) para cargar y transformar datos desde PostgreSQL a BigQuery. El sistema crea datasets en BigQuery para almacenar datos transformados, y utiliza conexiones de BigQuery a Cloud SQL para leer datos directamente desde PostgreSQL cuando es necesario.
Para integrar BigQuery, es necesario configurar el servicio en GCP (creación de datasets, configuración de permisos, creación de cuenta de servicio, etc.) y proporcionar a Lana Bank las credenciales necesarias, incluyendo el JSON de cuenta de servicio, ID de proyecto y nombres de datasets. La aplicación espera recibir estas credenciales como parte de la configuración del entorno.
Es importante notar que, aunque actualmente se utiliza BigQuery, la aplicación puede refactorizarse para realizar el mismo trabajo en otras bases de datos analíticas. El código ETL y de transformación puede adaptarse para trabajar con alternativas como Amazon Redshift, Snowflake, Azure Synapse Analytics, o incluso bases de datos analíticas on-premise. La arquitectura de datos está diseñada para que la capa de almacenamiento analítico pueda intercambiarse sin afectar significativamente la lógica de negocio, aunque requerirá trabajo de desarrollo para adaptar conectores y transformaciones a la nueva plataforma elegida.
En entornos Azure, donde BigQuery no está disponible, se pueden usar alternativas nativas como Azure Synapse Analytics o Azure Data Factory para realizar funciones similares de almacenamiento y procesamiento analítico.
15.4 Notas Adicionales
15.4.1 Configuración por Entorno
Diferentes entornos tendrán diferentes necesidades y deberán ajustarse a la misma arquitectura base. Los valores de recursos, conteos de réplicas y configuraciones específicas pueden variar según las necesidades de cada entorno.
15.4.2 Actualizaciones
Las versiones de Kubernetes se actualizan manualmente. Las versiones de aplicación y charts se gestionan vía vendir y referencias a repositorios externos. Las actualizaciones de base de datos deben planificarse cuidadosamente debido a posibles tiempos de inactividad. Todas las versiones siguen Semantic Versioning (SemVer).