Mekovault
Gobernanza técnica

Cómo está construido y operado Mekovault

Referencia para equipos de TI, seguridad, compliance y auditoría que evalúan Mekovault antes de firmar. Describe la infraestructura, el modelo de identidad, el aislamiento entre clientes, el tratamiento de credenciales de directorio y lo que todavía está en curso.

Última revisión: 9 de septiembre de 2026Documento descriptivo de controles operativos vigentes. No constituye certificación formal.

De un vistazo

Región
AWS Lightsail, us-east-1 (Virginia del Norte)
Topología
4 máquinas en red privada; una sola expuesta a Internet
Secretos de clientes
Infisical self-hosted, un project por tenant
Base de datos
PostgreSQL 16 con Row-Level Security por company_id
Sesión
JWT RS256 de 15 min + refresh de 30 días en cookie HttpOnly
MFA
TOTP, exigido en operaciones sensibles
Uso de credenciales
Registro inmutable por operación, exportable y firmado
Acceso administrativo
Solo por Tailscale; sin SSH público

01Infraestructura

Mekovault corre en AWS Lightsail, región us-east-1, sobre cuatro máquinas conectadas por red privada. Solo una de ellas recibe tráfico de Internet.

HostRolServiciosExposición
mekovault-appAplicaciónnginx, Next.js, servicios FastAPI, addonsÚnica expuesta: puertos 80/443 detrás de Cloudflare
mekovault-dataDatosPostgreSQL 16, Redis (2 instancias), RabbitMQSolo red privada
mekovault-vaultSecretosInfisical self-hosted, un project por tenantSolo red privada
mekovault-obsObservabilidadGrafana, Loki, Prometheus, Tempo, OpenTelemetry CollectorSolo red privada
Máquinas de producción
InternetCloudflare (80/443)ÚNICO PUNTO EXPUESTOmekovault-appnginx · web · svc-* · addons80/443RED PRIVADA (SIN IP PÚBLICA)mekovault-dataPostgreSQL 16 · Redis ×2 · RabbitMQmekovault-vaultInfisical · 1 project / tenantmekovault-obsGrafana · Loki · Prometheus · Tempo · OTelTailscaleadministración
Topología de producción. Solo mekovault-app recibe tráfico de Internet, a través de Cloudflare. El resto de las máquinas no tiene IP pública y se administra por Tailscale.
  • Administración exclusivamente por Tailscale (WireGuard). No hay SSH abierto a Internet en ningún host.
  • Firewall ufw activo en cada máquina con política de denegar por defecto.
  • Los servicios internos (PostgreSQL, Redis, RabbitMQ, Infisical, Grafana y los procesos FastAPI) escuchan en loopback o en la interfaz privada. nginx es el único proceso que atiende tráfico público.
  • Cloudflare termina TLS y filtra tráfico antes de que llegue a nginx.

02Arquitectura de servicios

La interfaz web es una aplicación Next.js 16. El backend está compuesto por servicios FastAPI sobre Python 3.12 con SQLAlchemy asíncrono, cada uno con una responsabilidad acotada.

ServicioResponsabilidad
svc-authAutenticación, sesiones, MFA y reset de contraseña
svc-tenancyEmpresas, membresías, roles, resellers y eliminación de tenants
svc-requestsSolicitudes de alta, baja y cambio; flujo de aprobaciones
svc-ticketsTickets de soporte y su seguimiento
svc-billingPlanes, suscripciones y facturación
svc-notificationsCorreo y notificaciones a usuarios
addonsMódulos conectores. Ejemplo: super-workspace, que opera sobre Google Workspace
Servicios del backend

Eventos y trabajos en segundo plano

  • Los servicios se comunican por eventos a través de RabbitMQ, en el exchange de tipo topic mekovault.events.
  • Los trabajos pesados (provisioning, eliminaciones, exportaciones) se registran en un libro mayor de jobs en PostgreSQL y los ejecuta un worker único.
  • Cada job reintenta con backoff exponencial. Sus pasos son idempotentes: volver a ejecutar un paso ya completado no produce efectos duplicados sobre el directorio.
  • Cuando un job agota sus reintentos, se genera una alerta y el job queda visible con su último error para intervención manual.

03Identidad y sesión

Los usuarios de Mekovault (administradores de TI, aprobadores, resellers) se autentican con OAuth de Google o con email y contraseña. La sesión está diseñada para que un token robado sirva poco tiempo y sea revocable.

MecanismoDetalle
Métodos de accesoOAuth con Google, o email y contraseña
Token de accesoJWT firmado con RS256, vigencia de 15 minutos, con claims de rol y de estado MFA
Refresh tokenVigencia de 30 días. Vive solo en una cookie HttpOnly (inaccesible desde JavaScript). Se rota en cada uso y es revocable individualmente por jti en Redis. Hereda el estado MFA de la sesión y revalida la membresía del usuario en la empresa en cada renovación.
MFATOTP (apps de autenticación estándar). Límite de 5 intentos por minuto; bloqueo de 15 minutos tras 10 fallos consecutivos.
Operaciones sensiblesExigen que la sesión tenga MFA verificado, aunque el usuario ya esté autenticado.
Reset de contraseñaToken de un solo uso con vigencia de 30 minutos.
Parámetros de sesión

Consecuencia práctica: un access token filtrado caduca en 15 minutos como máximo; el refresh no es exportable desde el navegador; y revocar el jti en Redis corta la sesión de inmediato, sin esperar a que expire nada.

04Aislamiento multi-tenant

Mekovault es multi-tenant: varios clientes comparten la misma infraestructura. El aislamiento entre ellos se impone en capas independientes, de modo que un error en una no exponga datos de otro cliente.

CapaControl
Modelo de datosToda fila con datos de cliente lleva company_id.
AplicaciónToda consulta filtra por la empresa que viene en el token de sesión. Nunca por un parámetro enviado por el cliente.
Base de datosRow-Level Security de PostgreSQL como barrera adicional: aunque una consulta olvidara el filtro, la base de datos no devuelve filas de otra empresa.
SuperadminRol de plataforma separado de los roles de cliente. Sus acciones requieren confirmación por código y MFA verificado.
ResellersUn reseller ve y opera solo sobre los tenants que administra.
Capas de aislamiento

05Credenciales de proveedores y auditoría de uso

Para operar sobre su directorio, Mekovault recibe credenciales con permisos de administración: el JSON de una Service Account de Google con delegación a nivel de dominio. Son el activo más sensible que manejamos.

  • Se almacenan cifradas en Infisical (self-hosted, en mekovault-vault), en un project dedicado por tenant.
  • Nunca se escriben en la base de datos, en logs ni en respuestas de API. La base de datos guarda solo una referencia al secreto.
  • Se cargan en memoria en el momento de llamar al proveedor y se descartan al terminar la operación.

Registro inmutable de cada uso

Cada llamada a Google con las credenciales del cliente deja una fila en la tabla credential_usage_log.

CampoContenido
Tenantcompany_id del cliente dueño de la credencial
ProveedorGoogle Workspace
OperaciónAcción ejecutada, por ejemplo create_user, suspend_user, add_group_member
ScopesScopes o permisos consumidos por esa operación
QuiénUsuario que originó la acción, o el proceso automático (worker, timer) que la ejecutó
MotivoReferencia a la solicitud, ticket o tarea que justificó la llamada
ResultadoÉxito o fallo, con código de error si aplica
LatenciaDuración de la llamada al proveedor en milisegundos
Campos de credential_usage_log
  • La tabla tiene triggers de PostgreSQL que rechazan cualquier UPDATE o DELETE. Ni el equipo de Mekovault puede editar o borrar una fila individual.
  • Cada fila tiene un id determinista derivado de la operación. Un reintento del mismo trabajo no genera una segunda fila, así el registro no se infla ni se contradice.
  • Una ráfaga de fallos sobre las credenciales de un tenant dispara una alerta al equipo de operación.

Retención

ParámetroValor
Mínimo24 meses
Máximo84 meses
ConfiguraciónPor tenant, dentro de ese rango
Eliminación del tenantSe borra junto con el tenant, o a los 24 meses, lo que ocurra primero
PurgaSemanal, solo de filas fuera del período configurado. Cada batch purgado deja constancia en la auditoría.
Retención del registro de uso

Exportación para auditores

El registro se exporta en CSV o JSON. Cada archivo va firmado con HMAC-SHA256 e incluye el identificador de la clave usada, de modo que un auditor puede verificar que el archivo no fue alterado después de generarse.

06Permisos que Mekovault solicita

Mekovault pide únicamente los permisos que necesita para gestionar usuarios, grupos y unidades organizativas. No solicita acceso a correo, archivos, calendario ni contenido de ningún usuario.

ScopePara qué se usa
admin.directory.userCrear, suspender, reactivar y modificar cuentas de usuario; asignar contraseña inicial y forzar su cambio.
admin.directory.groupCrear grupos y listas, y agregar o quitar miembros durante altas, cambios y bajas.
admin.directory.orgunitLeer y mover usuarios entre unidades organizativas según el flujo de onboarding u offboarding.
Google Workspace (Admin SDK Directory API)

Las llamadas se hacen con la Service Account impersonando al administrador delegado que el cliente designa al conectar el dominio. Ese administrador queda registrado en cada fila de credential_usage_log.

07Contraseñas iniciales y reset

  • Cuando Mekovault crea una cuenta o resetea una contraseña, la contraseña temporal queda visible para el administrador que ejecutó la acción durante 15 minutos.
  • Pasado ese plazo se purga del sistema. No se puede recuperar: si se perdió, se genera una nueva.
  • Las contraseñas nunca se escriben en logs, eventos ni en el registro de uso de credenciales.

08Eliminación de un tenant

Un cliente puede pedir la eliminación completa de su tenant (derecho de supresión, RGPD art. 17 y Ley 21.719 de Chile). El proceso está diseñado para que las credenciales desaparezcan antes que cualquier otro dato.

  1. Un administrador del tenant solicita la eliminación. La solicitud se encola como job.
  2. El tenant queda inaccesible de inmediato: se rechazan sus sesiones y nuevos inicios de sesión.
  3. El job revoca los secretos del tenant y elimina su project en Infisical. Desde este punto Mekovault ya no puede llamar al directorio del cliente.
  4. Solo después se borran en cascada los datos del tenant en PostgreSQL: usuarios, solicitudes, tickets, configuración.
  5. La eliminación queda registrada en la auditoría de plataforma.
  6. Los administradores reciben un correo de confirmación con el detalle de lo eliminado.

09Addons: módulos con límites

Los conectores a proveedores y otras extensiones se empaquetan como addons. Un addon con un defecto no debe poder degradar la plataforma completa, y el registro de addons impone esa regla.

EtapaControl
DeclaraciónCada módulo se describe en un manifiesto con sus puertos, rutas, tablas, migraciones y chequeo de salud.
ValidaciónAutomática antes de activarlo: esquema del manifiesto, colisiones de puertos, rutas y tablas con otros módulos, migraciones aplicables y respuesta del chequeo de salud.
EjecuciónCorre con límites de memoria y CPU. Un módulo que se desborda se reinicia sin afectar a los demás.
SupervisiónChequeo de salud cada 60 segundos, con resultado visible en el panel de operación.
Kill switchCualquier módulo puede desactivarse sin despliegue: en 15 segundos o menos sus rutas responden 503 y el resto de la plataforma sigue operando.
Ciclo de vida de un addon

10Perímetro y navegador

ControlEfecto
HSTSEl navegador solo se conecta por HTTPS al dominio, incluso si el usuario escribe http.
Content-Security-PolicyRestringe los orígenes desde los que el portal puede cargar scripts, estilos y conexiones.
X-Content-Type-Options: nosniffImpide que el navegador reinterprete el tipo de un archivo.
frame-ancestors 'none'El portal no puede embeberse en un iframe de otro sitio (clickjacking).
CORS restringidoSolo los orígenes de Mekovault pueden llamar a la API desde un navegador.
Sin source maps en producciónNo se publica el código fuente del frontend.
Sin documentación pública de APILos esquemas OpenAPI de los servicios no están expuestos en producción.
Errores sin trazasLas respuestas de error no incluyen stack traces ni detalles internos.
Cabeceras y políticas del portal

11Operación y observabilidad

SeñalDestino
Logs estructurados (JSON)Loki, consultados desde Grafana
MétricasPrometheus
Trazas distribuidasOpenTelemetry hacia Tempo
Señales de operación
  • Antes de cada despliegue se toma un backup de la base de datos.
  • Los servicios se despliegan de forma controlada; un despliegue fallido se revierte al backup previo.

Timers de higiene

TareaQué hace
Purga de PIIElimina datos personales que ya cumplieron su período de retención.
Cierre de ticketsCierra tickets resueltos sin actividad después del plazo configurado.
Expiración de secretosAvisa a los administradores 30, 7 y 0 días antes de que caduque una credencial de proveedor.
Purga del registro de usoSemanal; elimina solo filas fuera de la retención configurada y deja constancia del batch.
Tareas programadas

12Resumen de capas de seguridad

CapaControles
PerímetroCloudflare, nginx como único proceso público, ufw
RedRed privada de Lightsail, Tailscale para administración, servicios en loopback
IdentidadJWT RS256 de 15 min, refresh HttpOnly rotado y revocable, MFA TOTP con rate limit
AplicaciónFiltro por company_id del token en toda consulta
DatosRow-Level Security en PostgreSQL 16
SecretosInfisical self-hosted, un project por tenant, nunca en DB ni logs
Auditoríacredential_usage_log inmutable, exportación firmada con HMAC-SHA256
MódulosManifiesto validado, límites de recursos, supervisión cada 60 s, kill switch
OperaciónBackups previos al despliegue, timers de higiene, logs, métricas y trazas
Controles por capa

13Lo que está en curso

Preferimos decir qué falta antes de que lo pregunte un cuestionario. Estos puntos están en trabajo y no deben asumirse como vigentes hasta que esta página los mueva a la sección correspondiente.

ÍtemEstado
ENVIRONMENT=production en todos los servicios (hoy algunos corren con la configuración de desarrollo endurecida)En curso
Alertas de operación hacia SlackEn curso
Rol de PostgreSQL dedicado por addon, para que cada módulo acceda solo a sus tablasEn curso
SOC 2No planificado por ahora; el marco se usa como guía de controles
Roadmap técnico

FAQPreguntas de auditoría frecuentes

Respuestas directas a lo que suelen preguntar los equipos de seguridad y los auditores.

¿Dónde viven mis credenciales?
En Infisical, una instancia self-hosted en la máquina mekovault-vault, dentro de la red privada de AWS Lightsail en us-east-1. Cada tenant tiene su propio project. La base de datos guarda solo una referencia al secreto, nunca su valor.
¿Quién puede verlas?
Ninguna persona las ve en operación normal. Los servicios las cargan en memoria en el momento de llamar al proveedor y las descartan al terminar. El acceso a la máquina del vault exige Tailscale, y ese acceso está restringido al equipo de plataforma. Las contraseñas temporales que Mekovault genera son visibles al administrador del cliente durante 15 minutos y luego se purgan.
¿Qué pasa si dejo Mekovault?
Un administrador solicita la eliminación del tenant. El acceso se corta de inmediato; luego se revocan los secretos y se borra el project de Infisical; solo después se borran en cascada los datos en PostgreSQL. Queda registro en la auditoría de plataforma y los administradores reciben un correo con el detalle. Los sub-encargados con datos residuales están listados en la página de sub-encargados.
¿Cómo pruebo que no usaron mis permisos para otra cosa?
Con credential_usage_log: cada llamada a Google con sus credenciales queda registrada con operación, scopes, quién la originó, motivo, resultado y latencia. La tabla no admite UPDATE ni DELETE. Puede exportarla en CSV o JSON firmado con HMAC-SHA256 y verificar la firma con el id de clave incluido.
¿Un token de sesión robado sirve para algo?
El access token caduca en 15 minutos. El refresh token vive solo en una cookie HttpOnly, se rota en cada uso y se puede revocar por jti en Redis. Las operaciones sensibles exigen además MFA verificado en esa sesión.
¿Un módulo con fallas puede tumbar la plataforma?
No está diseñado para poder hacerlo. Cada addon corre con límites de memoria y CPU, se supervisa cada 60 segundos y tiene un kill switch que lo desactiva en 15 segundos o menos sin despliegue. El resto de servicios sigue operando.

Solicitar el paquete de seguridad

Incluye este documento en PDF, la lista de sub-encargados, el DPA firmable y las respuestas a cuestionarios estándar (CAIQ, SIG Lite). Te respondemos en 5 días hábiles.