Ir al contenido

La superficie de consultas (OSL-SQL)

POST /osl/query es el único endpoint de consumo. La analítica estructurada, las métricas, el retrieval vectorial gobernado y la travesía de grafos se expresan todos aquí — no aprendes cinco superficies para leer un dominio.

POST /osl/query
Authorization: Bearer <jwt> # attested delegation chain, see Authentication
Content-Type: application/json

El body es una de tres formas mutuamente excluyentes (mezclarlas es 400 E0513); las tres pasan por la misma costura gobernada y comparten un mismo request_id:

Body Qué es
{ "osql": "…" } OSL-SQL — el dialecto de SQL semántico (la superficie canónica)
{ "sql": "…" } Un SELECT crudo de solo lectura sobre el allowlist del tenant (el slice de SQL)
{ "metrics": […], "group_by": […], … } Consulta de métricas al estilo MetricFlow

osql es un dialecto de SQL semántico. Nombra solo objetos semánticos — osl.entities.<model> y columnas declaradas, o las funciones de tabla RETRIEVE(...) / TRAVERSE(...). Nunca nombra una tabla física ni una columna cruda.

El motor parsea osql (vía sqlglot, dialecto trino) y lo reduce a un IR de operadores cerrado — la escalera determinista sobre la que aplica el modelo de gobernanza. El lowering es total y default-deny: cualquier construcción que no reduzca a un nodo IR conocido se rechaza.

lower() clasifica cada consulta en exactamente una forma y valida su gramática:

SELECT segment, COUNT(*) AS n
FROM osl.entities.Customer
WHERE country IN ('ES','FR','DE')
GROUP BY segment
ORDER BY n DESC
LIMIT 100

Reduce a to_trino() → la costura de SQL gobernada. Los joins entre entidades estructuradas solo se permiten como un equijoin de clave sellada (ver abajo).

El único nodo cross-relacional es un equijoin cuyo ON es una igualdad escalar sobre una clave de entidad sellada (las entity_key_columns del modelo, o el campo scalar_indexed de una faceta) en ambas piernas. Cualquier otro JOIN … ON400 E0514.

No hay sintaxis que pase un segundo argumento relacional a un operador de similitud o de LLM — un join semántico relación×relación en query time (el no-objetivo R3) es una propiedad estructural de la gramática, no una blocklist que mantener.

X JOIN RETRIEVE(...) ON X.k = R.k no es un join relacional de dos tablas físicas. Corre así:

  1. RETRIEVE (gobernado) → passages, cada uno con su clave desnormalizada.
  2. Compuerta en claro → los valores de la clave, o rechazo (403 E0515).
  3. Prefiltro estructurado: … WHERE k IN (<keys>)to_trino → SQL gobernado (la lista IN se construye con conversión de literales de sqlglot — a prueba de inyección).
  4. Hash join en la celda sobre la clave sellada, proyectando las columnas de cada pierna.

En la forma RETRIEVE, un <op>(col) en el SELECT es un operador de proyección (RFC 0004). Son mapas unarios — nunca un join.

Clase Operadores Se ejecuta en Si falta
Encoder (determinista) SIMILARITY, CLASSIFY, TAG, RANK, DEDUP, OUTLIER, CLUSTER Sobre los embeddings ya presentes en el chunk
Decoder (inferencia) necesita LLM EXTRACT, SUMMARIZE, SCORE, GENERATE, COMPLETE Un backend LLM 503 E0521

{ "sql": "<SELECT>" } es un SELECT de solo lectura validado contra el allowlist del tenant con el punto de aplicación de política aplicado (filtros de filas + proyección del snapshot compuesto). { "metrics": …, "group_by": … } sigue la semántica de MetricFlow. Ambos comparten la misma costura gobernada que osql.

Código Significado
200 Éxito
400 Malformada / fuera de gramática (E0511), objeto no declarado (E0512), el body mezcla formas (E0513), JOIN sin clave sellada (E0514), sql vacío (E0246)
403 Deny del PDP (E2101/E2102), clave cross-modal no en claro (E0515), objeto fuera del allowlist (E0512)
422 Válida pero no resoluble — p. ej. MetricFlow aún no implementado (E1001)
503 Falta el snapshot del PDP (E2001, fail-closed), op decoder sin backend LLM (E0521)
502 Fallo de ejecución de Trino (E0510)

Ver Errores y códigos de estado para el envelope completo.