⭐ Ontology Projection — el catálogo escribe, el grafo lee
Entregable de arquitectura, 2026-08-06. Fija dos cosas que hasta hoy estaban
difusas y una que estaba mal:
- Qué es Index frente a Lakekeeper y OpenFGA — no compiten: Index los manda.
- Qué es el grafo frente al catálogo — CQRS a nivel de datos: el catálogo es el
write/governance model, el grafo el context read-model.- 🔴 Se retira la noción de «Pod». Era poco precisa y ocultaba el mecanismo.
Sustituye el encuadre de agentic-data-cloud.md en lo que
respecta al primitivo. Cruza con
catalogo-como-origen-del-grafo.md, que explica por
qué el sustrato de permisos es OpenFGA.
1 · Index no compite con Lakekeeper ni con OpenFGA: los unifica
La lectura equivocada —y estaba en el reconocimiento de F4— es tratarlo como un reparto de territorio: «si OpenFGA guarda los permisos, ¿qué le queda a Index?». Esa pregunta da por hecho que el valor está en poseer las piezas.
No lo está. El valor está en que sean UNA.
| Pieza | Qué resuelve | De quién es |
|---|---|---|
| Lakekeeper | el catálogo Iceberg: qué tablas, qué snapshot, qué esquema físico | estándar abierto |
| OpenFGA | el grafo de permisos: ReBAC, herencia bidireccional | CNCF |
| R2 / Parquet | los bytes | estándar abierto |
| Trino / DuckDB | el cómputo | estándar abierto |
| ⭐ Index | que todo lo anterior sea un solo entorno distribuido con un mando | nuestro |
Index es software de UNIFICACIÓN Y MANDO. Su valor no es guardar lo que otros
guardan mejor: es que el alta de una organización, la promoción de un asset, la
concesión de un permiso y la proyección al grafo sean UNA operación en vez de cuatro
sistemas que alguien tiene que coordinar a mano.Es exactamente lo que hace Unity Catalog, y es su valor real: no inventó Parquet, ni
Delta, ni el motor. Inventó que fueran uno.
⇒ T1 del documento anterior queda disuelta, no resuelta. La pregunta «¿quién es la SSOT de permisos?» estaba mal planteada:
| OpenFGA | es el almacén y evaluador de permisos — lo hace mejor que nosotros, con herencia topológica que no vamos a reimplementar |
| Index | es quien decide qué permisos existen, cuándo se conceden y por qué — el alta, la coordenada, la política, el ciclo de vida |
Un almacén no es una autoridad. principal_grants no desaparece: pasa a ser la
intención declarada, y OpenFGA su forma ejecutable — la misma relación que ya existe
entre «qué íbamos a hacer» y el commit de Iceberg en el ledger.
2 · 🔴 Se retira «Pod»
Por qué era poco preciso: «Pod» nombraba un objeto («el objeto de negocio gobernado e hidratado») y con eso escondía la pregunta que importa — de dónde sale y qué garantiza. Un nombre de objeto invita a construir una tabla de objetos; y en cuanto hay una tabla de Pods, hay una copia que alguien tiene que sincronizar.
Lo que lo sustituye no es otro nombre: es un mecanismo.
3 · El modelo: CQRS a nivel de datos
┌──────────── PLANO DE CONTROL · Write / Governance Model ──────────────┐
│ │
│ EL CATÁLOGO — Source of Truth │
│ · los datos, crudos y curados (R2 · Parquet · Iceberg) │
│ · el linaje FÍSICO (snapshots, commits) │
│ · las políticas de seguridad y acceso (OpenFGA) │
│ · la coordenada, el tier, la calidad (Index) │
│ │
└───────────────────────────────┬───────────────────────────────────────┘
│
PROYECCIÓN ONTOLÓGICA
(derivación, no importación)
│
▼
┌──────────── PLANO DE LECTURA · Context Read-Model ────────────────────┐
│ │
│ EL GRAFO (Memgraph / capa semántica) │
│ · relaciones semánticas y ontologías │
│ · ⭐ PUNTEROS GOBERNADOS — no copias del dato │
│ · optimizado para TRAVERSING de LLMs/agentes y navegación humana │
│ │
└───────────────────────────────────────────────────────────────────────┘
Las tres reglas que definen el patrón:
| Regla | Consecuencia | |
|---|---|---|
| R1 | El grafo nunca es autoridad. No se escribe gobernanza en él | una política sólo existe si existe en el catálogo. Sin excepción |
| R2 | El grafo no guarda dato crudo. Guarda relaciones y punteros gobernados | el grafo no puede filtrarse por su cuenta ni quedar obsoleto respecto al dato |
| R3 | El grafo se DERIVA. Si se pierde, se reproyecta | es un read-model: desechable por definición. Perderlo es un incidente de latencia, no de datos |
R3 es el test que distingue esto de un ETL. Si borrar el grafo perdiera algo
irrecuperable, no sería una proyección: sería un segundo almacén — y entonces habría que
gobernarlo aparte, que es exactamente lo que este diseño evita.
4 · Proyección ontológica ≠ ETL de metadatos
Es la diferencia con Stardog, y ahora tiene nombre técnico:
| ETL de metadatos (Stardog + Unity/Snowflake) | ⭐ Ontology Projection (Carbon) | |
|---|---|---|
| Relación con el catálogo | externo y ajeno | nativo y propio |
| Mecanismo | «a job runs on the specified schedule… will import Unity metadata» | derivación del catálogo que ya poseemos |
| Qué produce | una copia semántica de metadata | una vista semántica sobre punteros vivos |
| Frescura | la del último job | la de la proyección |
| Los permisos | se muestran; cada sistema autoriza por su cuenta | se heredan y se aplican — mismo grafo ReBAC |
| Si el origen cambia | la copia deriva hasta el próximo job | el puntero sigue siendo el mismo |
La frase que lo resume: el grafo no es una representación importada del catálogo;
es una proyección semántica del catálogo nativo. Stardog hace copias de metadatos
ajenos porque no tiene otra opción — el catálogo no es suyo. Nosotros no copiamos
porque no hace falta.
5 · ⭐ El punto que lo hace difícil, y donde OpenFGA se gana el sitio
Un read-model tiene que estar filtrado, o revela lo que oculta.
Si un agente atraviesa el grafo y llega a un nodo que no puede leer, aunque el resolve del puntero lo deniegue, ya ha aprendido que ese nodo existe — su nombre, su tipo, sus relaciones. En un grafo de conocimiento la topología ES información: saber que «Cliente» se relaciona con «Incidencia_Legal» dice algo aunque no se lean las filas.
⇒ No basta con gobernar el resolve. Hay que gobernar el TRAVERSING.
Y ahí es donde el sustrato deja de ser una preferencia:
- las aristas del grafo semántico y las tuplas de OpenFGA son la misma clase de objeto;
- la herencia bottom-up de OpenFGA —«only items in the direct path are presented to users»— es literalmente «enséñame sólo el trozo de grafo que me toca»;
- ⇒ filtrar el grafo por permisos es un
list-objectsde OpenFGA, no un post-filtro que haya que programar y mantener.
Éste es el argumento que hace a OpenFGA imprescindible, y no es de autorización: es de
producto. Con un modelo plano de permisos, cada consulta del agente exigiría recorrer
el grafo y filtrar a mano, con el riesgo permanente de que una arista se escape. Con
ReBAC, el grafo que el agente ve ya nace acotado.
6 · Lo que esto cambia en el trabajo
| F4 | Deja de ser «autorización para Trino» y pasa a ser el sustrato del read-model. Su valor no se cobra en F4: se cobra cuando el grafo exista |
| T3 (la incógnita) | Se reformula, y mejor: ya no es «¿cabe un Pod en el modelo de OpenFGA?» sino «¿puede un tipo propio (Concept, Entity) relacionarse con Table y heredar?». Sigue siendo el experimento que decide, y sigue costando una tarde |
agentic-data-cloud.md | Hay que barrer «Pod» del corpus y sustituirlo por el mecanismo |
| Index | Gana una responsabilidad explícita: ser quien proyecta — el alta de un asset y su aparición en el grafo son la misma operación, no dos |
7 · Las tres tensiones honestas del patrón
⚠️ C1 · CQRS trae consistencia eventual — y hay que decir cuánta
El read-model va por detrás. La pregunta no es si eso pasa, sino cuánto y qué se rompe: un agente puede ver una relación que ya no existe, o no ver una que acaba de nacer.
Mitigación estructural, y es lo que hace R2 imprescindible: como el grafo guarda punteros y no dato, el peor caso es «te enseño un puntero que ya no resuelve» — molesto y recuperable. Nunca es «te doy dato obsoleto», que sería inaceptable.
⚠️ Pero sí puede ser «te enseño una relación que ya no deberías ver» si la proyección de permisos va por detrás. ⇒ los permisos NO se proyectan: se consultan en vivo contra OpenFGA. El grafo proyecta estructura, no autorización.
⚠️ C2 · La proyección necesita un disparador, y hoy NO lo tenemos
¿Cómo se entera el grafo de que el catálogo cambió? Lakekeeper emite CloudEvents…
pero ya está medido (index-n0-n2-approach.md §4.1): los
únicos sinks son NATS y Kafka, no corremos ninguno, y LOG_CLOUDEVENTS sólo escribe
líneas de log.
⇒ La proyección arranca por PULL, exactamente como se decidió para N·2b. Push cuando la latencia lo pida, y con datos.
⚠️ C3 · Memgraph es un servicio más
Con OpenFGA ya son dos servicios nuevos. Y conviene ser explícito sobre el orden: OpenFGA sirve para algo hoy (F4, Trino); Memgraph no sirve para nada hasta que haya proyección. ⇒ OpenFGA ahora, Memgraph cuando el read-model tenga qué leer.
Cruza con: catalogo-como-origen-del-grafo.md (por qué OpenFGA) · agentic-data-cloud.md (la tesis de producto, cuyo primitivo esto corrige) · warehouse-index.md (qué es Index) · index-frontier.md (el patrón control/datos/hechos, del que esto es la continuación natural).