> ## Documentation Index
> Fetch the complete documentation index at: https://docs.iru.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Aislamiento multitenant

> Cómo mantiene Iru separados los datos de cada organización, mediante seguridad a nivel de fila aplicada en el motor de base de datos, y cómo cada cambio deja constancia de cualquier manipulación.

Iru Identity es multitenant: muchas organizaciones comparten el mismo servicio. La propiedad
más importante de ese diseño es que **un tenant nunca puede ver ni modificar los datos
de otro**. Iru lo aplica en el propio motor de base de datos, no solo en el
código de la aplicación, por lo que ni siquiera un error en una consulta puede cruzar la frontera.

## Aislamiento aplicado por la base de datos

Cada tabla que contiene datos de tenants incluye un `tenant_id` y está protegida mediante
**seguridad a nivel de fila (RLS) de PostgreSQL**:

* La tabla tiene RLS **habilitada y forzada** (`FORCE ROW LEVEL SECURITY`), de modo que la
  política se aplica a todos los roles. No hay ninguna vía privilegiada para eludirla.
* Una única política rige tanto las lecturas como las escrituras: las filas son visibles (`USING`) y
  modificables (`WITH CHECK`) solo cuando su `tenant_id` coincide con el tenant de la
  solicitud actual.

```sql theme={null}
-- The shape every tenant table shares
ALTER TABLE app.<table> ENABLE ROW LEVEL SECURITY;
ALTER TABLE app.<table> FORCE  ROW LEVEL SECURITY;

CREATE POLICY tenant_access_policy ON app.<table> FOR ALL
  USING      (tenant_id = current_setting('iru.tenant_id'))
  WITH CHECK (tenant_id = current_setting('iru.tenant_id'));
```

Esto se aplica de manera uniforme y a gran escala (**cientos de tablas**, cada una con RLS
forzada y una política de lectura y escritura idéntica), no solo a unas pocas privilegiadas.

<Note>
  Como la frontera reside en la base de datos, una consulta que olvide filtrar por
  tenant simplemente no devuelve nada de otro tenant. El motor se niega a mostrar
  o modificar filas fuera del tenant activo.
</Note>

## El contexto del tenant acompaña a cada solicitud

```mermaid theme={null}
flowchart LR
  req["Solicitud a<br/>tenant.subdomain"] --> mw["Resolver el tenant<br/>(rechazar si es desconocido)"]
  mw --> tx["Abrir transacción de BD"]
  tx --> setl["SET LOCAL iru.tenant_id = …<br/>+ instigador + id de correlación"]
  setl --> rls["La política RLS lee<br/>el mismo ajuste"]
  rls --> data[("Solo las filas de este tenant")]
```

1. El tenant se resuelve a partir del subdominio de la solicitud en el middleware. Si no se puede
   resolver, la solicitud se **rechaza antes de llegar a ningún controlador**.
2. Para cada transacción de base de datos, Iru establece el tenant (junto con el usuario
   que actúa y un id de correlación/rastreo) como un ajuste **limitado a la transacción**
   (`SET LOCAL`). Como está limitado a la transacción, no puede filtrarse a la
   siguiente solicitud que reutilice una conexión del pool.
3. La política RLS lee exactamente ese ajuste, por lo que la frontera de seguridad es el mismo
   valor que estableció la aplicación, fijado de forma transaccional en cada conexión.

## Privilegio mínimo, para que el historial de auditoría no se pueda reescribir

El rol de base de datos con el que se ejecuta la aplicación puede leer y escribir datos **activos**, pero
solo tiene acceso de **lectura** al **esquema de auditoría**. Aunque se abusara de algún modo del SQL
de la aplicación, este no tiene permisos para modificar ni eliminar el historial de auditoría. El registro está
protegido en la capa de privilegios, con independencia de cualquier lógica de la aplicación.

La integridad referencial también está limitada al tenant: las claves foráneas son compuestas
(`tenant_id` + id), por lo que un registro solo puede hacer referencia a otro registro **del
mismo tenant**.

## Cada cambio queda registrado (solo anexión)

Iru conserva un historial completo de los cambios en los datos de los tenants que deja constancia de cualquier manipulación.

<AccordionGroup>
  <Accordion title="Qué se captura" icon="clipboard-list">
    Cada tabla modificable tiene una **tabla de auditoría (diario)** espejo en la que escribe un
    disparador de base de datos al insertar, actualizar y eliminar. Cada entrada registra **qué**
    ocurrió (la acción), **quién** (tanto la entidad de base de datos que actúa como el
    usuario autenticado), **cuándo**, un **id de correlación/rastreo** que la vincula con la
    solicitud de origen y el **estado completo anterior y posterior** de la fila.
  </Accordion>

  <Accordion title="Por qué es de solo anexión" icon="lock">
    El registro está protegido de tres formas independientes: el disparador solo *inserta*
    filas en el diario; el rol de base de datos de la aplicación tiene acceso de **solo lectura** al
    esquema de auditoría; y el disparador se ejecuta con los derechos del definidor. No existe ninguna vía para que
    la aplicación altere o borre un registro de auditoría.
  </Accordion>

  <Accordion title="No puede desviarse sin que se note" icon="circle-check">
    Una comprobación de coherencia permanente compara las columnas de cada tabla activa con su
    tabla de auditoría y falla si falta alguna columna, de modo que los campos nuevos no pueden
    escapar del registro de auditoría sin que se note. Las migraciones de esquema también tienen versiones,
    se verifican mediante sumas de comprobación y quedan registradas.
  </Accordion>
</AccordionGroup>

## Los campos sensibles tienen una capa adicional

Además del aislamiento, los valores especialmente sensibles se **cifran a nivel de
campo con AES-256-GCM** (cifrado autenticado) antes de almacenarse, y
solo se descifran cuando los lee la aplicación. Las claves de cifrado se proporcionan en
tiempo de ejecución desde un almacén de secretos gestionado, nunca desde el código ni la base de datos.

## Cómo encaja esto en el panorama general

El aislamiento funciona de la mano de la **residencia regional de datos**: cada región tiene su
propia base de datos, y las consultas de un tenant solo se ejecutan en la base de datos de su región
(consulta [Arquitectura de la plataforma](/es/identity/security/platform-architecture)).
Dentro de esa base de datos, RLS mantiene separado a cada tenant.

<CardGroup cols={2}>
  <Card title="Arquitectura de la plataforma" icon="server" href="/es/identity/security/platform-architecture">
    Las regiones, los planos y la infraestructura sobre los que se ejecuta este aislamiento.
  </Card>

  <Card title="Arquitectura de autenticación" icon="signature" href="/es/identity/security/authentication-architecture">
    Cómo se hacen resistentes al phishing y a prueba de manipulaciones el inicio de sesión y las solicitudes de API.
  </Card>

  <Card title="Registro de actividad" icon="list-timeline" href="/es/identity/administration/activity-log">
    El registro de auditoría, disponible para que los administradores lo revisen.
  </Card>

  <Card title="Seguridad y privacidad" icon="lock" href="/es/identity/security/security-and-privacy">
    Las garantías que suman estos mecanismos.
  </Card>
</CardGroup>
