Plataforma · Gobernanza y control de acceso

Gobernanza, integrada en el núcleo

En MindooDB la gobernanza es una propiedad de la propia capa de datos, no un añadido atornillado a un servidor de confianza o a una capa de aplicación. La política de acceso, la identidad y un registro de auditoría demostrable criptográficamente y reproducible a cualquier instante se guardan y se imponen en el núcleo de la base de datos. La recompensa: puedes demostrar no solo qué cambió, sino quién tenía permiso para cambiarlo, en el momento en que el cambio entró de verdad en el tenant.

Tiene dos mitades: un lado de escritura que controla quién puede crear, cambiar o borrar documentos - y que se aplica también cuando los usuarios están sin conexión - y un lado de lectura que controla quién puede ver los datos, combinando una puerta de acceso en la sincronización con una distribución de claves opaca para el administrador. Ambos se apoyan en el cifrado de extremo a extremo de MindooDB.

Gobernanza integrada en el núcleo: los dispositivos cliente envían peticiones de escritura firmadas a través de una puerta de políticas formada por reglas firmadas por el administrador; las escrituras permitidas llegan a la base de datos cifrada y las denegadas se bloquean, mientras una cronología de auditoría muestra la autorización en cada instante
Por qué esto es gobernanza y no solo permisos

La gobernanza es una propiedad de la capa de datos

La mayoría de los stacks empujan la gobernanza hacia arriba, al servidor o a la aplicación: la base de datos guarda filas y algo distinto decide quién puede tocarlas y lleva el registro. MindooDB le da la vuelta. La política, la identidad, el historial completo y el registro de auditoría viven en los mismos almacenes append-only cifrados de extremo a extremo, así que las garantías viajan con los datos a través de servidores, peers y dispositivos sin conexión, y sobreviven a un servidor completamente comprometido.

La política, como datos versionados

Las políticas y las reglas son documentos firmados por el administrador en la base de datos del directorio, y son append-only ellos mismos. El momento exacto en que se activó la gobernanza - o se desactivó de forma temporal - forma parte del registro permanente, no es un cambio de configuración que no deja rastro.

Autorización reproducible

Cada entrada lleva una hora de confianza y el directorio mantiene una cadena de viaje en el tiempo de su propio historial. Así wasAllowedAt(op, user, dbid, at) puede reproducir qué reglas regían y quién estaba autorizado en cualquier momento del pasado: un veredicto determinista con el que coincide toda réplica honesta.

Responsabilidad demostrable

Cada cambio va firmado con Ed25519 para que no se pueda repudiar y queda atestiguado contra un reloj de confianza. Las infracciones no se descartan en silencio: quedan anotadas en un registro de cuarentena y auditoría por tenant que Haven muestra, así que incluso los intentos rechazados son rastreables.

Identidad, revocación y borrado

Las concesiones contienen matrices de claves por dispositivo; revocar es simplemente quitar claves, y un borrado remoto explícito elimina el tenant completo de un dispositivo robado o dado de baja la próxima vez que se conecta: el ciclo de vida de la identidad se gobierna en el mismo directorio firmado.

La idea central

El modelo de dos tiers

Cada regla cae en uno de los dos tiers según qué puede ver el servidor de sincronización. El servidor solo maneja texto cifrado más un pequeño conjunto de metadatos en claro: nunca puede leer el cuerpo de un documento. Esa única distinción es toda la arquitectura: le permite a MindooDB hacer una promesa honesta sobre qué está garantizado criptográficamente y qué se impone por política entre clientes que cooperan.

Tier 1 frente a Tier 2
Las reglas de identidad de Tier 1 comprueban el autor, la base de datos y el tipo de operación y las imponen tanto el servidor como los clientes; las reglas de contenido de Tier 2 comprueban withfields y solo las imponen los clientes
Una regla es de Tier 2 si y solo si tiene una cláusula withfields. Todo lo demás es Tier 1.
Los dos tiers, comparados
Tier Qué comprueba Quién lo impone Fuerza
Tier 1 - IdentidadIdentidad del autor, base de datos de destino, tipo de operación El servidor y los clientesCriptográfica - el servidor se niega a atestiguar una entrada infractora, así que no puede propagarse
Tier 2 - ContenidoEl contenido real del documento (withfields)Solo los clientes De política - acota a los clientes honestos y da forma a la UX. Un cliente manipulado solo puede saltársela en local; toda réplica honesta vuelve a comprobar withfields al recibir y pone en cuarentena el cambio infractor, así que nunca se hace visible para nadie más
El problema del reloj sin conexión

Recibos del testigo: un reloj de confianza que no depende de lo que diga el cliente

La pregunta más difícil en un sistema local-first es "¿de qué reloj nos fiamos?". Quien trabaja sin conexión podría antedatar sus propias entradas para colar un cambio por delante de una política. MindooDB lo resuelve con un recibo del testigo: una certificación, firmada por un testigo de confianza (tu servidor de sincronización), de que una entrada se aceptó en un momento concreto. Cada punto de aplicación usa así exactamente un reloj bien definido.

El ciclo de vida de una escritura
El dispositivo del autor crea una entrada y la envía; el servidor, como testigo, comprueba Tier 1, sella receivedAt y firma un recibo; las demás réplicas la recuperan y confían en el recibo. Una entrada denegada se queda en local y no puede sincronizarse.
Quien ha perdido un permiso simplemente no puede sincronizar el cambio en cuestión: el reloj sin conexión nunca sirve para antedatar y esquivar una política.
Escenario A
Escribir en local

El SDK evalúa Tier 1 + Tier 2 contra el estado local del directorio a la hora local actual. Si está permitido, la entrada se guarda en local sin campos de testigo y se ve al instante en ese dispositivo. El propio reloj del usuario rige su propia vista local, y eso no supone ningún problema porque el cambio todavía no ha entrado en el tenant compartido.

Escenario B
Enviar a un servidor

El servidor evalúa Tier 1 contra su propio estado a la hora del servidor. Si está permitido, sella receivedAt, anota la clave del testigo, firma el recibo y devuelve los campos del testigo para que lleguen al remitente y sigan su camino. Si lo deniega, devuelve un AccessDenied estructurado y la entrada se queda en local: no puede propagarse.

Escenario C
Recuperar de un servidor

Quien recibe verifica la firma del recibo contra su lista de testigos de confianza. Una firma válida significa que Tier 1 se cumplía en receivedAt, así que por defecto no se vuelve a evaluar. Después comprueba Tier 2 en local y o materializa el cambio o lo desvía a un registro local de cuarentena y auditoría.

Reglas, políticas e identidades

Cómo se configuran las decisiones

Todo el estado del control de acceso vive en la base de datos directory, accesible solo para administradores, y se sincroniza con todos los participantes. Todo lo que el servidor necesita para Tier 1 está cifrado con la clave $publicinfos, así que puede leerse sin tener la clave de tenant predeterminada; el contenido de withfields nunca es legible para el servidor. Toda llamada que modifica algo va firmada por el administrador.

Las políticas fijan la base

Una política de tenant predeterminada y políticas opcionales por base de datos definen qué operaciones se deniegan mientras no coincida una regla de permiso:

  • Create, change, delete & undelete - permitidos por defecto, hasta que los deniegues
  • Snapshot & purge - solo para administradores por defecto
  • Read - la base de la puerta de lectura y sincronización a nivel de base de datos, afinada con reglas de lectura
  • IDs de base de datos permitidos - la lista blanca del tenant con las bases de datos que pueden existir; el servidor se niega a crear o sincronizar cualquiera que quede fuera
  • Clave de cifrado predeterminada - qué clave usa un documento nuevo si no se indica ninguna; es una comodidad, no una medida de seguridad
  • Interruptor general - un solo indicador que desactiva de golpe todas las comprobaciones de acceso

Un tenant recién creado no tiene ningún documento de política, así que todo está permitido hasta que un administrador escriba uno. Cada revisión se añade al historial, de modo que la ventana exacta de activación y desactivación sigue siendo auditable. Y algo clave: cada cambio se juzga contra las políticas que estaban activas a su propia hora de confianza (receivedAt). Los cambios que entraron en el tenant después de la activación quedan cubiertos, mientras que los anteriores se resuelven contra la regla implícita de permitir todo, así que los datos preexistentes quedan a salvo automáticamente, sin ningún paso de migración.

Las reglas deciden con deny-overrides-allow

Cada regla apunta a un tipo de operación y a una base de datos ("*" = todas) y enumera los usuarios o grupos a los que se aplica. La evaluación se basa en conjuntos y no depende del orden:

  • si coincide alguna regla denydenegado
  • si no, si coincide alguna regla allowpermitido
  • si no, decide la política base

Que no dependa del orden importa porque los documentos de reglas se fusionan entre réplicas mediante CRDT: no hay ningún orden de reglas sobre el que discrepar.

Un servidor solo puede llegar a un veredicto de Tier 1. Si lo único que separa permitir de denegar es una regla de contenido de Tier 2, trata la entrada como permitida en Tier 1 y deja la comprobación de withfields a los clientes. Cada decisión devuelve un resultado estructurado - allowed, un reason legible, el matchedRuleId y el tier - que el SDK usa para atenuar las acciones que un usuario no puede realizar.

withfields: restricciones de contenido

Una cláusula withfields comprueba una ruta con puntos dentro del documento usando un conjunto cerrado de operadores (equals, contains, gt, …) y marcadores como ${user.usernames}. Cada cláusula se evalúa contra un estado del documento que tú eliges:

  • before - el documento existente (predeterminado para change y delete): "tienes que ser editor ya". Evaluar con after permitiría que alguien se añadiera a sí mismo y autorizara su propia edición.
  • after - el documento con el cambio aplicado (predeterminado para create): "quien lo crea tiene que añadirse a myeditors".
Identidades, grupos y revocación

Las reglas se comparan con el hash del nombre de usuario, con los hashes de sus grupos (también los grupos anidados) y con pseudotokens reservados:

  • $everyone - todos los usuarios registrados
  • $admin - solo el administrador
  • $author - quien creó originalmente el documento (Tier 1, modelo de propiedad)

La revocación se hace quitando claves del documento de concesión firmado por el administrador; no hay documentos de revocación aparte. Un administrador puede además firmar un borrado remoto del dispositivo explícito y opcional, que elimina el tenant de un dispositivo robado o dado de baja la próxima vez que se conecta.

Ejemplo práctico

Un CRM con editores por registro

Aquí recorremos una política realista de principio a fin para que las piezas encajen. El tenant tiene una base de datos crm y queremos cuatro reglas: todo el mundo puede crear contactos, pero tiene que incluirse en myeditors; solo quien ya figure como editor puede cambiar un contacto; solo quien lo creó puede borrarlo; y el grupo de RR. HH. puede cambiar lo que sea, como vía de escape para supervisión.

Alice crea un contacto

La base es deny. La regla 1 coincide vía $everyone y su withfields pasa porque el myeditors del estado after contiene a Alice → permitido. El servidor solo confirma Tier 1 y después atestigua la entrada.

Bob (que no es editor) intenta cambiarlo

La regla 2 coincide por $everyone, pero su withfields falla: el myeditors del estado before no contiene a Bob → denegado en local, aunque su cambio intente añadirlo. Un cliente manipulado podría enviarlo, pero toda réplica honesta lo pone en cuarentena al materializarlo.

Alice borra y RR. HH. se impone

La regla 3 coincide vía $author: la clave de creación y quien firma el borrado se resuelven al mismo usuario → permitido y atestiguado (Tier 1, sobrevive a un cliente malicioso). La regla 4 deja que cualquier miembro del grupo de RR. HH. cambie cualquier contacto, sin importar myeditors.

Esto muestra el reparto de trabajo: las reglas de Tier 1 ($author, el grupo hr) las impone el servidor y sobreviven a un cliente malicioso; las de Tier 2 (las comprobaciones de contenido sobre myeditors) las impone cada cliente honesto y se ponen en cuarentena al recibirlas si se incumplen.

El lado de la lectura

Control de acceso de lectura

Las reglas de escritura deciden quién puede cambiar los datos; el acceso de lectura decide quién puede verlos, y MindooDB lo impone en dos niveles, ambos firmados por el administrador y cifrados con $publicinfos para que el servidor de confianza cero pueda actuar sobre los metadatos que necesita sin tener nunca la clave del tenant.

1. Una puerta de lectura y sincronización a nivel de base de datos. Una base denyDocRead más las reglas doc_read (la misma evaluación deny-overrides-allow, apuntando a usuarios, grupos, $everyone o $admin) deciden quién puede abrir y sincronizar una base de datos en absoluto. Está tejida directamente en el sistema de sincronización: quien pierde el acceso de lectura deja de recibir actualizaciones y ya no puede ni abrir la copia local que ya tenía sincronizada. Como la puerta se sitúa delante de toda operación de sincronización, la lectura es la puerta maestra de cada base de datos y también gobierna la escritura: quien no puede leer una base de datos tampoco puede crear datos en ella (si no, escribiría documentos que nunca podría ver).

2. La confidencialidad de los documentos sigue siendo criptográfica. Un documento solo puede leerlo quien tenga en su KeyBag (su almacén de claves personal, protegido por contraseña) una clave que lo descifre; aquí el servidor nunca toma una decisión de lectura. La distribución de claves es la forma de llevar esas claves a las personas correctas de manera segura: una política firmada por el administrador dice qué usuarios y grupos deben tener cada clave, y cada cliente mantiene su KeyBag al día con ella automáticamente. Hay que activarlo expresamente: con la clave predeterminada compartida y sin puerta de lectura, todo el mundo puede leer todo, exactamente como antes.

Una puerta de lectura tejida en la sincronización

En el punto de paso del servidor, el mismo hook que evalúa la lista blanca de IDs de base de datos evalúa también doc_read para el principal autenticado contra la hora de confianza del servidor, y se niega a servir ni a aceptar envíos de una base de datos denegada: las actualizaciones no permitidas simplemente no se entregan nunca. A la par, el camino de apertura en el cliente se niega a abrir una base de datos a la que el usuario ha perdido el acceso, así que un usuario revocado no puede ni leer su copia sincronizada en local. La base de datos directory nunca pasa por la puerta (lleva justo las políticas de las que la puerta depende); el administrador queda exento.

Las claves viajan cifradas para cada destinatario

Cuando una clave se envía a un usuario, se cifra con la clave pública (RSA) personal de ese usuario, así que solo él puede desenvolverla: ningún otro usuario, y ni siquiera el administrador, puede leer la clave. Por eso la distribución es opaca para el administrador: quien ya tiene la clave la empaqueta para los destinatarios y el administrador solo firma y publica el resultado. Un usuario normal puede preparar una distribución y entregarla a un administrador para que la firme, incluso a uno que no tenga la clave.

Enviar una clave revela datos; retirarla los oculta

Cada cliente mantiene su KeyBag al día con la política al arrancar y después de cada sincronización. Envía una clave a un usuario y su siguiente sincronización traerá los documentos que esa clave abre: simplemente aparecen en la base de datos, ya legibles. Retira la clave y esos documentos desaparecen: las copias locales que ya no se pueden descifrar se eliminan de la base de datos, de las cachés y de las vistas. Los ascensos, las rotaciones y los cambios de departamento se gestionan automáticamente por esta vía.

El corte de verdad es la rotación

Como medida de ahorro de ancho de banda, el servidor también deja de entregar datos cifrados con una clave que un usuario ha perdido. Pero quien sale y se ha quedado con una copia antigua todavía puede leer lo que ya tenía, así que el corte real es la rotación: emite una versión nueva de la clave solo para los destinatarios que quedan y todo cambio futuro usará una versión que esa persona nunca recibió.

Distribuir apps

Distribución de apps basada en políticas

La misma maquinaria firmada por el administrador que distribuye claves distribuye también aplicaciones de Haven. El administrador publica una política que nombra qué apps ofrece un tenant y quién debe recibirlas, y cada cliente Haven reconcilia su lista local de aplicaciones con esa política después de sincronizar el directorio: así, dar de alta a alguien en un tenant instala automáticamente las apps que ese tenant publica, y revocarle el acceso las vuelve a quitar.

A diferencia de una clave, una app no lleva ningún secreto, así que distribuirla es solo una cuestión de quién recibe qué. La definición de la app y sus metadatos están cifrados con la clave del tenant, así que el servidor de confianza cero solo ve texto cifrado y aun así encamina la política a los destinatarios correctos.

Enviar a usuarios y grupos (y retirar de ellos)

Una política apunta tanto a usuarios concretos como a grupos enteros. Una lista de envío dice quién debe recibir una app; una lista de retirada la quita. La pertenencia a un grupo se resuelve en el momento de distribuir, así que añadir o quitar a alguien de un grupo cambia quién recibe la app sin tocar la política, y cuando ambas listas se solapan, la retirada siempre gana.

Preparada por los usuarios, firmada por el administrador

Un usuario normal puede preparar una distribución nueva - o un cambio en una existente - y entregarla al administrador como una solicitud lista para firmar. El administrador la revisa y firma el documento de política; solo esa firma la hace vinculante. Funciona exactamente igual que la distribución de claves, así que quien ya gestiona claves gestiona apps.

Instalar, actualizar y quitar automáticamente

Después de cada sincronización del directorio, cada cliente compara la política con lo que tiene en local: instala las apps que ahora le corresponden, actualiza una cuando cambian la versión publicada o los detalles y quita cualquier app a la que ya no tenga derecho, todo sin que el usuario levante un dedo.

Claramente gestionada por el tenant

Una app distribuida se marca como gestionada por el tenant y muestra de qué tenant viene. El usuario no puede editar ni quitar las apps gestionadas, solo duplicarlas en una copia privada para construir y probar en local, de modo que la versión publicada por el tenant sigue siendo la referencia.

Auditoría y alcance

Auditable por diseño, honesto sobre sus límites

Reproducible para cualquier instante

Como cada entrada lleva una hora de confianza (receivedAt, o createdAt como respaldo en las entradas que solo existen en local) y el directorio mantiene una cadena de viaje en el tiempo de su propio historial, puedes responder a "¿tenía el usuario X permiso para cambiar este documento cuando el cambio entró de verdad en el tenant?" y reconstruir con exactitud cómo evolucionó su acceso. La consulta wasAllowedAt(op, user, dbid, at) lo convierte en una API de primera clase. Las infracciones de Tier 2 no desaparecen en silencio: quedan anotadas en un registro de cuarentena por tenant que Haven muestra en su vista de auditoría.

Alcance y no objetivos de la v1

Esta capa gobierna tanto la escritura como la lectura (a nivel de documento y de clave). No puede impedir que un cliente manipulado redacte una entrada en local, pero sí evita que esa entrada se acepte en el tenant, y la puerta de lectura del servidor impide que los datos sin derecho lleguen nunca a un cliente. La v1 apunta a la sincronización mediada por servidor como testigo. La sincronización de dispositivo a dispositivo por Iroh ya existe, pero un peer no sella ningún recibo de testigo: el dispositivo que recibe evalúa él mismo las reglas de identidad, y el servidor vuelve a juzgar la entrada cuando llega. Los recibos de testigo emitidos por un peer y un control de lectura real a nivel de campo (claves por campo) siguen siendo trabajo futuro. El historial nunca se vuelve a cifrar sobre sí mismo, porque las firmas de autoría cubren el texto cifrado.

Verlo en acción
Haven - el espacio de trabajo construido sobre este modelo de acceso

MindooDB Haven lleva ese mismo cifrado de extremo a extremo, ese historial firmado y esa gobernanza integrada a un espacio de trabajo sereno y multiplataforma, con la vista de auditoría que saca a la luz los cambios en cuarentena. Prueba la beta gratuita o entra en los análisis a fondo.