La superfície de query (OSL-SQL)
POST /osl/query és l’únic endpoint de consum. L’analítica estructurada, les
mètriques, el retrieval vectorial governat i la travessa de grafs s’expressen tots
aquí — no aprens cinc superfícies per llegir un domini.
POST /osl/queryAuthorization: Bearer <jwt> # attested delegation chain, see AuthenticationContent-Type: application/jsonEl body és una de tres formes mútuament excloents (barrejar-les és 400 E0513);
totes tres passen per la mateixa junta governada i comparteixen un request_id:
| Body | Què és |
|---|---|
{ "osql": "…" } |
OSL-SQL — el dialecte SQL semàntic (la superfície canònica) |
{ "sql": "…" } |
Un SELECT de només lectura sobre l’allowlist del tenant (el slice SQL) |
{ "metrics": […], "group_by": […], … } |
Query de mètriques a l’estil MetricFlow |
OSL-SQL
Section titled “OSL-SQL”osql és un dialecte SQL semàntic. Anomena només objectes semàntics —
osl.entities.<model> i columnes declarades, o les funcions de taula
RETRIEVE(...) / TRAVERSE(...). Mai anomena una taula física ni una columna
crua.
El lowering és la frontera de seguretat
Section titled “El lowering és la frontera de seguretat”El motor parseja osql (via sqlglot, dialecte trino) i el baixa a una IR
d’operadors tancada — l’escala determinista sobre la qual aplica el
model de governança. El lowering és total i
default-deny: qualsevol construcció que no baixi a un node d’IR conegut es refusa.
Les cinc formes
Section titled “Les cinc formes”lower() classifica cada query en exactament una forma i valida la seva gramàtica:
SELECT segment, COUNT(*) AS nFROM osl.entities.CustomerWHERE country IN ('ES','FR','DE')GROUP BY segmentORDER BY n DESCLIMIT 100Baixa a to_trino() → la junta SQL governada. Els joins entre entitats
estructurades només s’admeten com un equijoin de clau segellada (vegeu més avall).
SELECT SUMMARIZE(text) AS summary, scoreFROM RETRIEVE(facet => 'meeting_transcripts', query => 'european equity exposure', top_k => 5)Baixa al store Lance + retrieval governats. Una columna nua passa directament; un
<op>(col) al SELECT és un operador de projecció.
SELECT concepto, amount_eurFROM TRAVERSE(anchor => 'customer', target => 'orders', keys => ('c-anna', 'c-bruno'))Baixa a la travessa L2 governada des de les claus àncora (hop-by-hop, cardinalitat acotada + dedup).
SELECT name, segment, recent_meeting_topicsFROM osl.entities.CustomerWHERE customer_id IN ('9c1e…f04a', 'e4f8…2a91')La forma “registre” entity-first: columnes estructurades + evidència Lance + atributs derivats per a les claus donades, en una sola resolució.
SELECT x.segment, r.text, r.scoreFROM osl.entities.Customer xJOIN RETRIEVE(facet => 'meeting_transcripts', query => 'churn risk') r ON x.customer_id = r.customer_id“La relació és un filtre”: RETRIEVE corre primer, les seves claus prefiltren la pota estructural, després un hash join in-cell sobre la clau segellada. Vegeu més avall.
R3 és inexpressable, no bloquejat
Section titled “R3 és inexpressable, no bloquejat”L’únic node cross-relacional és un equijoin l’ON del qual és una igualtat
escalar sobre una clau d’entitat segellada (les entity_key_columns del model, o
el camp scalar_indexed d’una faceta) a totes dues potes. Qualsevol altre
JOIN … ON → 400 E0514.
No hi ha cap sintaxi que passi un segon argument relacional a un operador de similitud o LLM — un join semàntic relació×relació en temps de query (el no-objectiu R3) és una propietat estructural de la gramàtica, no una blocklist a mantenir.
El join cross-modal, executat
Section titled “El join cross-modal, executat”X JOIN RETRIEVE(...) ON X.k = R.k no és un join relacional de dues taules
físiques. S’executa així:
- RETRIEVE (governat) → passatges, cadascun portant la seva clau desnormalitzada.
- Porta en clar → els valors de clau, o refusa (
403 E0515). - Prefiltre estructurat:
… WHERE k IN (<keys>)→to_trino→ SQL governat (la llistaINes construeix amb la conversió de literals de sqlglot — segura contra injecció). - Hash join in-cell sobre la clau segellada, projectant les columnes de cada pota.
Operadors de projecció
Section titled “Operadors de projecció”A la forma RETRIEVE, <op>(col) al SELECT és un operador de projecció
(RFC 0004). Són mapes unaris — mai un join.
| Classe | Operadors | Corre sobre | Si falta |
|---|---|---|---|
| Encoder (determinista) | SIMILARITY, CLASSIFY, TAG, RANK, DEDUP, OUTLIER, CLUSTER |
Embeddings ja presents al chunk | — |
| Decoder (inferència) requereix LLM | EXTRACT, SUMMARIZE, SCORE, GENERATE, COMPLETE |
Un backend LLM | 503 E0521 |
Bodies de SQL cru i MetricFlow
Section titled “Bodies de SQL cru i MetricFlow”{ "sql": "<SELECT>" } és un SELECT de només lectura validat contra l’allowlist
del tenant amb el punt d’aplicació de polítiques aplicat (row filters + projection
des de l’snapshot compost). { "metrics": …, "group_by": … } segueix la semàntica
de MetricFlow. Tots dos comparteixen la mateixa junta governada que osql.
Codis d’estat
Section titled “Codis d’estat”| Codi | Significat |
|---|---|
200 |
Èxit |
400 |
Malformat / fora de gramàtica (E0511), objecte no declarat (E0512), el body barreja formes (E0513), JOIN sense clau segellada (E0514), sql buit (E0246) |
403 |
Deny de la PDP (E2101/E2102), clau cross-modal no en clar (E0515), objecte fora de l’allowlist (E0512) |
422 |
Vàlid però no resoluble — p. ex. MetricFlow encara no implementat (E1001) |
503 |
Falta l’snapshot de la PDP (E2001, fail-closed), op decoder sense backend LLM (E0521) |
502 |
Fallada d’execució de Trino (E0510) |
Vegeu Errors i codis d’estat per a l’envelope complet.