nessie

Hecho en la UE, y dónde están tus datos

Dónde se construye Nessie, dónde están tus datos y qué controlas cuando lo alojas tú mismo.

Quién lo construye y bajo qué ley

Nessie está desarrollado por UnlikeOtherAI s.r.o., una empresa registrada en la República Checa y sujeta al derecho checo.

Esta página describe cómo está construido el software y dónde se ejecuta. No es una declaración de cumplimiento normativo: Nessie no cuenta con ninguna certificación de seguridad y nada de lo que aquí se dice debe entenderse como tal. Qué datos personales se tratan y con qué base jurídica es materia de la política de privacidad, que es una página aparte.

Dónde se ejecuta el producto alojado

Nessie Cloud funciona en proveedores de alojamiento europeos (Scaleway, Hetzner y otros). Elegimos el mejor servicio que ofrece cada proveedor, así que distintas partes del producto pueden funcionar con distintos proveedores, todos en Europa.

Cualquier dato más preciso que ese (un emplazamiento, una ciudad o un centro de datos concretos) no se indica aquí a propósito, porque se quedaría desfasado sin que nadie se diera cuenta.

Con el alojamiento propio, la decisión es tuya

Dónde se ejecuta una instancia de alojamiento propio es un ajuste del despliegue, no del producto. La vía de una sola máquina es una pila de Docker Compose que instalas en la máquina que elijas. En el árbol de Terraform para una nube gestionada, la región es un parámetro de entrada sin ningún valor por defecto: nada de lo que hay ahí se puede adivinar, así que nada tiene un valor por defecto, y la base de datos, el bucket de almacenamiento de objetos y los servicios siguen todos la región que indiques.

Hay dos detalles estructurales que importan para esta misma cuestión. La cola y el transporte en tiempo real son ambos PostgreSQL: no hay Redis ni intermediario de mensajes en el recorrido, así que no hay un tercer sistema que ubicar. Y el almacenamiento de objetos es compatible con S3 en lugar de depender de un único proveedor; el despliegue de referencia ejecuta MinIO en un contenedor, en una red privada y sin entrada propia desde el exterior. Las piezas que tienen que estar en algún sitio son la base de datos, el almacén de objetos y los dos servicios de Node, y todas están donde tú las pongas. Cómo montarlo se explica en la página de instalación.

Qué guarda Nessie y qué decide no guardar

La identidad no se copia

Con el inicio de sesión de UnlikeOtherAI, el proveedor de identidad gestiona y almacena la identidad de las personas: los factores de autenticación, los perfiles, la pertenencia a organizaciones y equipos, y las invitaciones. Nessie es una parte confiante (relying party), no un segundo sistema de identidad. Es una decisión sobre datos tanto como de arquitectura: una identidad que Nessie nunca almacena es una identidad que no puede filtrar, perder ni dejar de borrar.

Lo que la tabla users guarda en realidad es el identificador de usuario estable del proveedor (la clave a través de la cual se resuelve todo lo demás), la dirección de correo, una copia no autoritativa del nombre visible y del avatar, y campos propios del producto (preferencias, pronombres, una versión de token que sirve para revocar sesiones). La copia existe solo para poder mostrar un nombre y una imagen sin hacer una petición por fila, y se vuelve a sincronizar con las declaraciones verificadas del proveedor al iniciar sesión, al cambiar de equipo y al renovar la sesión. Nada fabrica un valor: una persona a la que el proveedor no ha puesto nombre aparece con su dirección de correo hasta que lo haga. Un hash de contraseña existe únicamente para el propietario inicial de una instalación sin ningún proveedor de identidad.

Lo mismo vale para la estructura. Una organización del proveedor es una organización de Nessie, vinculada mediante el identificador de organización del proveedor; un equipo sin vínculo de origen responde 404 TEAM_NOT_LINKED en lugar de recurrir a una suposición local, y una lectura en vivo de la lista de miembros va al proveedor de identidad y no persiste nada.

Aún quedan dos copias por eliminar, y sería deshonesto dar a entender lo contrario. Los nombres de organizaciones y equipos siguen almacenándose localmente junto a los identificadores del vínculo, y las filas locales de pertenencia siguen autorizando las peticiones ordinarias entre sincronizaciones. Eliminar ambas cosas es trabajo abierto y registrado en el repositorio, no algo ya terminado.

Nada comercial

El servicio central de facturación gestiona los pagos. Nessie no almacena ningún cliente, suscripción, factura, precio, saldo de crédito, política de recarga, consentimiento de pago, extracto ni estado de cancelación del proveedor de pagos, y no calcula tarifas. Lee valores ya preparados para mostrar y los muestra.

Secretos

Para guardar un secreto hace falta un almacén seguro (vault) configurado. A propósito no hay alternativa en la base de datos ni ninguna vía en texto plano: sin él, guardar, rotar y revocar un secreto devuelven un error en lugar de degradarse a algo menos seguro. Los registros propios de Nessie sobre un secreto no contienen ningún valor, texto cifrado, clave ni token del almacén, solo una referencia opaca y sus metadatos, y las rutas del almacén se construyen únicamente con identificadores estructurales, nunca con el nombre de una organización, un equipo, un proyecto o una persona.

Las credenciales que Nessie tiene que conservar para actuar como cliente OAuth (credenciales de conectores y de buzones, secretos de webhooks, material de renovación de sesión, cargas de ejecutores) se sellan en envoltorios AES-256-GCM con un propósito concreto, bajo un anillo de claves versionado que es una raíz distinta del secreto de firma de sesiones y que cuenta con un procedimiento de rotación documentado.

También hay una regla sobre los modelos: se puede saber que un secreto existe y se puede autorizar su uso, pero el contenido del secreto no debe entrar en el contexto del modelo, los prompts, los argumentos o resultados de herramientas, la memoria, los embeddings, la búsqueda, los registros ni los mensajes. A un agente se le puede conceder la capacidad de usar un secreto. Nunca se le puede conceder la de revelarlo.

Que los discos subyacentes estén cifrados es una propiedad de la máquina en la que se ejecuta un despliegue. El repositorio no establece el cifrado a nivel de volumen para los volúmenes de la base de datos y del almacenamiento de objetos, así que esta página no lo afirma.

Aislamiento entre inquilinos

Nessie es multiinquilino por diseño: una sola base de datos en la que cada fila pertenece a una única organización y cada tabla hija lleva un organization_id. El aislamiento se aplica en dos puntos: la cláusula de ámbito que lleva cada consulta y las claves foráneas reales sobre esa columna, que se añadieron mediante cuarenta y dos restricciones después de que una auditoría interna encontrara la columna presente pero sin restricciones en decenas de tablas.

Un conjunto de pruebas de conformidad mantiene esa invariante en el límite HTTP. Siembra a un atacante con privilegios máximos (propietario completo de su propia organización) y comprueba que toda lectura canónica de recursos de otra organización responde 403, 404 o vacío, y que toda mutación canónica es rechazada sin tocar la fila de la otra organización. Cubre canales, aprobaciones, el registro de auditoría, disparadores, agentes y sus vínculos, ejecuciones, proyectos, tareas, hilos, conexiones, instalaciones de flujos de trabajo, instancias MCP, la base de conocimiento y las alertas.

Con precisión sobre el mecanismo: es una aplicación de la regla a nivel de aplicación más claves foráneas, no seguridad a nivel de fila de PostgreSQL (RLS). No hay ninguna política RLS ni un respaldo en la propia base de datos, y el conjunto de pruebas de conformidad se ejecuta contra un almacén en memoria fiel y no contra una base de datos real, de modo que demuestra las cláusulas de ámbito que escribe el código y no el SQL que ejecuta un servidor. El repositorio lo dice en la propia documentación del conjunto de pruebas, y esta página también.

El registro de auditoría

Se registra toda acción relevante: quién actuó y en calidad de qué (una persona, un agente, un servicio), qué hizo, sobre qué recurso, en qué organización, proyecto, equipo o canal, si tuvo éxito o fue denegada, por qué, y el identificador de la petición, la dirección y el agente de usuario con los que llegó.

El registro es de solo anexado por diseño y no hay forma de escribir en él desde fuera: POST /api/audit-log no existe, y es a propósito. Las entradas están encadenadas: cada una lleva un resumen SHA-256 de sus propios campos canónicos más el resumen de la entrada anterior de esa organización, de modo que una fila modificada o eliminada rompe la cadena y es detectable. Un propietario o administrador de la organización puede recorrer esa cadena cuando quiera y, si se rompió, se le indica dónde se rompió por primera vez.

Dos salvedades honestas. La cadena hace que el registro evidencie la manipulación, no que sea inmune a ella: no hay detrás ninguna revocación de escritura a nivel de base de datos ni almacenamiento de escritura única, así que la garantía es la detección, no la prevención. Y las entradas se conservan indefinidamente por defecto: la retención configurable con exportación antes del borrado está diseñada, no construida. Además, las entradas tienen prohibido incluir secretos o cuerpos completos de peticiones, y un conjunto fijo de nombres de campos de metadatos sensibles se oculta al entrar.

El libro de costes

Cada invocación de un modelo se registra a nombre de la organización y del usuario, equipo, proyecto, canal, agente y ejecución de los que procede, con los tokens consumidos y, lado a lado, el coste que informa el proveedor y la estimación propia de Nessie. Una métrica que el proveedor no informa se guarda como nula en lugar de inventarla. Los informes los puede leer un propietario o administrador de la organización.

Este libro es telemetría operativa: lo que ha gastado una organización y por cuenta de quién. No es una factura ni una autoridad de facturación.

Terceros, cuando usas el producto alojado

Un despliegue alojado se comunica con un conjunto pequeño y fijo de servicios. El tráfico de modelos y la búsqueda web no van directamente a los proveedores: ambos salen por una única pasarela operada por UnlikeOtherAI, que es donde están los proveedores de modelos y de búsqueda. El inicio de sesión y la facturación van al autenticador de UnlikeOtherAI. El almacén de secretos está alojado por cuenta propia junto a la aplicación. Los enlaces de videollamada generados por el servidor usan por defecto el servicio público de Jitsi.

Casi todo lo demás está desactivado hasta que un operador lo configura, y lo dice en lugar de fallar en silencio: las cuentas conectadas de Google, Microsoft y Slack; el correo de los agentes a través de Amazon SES, que cada despliegue ejecuta en su propia cuenta y sin intermediarios; las notificaciones push móviles y de navegador; los conectores de investigación y de fuentes de tableros; los navegadores en la nube. Hay dos detalles que conviene señalar porque cambian adónde van los datos:

  • Los buzones conectados se quedan con tu proveedor. El correo se lee en directo desde tu proveedor, por IMAP y SMTP o con el inicio de sesión del propio proveedor; Nessie guarda la credencial, sellada, y nada más de la cuenta. Un buzón que conectas a la bandeja de entrada de clientes es la excepción: pides que sus conversaciones se conserven con cada cliente, así que se copian.
  • Las llamadas de voz en la app no pasan por Nessie. La API intermedia una credencial y el cliente abre por sí mismo la conexión de audio. El dictado y las llamadas telefónicas son distintos: su audio pasa por Nessie hasta los proveedores de voz y de modelos que lo procesan.

Un detalle de inferencia sigue el mismo principio: las cabeceras firmadas de identidad del solicitante solo se envían al host de chat configurado, de modo que, si se apuntan los embeddings a otro endpoint, ese endpoint nunca recibe una aserción de delegación sobre la persona cuyo texto se está incorporando.

El producto alojado usa varios proveedores de inferencia y elige entre ellos según el coste y la calidad. Una organización podrá elegir en Admin qué proveedores pueden usar sus agentes: solo occidentales, solo europeos, solo chinos o sin preferencia, es decir, el proveedor más eficiente para cada trabajo. Una instancia autoalojada elige los suyos.

Si lo ejecutas tú, todo esto cambia

Cada tercero mencionado arriba es una opción de configuración en una instancia de alojamiento propio. La inferencia puede apuntarse a cualquier endpoint compatible con OpenAI, incluido uno en tu propio hardware. Los conectores están desactivados salvo que los actives. El inicio de sesión de UnlikeOtherAI es la vía admitida, y un despliegue sin ningún proveedor de identidad funciona como una única organización sin vincular con un propietario inicial.

Ese es el sentido de todo el planteamiento: el software es el mismo, y las decisiones sobre dónde se ejecuta y a qué puede acceder corresponden a quien lo ejecuta. La página de instalación explica cómo.