⭐ El catálogo como ORIGEN del grafo — por qué OpenFGA es la pieza, no un rodeo
Decisión de arquitectura, 2026-08-06. Reencuadra F4 y corrige la recomendación del
reconocimiento, que proponía «OPA con políticas
alimentadas por Index» por descarte de OpenFGA.Ese descarte estaba mal fundado: juzgaba OpenFGA como «un store opaco que duplica
principal_grants» — cierto si la autorización fuera el fin, falso cuando el fin es
un grafo de contexto que HEREDA del catálogo.
1 · La tesis de producto, y qué exige de la infraestructura
La cuña: trae tus datos estructurados y no estructurados a un catálogo nativo
enterprise, y conviértelos en contexto listo para agentes, LLMs y humanos —
promocionando data assets y data products a un grafo semántico ontológico.Y la regla que lo hace defendible: la gobernanza, el linaje, los permisos y las
políticas EMANAN DEL CATÁLOGO — no se construyen encima del grafo.
Eso último no es un eslogan: es un requisito técnico con una consecuencia dura.
Si el grafo hereda en vez de re-declarar, entonces el sustrato de permisos tiene
que ser transitable por relaciones — porque «¿puede este agente ver este Pod?» se
responde recorriendo Pod → Table → Namespace → Warehouse → Workspace. Un modelo de
permisos plano (una fila por principal × privilegio × objeto) no responde eso sin
programarlo a mano.
⇒ El sustrato tiene que ser un grafo. Y eso es exactamente lo que es OpenFGA.
2 · Por qué OpenFGA encaja — verificado, no supuesto
① Es ReBAC (Zanzibar): las preguntas de autorización son preguntas de grafo
«Most real authorization questions are graph questions: "Can this user read this
document?" depends on whether they're a member of the team that owns the project that
contains the document.»
Tuplas (objeto, relación, usuario) — la misma forma que una arista. La topología del
permiso y la topología del conocimiento son el mismo tipo de estructura.
② El modelo de Lakekeeper ya es jerárquico y bidireccional
Tipos: Server · Project · Warehouse · Namespace · Table · View ·
Generic Table · Role · Tag.
Relaciones: ownership · grants · describe · select · create · modify ·
manage_tags.
| Dirección | Qué hace |
|---|---|
| Top-down | «permissions in higher-up entities are inherited to their children» — un modify sobre el warehouse cae en cascada a namespaces, tablas y vistas |
| Bottom-up | select sobre una tabla da listado limitado en los namespaces padre — «only items in the direct path are presented to users» |
⭐ El bottom-up resuelve C3 nativamente, y eso no lo habíamos visto
Hoy
listTablesno filtra por inquilino, y el propio código lo admite como
pendiente. YlistNamespacesfiltra por el primer nivel, con el efecto de que
producción vemain.test(C2). Las dos son exactamente lo que la herencia
bottom-up de OpenFGA hace de fábrica. No es un extra: es trabajo que dejamos de
escribir, y que hoy está a medias.
③ El bridge OPA es OSS — la lección de Cedar no se repite
«The Bridge itself is a collection of OPA files in the
authz/opa-bridgefolder of
the Lakekeeper GitHub repository.»
Son ficheros Rego en el repo público, no un binario de la edición comercial. Es una
instancia de OPA cargando esas políticas; Trino apunta a
opa.policy.uri=…/v1/data/trino/allow y opa.policy.batched-uri=…/v1/data/trino/batch.
⚠️ Y es la diferencia con Cedar, que sí era comercial y arrancaba fingiendo estar activo. Aquí hay código que se puede leer antes de desplegar.
④ Y el propio proyecto enuncia el argumento del usuario
«…so engines that run their own access control via OPA — Trino today — enforce the
same permissions instead of a second, drifting copy.»
⑤ En OSS, OpenFGA no es una opción: es la única
crates/authz-openfga es el único backend del build Apache-2.0 (Cedar es comercial). ⇒
si queremos que el catálogo autorice, es OpenFGA o nada.
3 · La cuña frente a Stardog — y es mayor de lo que parece
Medido en su documentación:
| Stardog + Unity Catalog | Carbon | |
|---|---|---|
| Relación con el catálogo | externo y ajeno (Databricks, Snowflake) | ⭐ nativo y propio |
| Cómo llega la metadata | «a job … runs on the specified schedule… will import Unity metadata» — se copia | no se copia: ya está |
| Frescura | la del último job | la del catálogo |
| Qué se hereda | metadata, linaje, ownership — para VER | metadata, linaje y los permisos, APLICADOS |
| Autorización | de cada sistema por separado | una sola, y el motor la ejecuta |
La diferencia no es «nosotros también tenemos grafo». Es que en Stardog el grafo
muestra la gobernanza de otro; en Carbon el grafo hereda una gobernanza que se
aplica — porque el catálogo es nuestro y el motor pregunta al mismo sitio.Y es lo que hace que «el agente nunca ve las tablas» sea una propiedad y no una
promesa: el Pod hereda del asset, el asset del namespace, el namespace del warehouse.
4 · La arquitectura resultante
agentes · LLMs · humanos BI · notebooks · JDBC
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ GRAFO SEMÁNTICO│ │ TRINO │
│ Pods · ontología│ └────────┬────────┘
└────────┬────────┘ │ nativo
│ hereda por RELACIÓN ▼
│ ┌───────────────┐
│ │ OPA │ ← bridge (Rego, OSS)
│ └───────┬───────┘
└───────────────┬────────────────────────────┘
▼
┌─────────────────────┐
│ OPENFGA │ ReBAC · el GRAFO de permisos
└──────────┬──────────┘
│
┌─────────────────────┐
│ LAKEKEEPER (cat.) │ + INDEX (lo que el catálogo no sabe:
└─────────────────────┘ linaje, calidad, tier, ontología)
El punto que hay que retener: Trino no habla con OpenFGA. Habla con OPA, que es su mecanismo nativo, y el bridge traduce. Nadie escribe políticas de negocio en Rego.
5 · Las cinco tensiones — dichas antes de comprometerse
🔴 T1 · ¿Quién es la SSOT de permisos: Index u OpenFGA?
Hoy principal_grants de Index decide y la cara aplica — probado en F2 (403 por
schema, CREATE TABLE denegado). Meter OpenFGA sin decidir esto crea dos sistemas
afirmando autoridad sobre el mismo hecho, que es literalmente el error del espejo de
nombres que N·1 corrigió.
La respuesta coherente con la tesis:
| SSOT | |
|---|---|
| Permisos sobre objetos del catálogo (warehouse · namespace · tabla · vista) | OpenFGA |
| Todo lo que el catálogo no puede saber (linaje, calidad, tier, procedencia, ontología, Pods) | Index |
⇒ principal_grants migra a OpenFGA y la cara pasa a consultarlo. No es cableado: es
mover la autoridad. Y hay que decidirlo antes de escribir una línea.
🟠 T2 · El modelo de Index es MÁS RICO que el de Lakekeeper
Index: CATALOG_* · SCHEMA_* · TABLE_* · VIEW_* · POLICY_* · WORKSPACE_* (con
TABLE_READ_PROPERTIES ≠ TABLE_READ_DATA, que es la distinción que hace posible el
vending).
Lakekeeper: ownership · grants · describe · select · create · modify ·
manage_tags.
⇒ [confirmar] el mapeo, privilegio a privilegio. Si algo de Index no tiene
equivalente —sospecha principal: la separación metadata vs datos— o se modela con tipos
propios, o se queda en Index y hay dos planos por razón, no por descuido.
🟠 T3 · ⚠️ ¿Podemos añadir NUESTROS tipos al modelo? — la incógnita que decide la jugada
Para que un Pod herede permisos por relación, tiene que ser un objeto en el grafo de
OpenFGA, con una relación hacia su Table.
- OpenFGA soporta modular models: «types can be defined across different modules and files», para que cada equipo evolucione lo suyo.
- Pero Lakekeeper gestiona SU store y escribe su modelo, y los modelos de OpenFGA son inmutables (versionados).
⇒ [confirmar] con OpenFGA desplegado: ¿se puede extender el modelo de Lakekeeper con
un módulo propio, o hacen falta dos stores y una relación entre ellos? De esto
depende que la herencia sea nativa o haya que puentearla — y es la única pregunta de
este documento que no se puede responder leyendo.
🟡 T4 · Sigue siendo UNA capa, no dos
La propia doc avisa: «ensure that no users have root access to trino or OPA as those contain credentials to Lakekeeper with very high permissions». Es el mismo modelo de confianza que el runbook ya tiene escrito (compute enforces permissions) y la misma raíz que trino#27917. OpenFGA no lo cambia. El aislamiento duro se sigue comprando con cluster por inquilino.
🟡 T5 · Un servicio más
OpenFGA v1.11+, con su datastore. Coste operativo real, y hay que presupuestarlo.
6 · Lo que esto cambia en F4
El reconocimiento recomendaba B (OPA alimentado por Index). Queda sustituido por A, con un motivo que no es de autorización sino de producto: B no da herencia topológica —habría que programarla— y la herencia es el mecanismo de la tesis, no un detalle.
| Fase | Qué |
|---|---|
| F4·0 | Desplegar OpenFGA + AUTHZ_BACKEND=openfga. ⚠️ Y limpiar la variable de Cedar, que hoy sugiere una protección inexistente |
| F4·1 | Migrar principal_grants → tuplas de OpenFGA (T1). Gate: los mismos 403 de F2, ahora decididos por OpenFGA |
| F4·2 | Desplegar el bridge OPA y apuntar Trino. Gate: SELECT sobre schema sin grant → denegado por el motor |
| F4·3 | ⭐ Retirar el filtrado a mano de la cara (listNamespaces/listTables) y dejar que lo haga la herencia bottom-up. Es donde C2 y C3 mueren |
| F4·4 | 🔬 El experimento de T3: un tipo propio (Pod) relacionado con Table, y comprobar si check hereda |
F4·4 es el que vale más y el que menos cuesta. Si la herencia funciona, la tesis del
producto tiene sustrato nativo. Si no, hay que puentear — y es mejor saberlo con un
experimento de una tarde que después de migrar los permisos.
7 · Lo que sigue sin resolver
- Row filters y column masks siguen sin salir de aquí: OpenFGA responde «¿puede ver esta tabla?», no «qué filas». Eso sigue siendo F4·b y sigue exigiendo un modelo de políticas de fila que Index hoy no tiene.
- El orden frente a H1 (namespace plano). La herencia de OpenFGA es sobre namespaces jerárquicos; conviene decidir H1 antes de poblar tuplas, o se poblarán dos veces.
Cruza con: f4-opa-reconocimiento.md (el terreno medido, cuya
recomendación esto corrige) · trino-first-viraje.md ·
agentic-data-cloud.md (la tesis de producto) ·
warehouse-index.md (qué se queda en Index) ·
infra/lakekeeper/policies/README.md.