La surface de query (OSL-SQL)
POST /osl/query est l’unique endpoint de consommation. L’analytique
structurée, les métriques, le retrieval vectoriel gouverné et la traversée de
graphe s’y expriment tous — vous n’apprenez pas cinq surfaces pour lire un
domaine.
POST /osl/queryAuthorization: Bearer <jwt> # attested delegation chain, see AuthenticationContent-Type: application/jsonLe body est l’une de trois formes mutuellement exclusives (les mélanger donne
400 E0513) ; toutes trois passent par le même seam gouverné et partagent un
seul request_id :
| Body | Ce que c’est |
|---|---|
{ "osql": "…" } |
OSL-SQL — le dialecte de SQL sémantique (la surface canonique) |
{ "sql": "…" } |
Un SELECT brut en lecture seule sur l’allowlist du tenant (le slice SQL) |
{ "metrics": […], "group_by": […], … } |
Query de métriques façon MetricFlow |
osql est un dialecte de SQL sémantique. Il ne nomme que des objets
sémantiques — osl.entities.<model> et des colonnes déclarées, ou les fonctions
de table RETRIEVE(...) / TRAVERSE(...). Il ne nomme jamais une table physique
ni une colonne brute.
L’abaissement est la frontière de sécurité
Section intitulée « L’abaissement est la frontière de sécurité »Le moteur parse osql (via sqlglot, dialecte trino) et l’abaisse en un IR
d’opérateurs fermé — l’échelle déterministe sur laquelle le modèle de
gouvernance applique l’enforcement. L’abaissement est
total et default-deny : toute construction qui ne s’abaisse pas en un nœud IR
connu est refusée.
Les cinq formes
Section intitulée « Les cinq formes »lower() classe chaque query dans exactement une forme et valide sa grammaire :
SELECT segment, COUNT(*) AS nFROM osl.entities.CustomerWHERE country IN ('ES','FR','DE')GROUP BY segmentORDER BY n DESCLIMIT 100S’abaisse en to_trino() → le seam SQL gouverné. Les joins entre entités
structurées ne sont autorisés que comme equijoin sur clé scellée (voir plus
bas).
SELECT SUMMARIZE(text) AS summary, scoreFROM RETRIEVE(facet => 'meeting_transcripts', query => 'european equity exposure', top_k => 5)S’abaisse en le store Lance gouverné + retrieval. Une colonne nue passe telle
quelle ; un <op>(col) dans le SELECT est un opérateur de
projection.
SELECT concepto, amount_eurFROM TRAVERSE(anchor => 'customer', target => 'orders', keys => ('c-anna', 'c-bruno'))S’abaisse en la traversée L2 gouvernée à partir des clés d’ancre (saut par saut, cardinalité bornée + dedup).
SELECT name, segment, recent_meeting_topicsFROM osl.entities.CustomerWHERE customer_id IN ('9c1e…f04a', 'e4f8…2a91')La forme « record » orientée entité : colonnes structurées + preuves Lance + attributs dérivés pour les clés données, en une seule résolution.
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 relation est un filtre » : RETRIEVE s’exécute d’abord, ses clés préfiltrent la jambe structurelle, puis un hash join in-cell sur la clé scellée. Voir plus bas.
R3 est inexprimable, pas bloqué
Section intitulée « R3 est inexprimable, pas bloqué »Le seul nœud inter-relationnel est un equijoin dont le ON est une égalité
scalaire sur une clé d’entité scellée (les entity_key_columns du modèle, ou un
champ scalar_indexed d’une facette) sur les deux jambes. Tout autre
JOIN … ON → 400 E0514.
Il n’existe aucune syntaxe qui passe un second argument relationnel à un opérateur de similarité ou de LLM — un join sémantique relation×relation au query time (le non-objectif R3) est une propriété structurelle de la grammaire, pas une blocklist à maintenir.
Le join cross-modal, exécuté
Section intitulée « Le join cross-modal, exécuté »X JOIN RETRIEVE(...) ON X.k = R.k n’est pas un join relationnel de deux
tables physiques. Il s’exécute ainsi :
- RETRIEVE (gouverné) → des passages, chacun portant sa clé dénormalisée.
- Gate en clair → les valeurs de clé, ou refus (
403 E0515). - Préfiltre structurel :
… WHERE k IN (<keys>)→to_trino→ SQL gouverné (la listeINest construite avec la conversion de littéraux de sqlglot — sûre vis-à-vis des injections). - Hash join in-cell sur la clé scellée, projetant les colonnes de chaque jambe.
Opérateurs de projection
Section intitulée « Opérateurs de projection »Dans la forme RETRIEVE, <op>(col) dans le SELECT est un opérateur de projection
(RFC 0004). Ce sont des maps unaires — jamais un join.
| Classe | Opérateurs | S’exécute | Si absent |
|---|---|---|---|
| Encoder (déterministe) | SIMILARITY, CLASSIFY, TAG, RANK, DEDUP, OUTLIER, CLUSTER |
Sur les embeddings déjà présents dans le chunk | — |
| Decoder (inférence) requiert un LLM | EXTRACT, SUMMARIZE, SCORE, GENERATE, COMPLETE |
Un backend LLM | 503 E0521 |
Bodies SQL brut et MetricFlow
Section intitulée « Bodies SQL brut et MetricFlow »{ "sql": "<SELECT>" } est un SELECT en lecture seule validé contre l’allowlist
du tenant avec le point d’application des politiques appliqué (filtres de lignes +
projection depuis le snapshot composé). { "metrics": …, "group_by": … } suit la
sémantique MetricFlow. Les deux partagent le même seam gouverné qu’osql.
Codes de statut
Section intitulée « Codes de statut »| Code | Signification |
|---|---|
200 |
Succès |
400 |
Malformé / hors grammaire (E0511), objet non déclaré (E0512), le body mélange des formes (E0513), JOIN non sur clé scellée (E0514), sql vide (E0246) |
403 |
Deny du PDP (E2101/E2102), clé cross-modal non en clair (E0515), objet hors de l’allowlist (E0512) |
422 |
Valide mais non résoluble — p. ex. MetricFlow pas encore implémenté (E1001) |
503 |
Snapshot du PDP manquant (E2001, fail-closed), op decoder sans backend LLM (E0521) |
502 |
Échec d’exécution de Trino (E0510) |
Voir Erreurs et codes de statut pour l’envelope complet.