Korpex.

Seguridad · Korpex Copiloto

Doc público. Última actualización: 2026-09-04 (incluye ADR-042 hardening + ADR-043 notificaciones personalizables).

Korpex Copiloto maneja información sensible de negocios locales (finanzas, contactos, empleados, documentos, tokens OAuth de plataformas externas). Este documento describe qué medidas concretas tomamos para protegerla — no como marketing sino como referencia técnica auditable por vos, tu contador, tu equipo IT o quien necesite validarlo.


1. Autenticación

Login

  • Contraseñas hasheadas con bcrypt (Supabase Auth managed). Nunca

guardamos el texto plano.

  • Política de contraseñas: mínimo 12 caracteres, con mayúscula,

minúscula, número y símbolo. Rechazamos passwords débiles en creación y cambio.

  • Rate limit anti-brute-force: 10 intentos fallidos por email cada

15 minutos → lockout automático. 30 fallos por IP cada 15 min → IP bloqueada.

  • Sin user enumeration: el mensaje "correo o contraseña incorrectos"

es idéntico si el email existe o no. No damos pistas al atacante.

MFA (segundo factor)

  • TOTP (Time-based One-Time Password) compatible con Google

Authenticator, Authy, 1Password, Microsoft Authenticator y demás.

  • Obligatorio para administradores de la plataforma. **Opcional pero

recomendado** para dueños de negocio.

  • Setup en /app/[tenant]/config/seguridad.

Sesiones

  • Cookies HttpOnly + SameSite=Lax (bloquea CSRF cross-site).
  • Refresh automático server-side (Supabase SSR).
  • Cambio de contraseña invalida sesiones activas en otros dispositivos.

2. Autorización y aislamiento

Row-Level Security (RLS)

  • 100% de las tablas de datos del tenant tienen RLS habilitado en

PostgreSQL.

  • Cada request lleva un header x-tenant-id que la política de RLS usa

para filtrar filas — un tenant no puede leer datos de otro incluso si hubiera un bug en la capa app.

  • Los admins de tenant se autorizan por tenant_members (tabla ligada

a auth.uid()), no por email compartido.

Empleados con permisos granulares

  • Cada empleado que use el bot tiene una lista blanca de qué

sub-agentes puede invocar (ej: "solo tareas y jornadas, nada de finanzas").

  • El sub-agente que le queda fuera de scope literalmente no aparece en

el prompt del LLM del empleado — no puede pedírselo ni por accidente.

Historial aislado

  • Cada usuario de Telegram (dueño, empleado A, empleado B) tiene su

propio hilo de conversación filtrado por telegram_user_id. Nadie ve el chat de nadie más.


3. Cifrado

En tránsito

  • HTTPS forzado (HSTS con `max-age=63072000; includeSubDomains;

preload`). Un browser que ya nos visitó rechaza descargas por HTTP.

  • Conexión a Supabase por TLS. Conexión a Telegram, Notion, Canva,

Google APIs por HTTPS.

En reposo

  • Tokens OAuth de Notion, Canva, Google Calendar/Drive/Gmail se

guardan cifrados con AES-256-GCM en Supabase. Un dump de base de datos comprometido no expone los tokens sin la master key (que vive en Vercel envs como sensitive).

  • Contraseñas nunca se guardan cifradas ni en claro — solo hash bcrypt.

4. Perímetro

Rate limiting

Dos capas:

  1. Vercel Firewall (edge): límites por path + geo-block admin +

deny scans automáticos + Bot Protection + AI Bots.

  1. App layer (Upstash Redis): límites por acción (login, webhook

Telegram, uploads, búsquedas, OAuth start).

Security headers

Aplicados en toda respuesta:

  • Content-Security-Policy (whitelist estricta de dominios permitidos).
  • Strict-Transport-Security (2 años + preload).
  • X-Frame-Options: DENY (previene clickjacking).
  • X-Content-Type-Options: nosniff.
  • Referrer-Policy: strict-origin-when-cross-origin.
  • Permissions-Policy (bloquea camera/microphone/USB/magnetometer/etc).
  • Cross-Origin-Opener-Policy y Cross-Origin-Resource-Policy.

CSRF

  • Verificación de Origin header en cada request POST/PATCH/DELETE.
  • Solo dominios en whitelist (app.korpex.co, korpex.co) pueden mandar

writes. Excepciones documentadas para webhooks OAuth de terceros.

Body size + timeouts

  • Payload máximo 512KB en webhooks públicos.
  • maxDuration de 60s (webhook Telegram, IA) evita que un attacker

cuelgue funciones para siempre.


5. Audit trail

Cada evento de seguridad relevante queda registrado:

  • Logins exitosos y fallidos (con hash del email + IP + user agent).
  • Cambios de contraseña.
  • MFA enroll / unenroll.
  • OAuth connect / revoke.
  • Acciones de admin (crear cliente, borrar, editar).
  • Bindings de Telegram creados / revocados.
  • Lockouts por rate limit.
  • Alertas de seguridad detectadas.

Retención: 180 días (borrado automático nightly).

Los admins ven todo el audit en /app/admin/security. Los dueños de tenant ven solo lo que aplica a su negocio (por RLS).


6. Retention de datos

Tipo de datoRetención
Datos del negocio (tareas, contactos, finanzas)Indefinido, hasta borrar por el dueño
Conversaciones con el bot (ai_activity_log)90 días
Audit log de seguridad180 días
Intentos de vinculación Telegram30 días
Registro de envíos de notificaciones (dedup diario)60 días
CSRF states OAuth (temporales)10 min

7. Terceros y datos que compartimos

Datos del tenant NUNCA se comparten con nadie fuera del tenant. Los terceros a los que llamamos son proveedores de infraestructura, no consumidores de tus datos:

  • Supabase (Postgres managed) — hosting de BD, con RLS y cifrado.
  • Vercel (hosting Next.js) — logs de request agregados 30 días.
  • Vercel AI Gateway (LLMs) — cada mensaje al bot pasa por

OpenAI/Google/Anthropic. Ninguno guarda tus mensajes bajo "zero data retention" que aplicamos.

  • Upstash Redis — contadores de rate limit (no data de negocio).
  • Notion / Canva / Google — solo cuando el dueño conecta la

integración voluntariamente. Los tokens viven cifrados con vos.

  • Sentry (opcional, si activado) — errores del sistema sin

payloads sensibles.

Ningún dato de un tenant se usa para entrenar modelos de IA de terceros. La política del AI Gateway prohíbe explícitamente ese uso.


8. Rotación de secrets

Rotamos periódicamente:

  • Tokens de bot Telegram y webhook secret: cada 90 días.
  • Service role keys de Supabase: cada 90 días.
  • Cron secret: cada 90 días.
  • Master key de cifrado: solo bajo sospecha de compromiso (requiere

re-cifrar tokens de todos los tenants — proceso documentado).

Ver docs/security-secret-rotation.md (interno) para el proceso.


9. Contacto de seguridad

Si encontrás una vulnerabilidad, reportala directamente a: davidcuervo399@gmail.com con "SECURITY" en el asunto. Respondemos en < 48 h.

No divulgues públicamente hasta que tengamos un fix aplicado. Te mencionamos en el changelog si querés.


10. Compliance y estándares que seguimos

  • OWASP ASVS 4.0 — Application Security Verification Standard.
  • OWASP Top 10 — cubierto para todos los ítems relevantes a nuestro

stack (Broken Access Control, Cryptographic Failures, Injection, Insecure Design, Security Misconfiguration, Vulnerable Components, Auth Failures, Software Integrity, Logging Failures, SSRF).

  • NIST SP 800-63B — política de passwords sin rotación forzada.
  • RFC 7591 (Dynamic Client Registration) + PKCE para OAuth 2.1

contra los MCPs.

No aplicamos ni buscamos SOC 2 / ISO 27001 / HIPAA / PCI todavía — somos una startup pequeña sin obligación regulatoria hoy. Cuando manejemos datos de pagos directos o salud, subimos el nivel.