---
title: Seguridad
persona: all
category: Documentación técnica
version: 1.0.0
updated: 2026-06-09
---

# Seguridad

La seguridad de MyFinAI descansa en tres muros que no dependen de la disciplina de
nadie: **aislamiento por inquilino** (RLS), **aislamiento por rol**, y **trazas
inviolables** (auditoría encadenada + BYOK). Cada uno se verifica de forma continua
y re-ejecutable.

## Muro 1 · aislamiento por inquilino (RLS)

Cada tabla con datos de inquilino lleva una política `FORCE ROW LEVEL SECURITY`
sobre `app.current_tenant_id`, y la aplicación se conecta con el rol `myfinai_app`
(`NOSUPERUSER`, `NOBYPASSRLS`). El libro de un negocio y el de un hogar son
físicamente invisibles entre sí.

**Probado en vivo:** dos espacios —Café La Aurora y Hogar Marrero— con fuga cero en
ambos sentidos. Sus conjuntos de transacciones son disjuntos, y un mismo login que
cambia de espacio obtiene un libro distinto: café DR **$91,216** ≠ hogar DR
**$6,360**.

## Muro 2 · aislamiento por rol

El RLS aísla *inquilinos*; los roles aíslan *personas dentro de un inquilino*. Los
libros del negocio (movimientos, nómina, mayor, impuestos, auditoría) están detrás
del nivel **books** (dueño · tenedor de libros · contador · jefe de hogar). El
**empleado** y el **miembro de familia** quedan fuera: solo ven su propio recibo o
su propia mesada.

> Esto se **impide** en el servidor, no en la interfaz. Aunque un empleado pidiera
> `GET /api/data/payroll` directamente, la respuesta es `403`. Lo mismo para Norte:
> nadie saca los libros a través del asistente.

## Muro 3 · membresía verificada

No puedes obtener un token para un espacio al que no perteneces. `/api/auth/switch`
valida la membresía en el servidor: un usuario del café recibe `403` al intentar
cambiar al hogar, y viceversa. La pertenencia se comprueba, no se asume.

## BYOK · tus llaves, cifradas

Si un inquilino trae su propia llave de IA (BYOK), se guarda cifrada con
**Fernet + HKDF** (llave maestra del entorno + sal por inquilino,
`info="myfinai-byok-v1"`). Solo se guarda el texto cifrado; la maestra falla en
cerrado y el texto plano nunca se registra ni se devuelve. Sin llave, los agentes
deterministas siguen funcionando: la IA pule la respuesta, no es un requisito para
que el sistema opere.

## Auditoría encadenada

Cada acción relevante —apertura de período, decisión, aprovisionamiento, y lo que
hace cada agente— se escribe en `audit_log` con el hash del evento anterior
(`prev_hash → hash`). Alterar un registro pasado rompe la cadena y se nota. La
auditoría cubre operaciones, no solo dinero.

## Verificación continua

Todo lo anterior se prueba con `api/infra/audit_flows.py`: **77 comprobaciones, 0
fallos** contra el sistema en producción, cubriendo los siete roles, el cruce de
inquilinos en ambos sentidos, y la reconciliación de ambos libros. El registro de
hallazgos, correcciones y pendientes vive en `api/AUDIT.md`.

```
python api/infra/audit_flows.py            # contra producción
BASE=http://localhost:8090 python …        # contra una instancia local
```

> **La idea:** la confianza no se pide, se demuestra. Cualquiera puede re-correr la
> prueba y ver, en su pantalla, que los muros siguen en pie.
