Die Query-Oberfläche (OSL-SQL)
POST /osl/query ist der einzige Konsum-Endpoint. Strukturierte Analytik,
Metriken, gesteuertes Vektor-Retrieval und Graph-Traversierung werden alle hier
ausgedrückt — du lernst nicht fünf Oberflächen, um eine Domain zu lesen.
POST /osl/queryAuthorization: Bearer <jwt> # attested delegation chain, see AuthenticationContent-Type: application/jsonDer Body ist eine von drei wechselseitig ausschließenden Formen (sie zu mischen
ist 400 E0513); alle drei laufen durch dieselbe gesteuerte Naht und teilen
sich eine request_id:
| Body | Was es ist |
|---|---|
{ "osql": "…" } |
OSL-SQL — der semantische SQL-Dialekt (die kanonische Oberfläche) |
{ "sql": "…" } |
Ein rohes read-only SELECT über die Allowlist des Tenants (der SQL-Slice) |
{ "metrics": […], "group_by": […], … } |
MetricFlow-artige Metrik-Query |
OSL-SQL
Abschnitt betitelt „OSL-SQL“osql ist ein semantischer SQL-Dialekt. Er benennt nur semantische
Objekte — osl.entities.<model> und deklarierte Spalten oder die Table-Functions
RETRIEVE(...) / TRAVERSE(...). Er benennt niemals eine physische Tabelle oder
eine rohe Spalte.
Das Lowering ist die Sicherheitsgrenze
Abschnitt betitelt „Das Lowering ist die Sicherheitsgrenze“Die Engine parst osql (via sqlglot, trino-Dialekt) und senkt es zu einem
geschlossenen Operator-IR ab — die deterministische Leiter, über die das
Governance-Modell durchsetzt. Das Lowering ist
total und default-deny: Jedes Konstrukt, das nicht zu einem bekannten
IR-Knoten absenkt, wird abgelehnt.
Die fünf Formen
Abschnitt betitelt „Die fünf Formen“lower() klassifiziert jede Query in genau eine Form und validiert ihre Grammatik:
SELECT segment, COUNT(*) AS nFROM osl.entities.CustomerWHERE country IN ('ES','FR','DE')GROUP BY segmentORDER BY n DESCLIMIT 100Senkt zu to_trino() ab → die gesteuerte SQL-Naht. Joins zwischen strukturierten
Entities sind nur als Equijoin auf versiegeltem Schlüssel erlaubt (siehe unten).
SELECT SUMMARIZE(text) AS summary, scoreFROM RETRIEVE(facet => 'meeting_transcripts', query => 'european equity exposure', top_k => 5)Senkt zum gesteuerten Lance-Store + Retrieval ab. Eine bloße Spalte wird
durchgereicht; ein <op>(col) im SELECT ist ein
Projektionsoperator.
SELECT concepto, amount_eurFROM TRAVERSE(anchor => 'customer', target => 'orders', keys => ('c-anna', 'c-bruno'))Senkt zur gesteuerten L2-Traversierung von den Anker-Schlüsseln ab (Hop für Hop, beschränkte Kardinalität + Dedup).
SELECT name, segment, recent_meeting_topicsFROM osl.entities.CustomerWHERE customer_id IN ('9c1e…f04a', 'e4f8…2a91')Die Entity-first-„Record“-Form: strukturierte Spalten + Lance-Evidenz + abgeleitete Attribute für die gegebenen Schlüssel, in einer Auflösung.
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„Die Relation ist ein Filter“: RETRIEVE läuft zuerst, seine Schlüssel vorfiltern das strukturelle Bein, dann ein In-Cell-Hash-Join auf dem versiegelten Schlüssel. Siehe unten.
R3 ist nicht ausdrückbar, nicht blockiert
Abschnitt betitelt „R3 ist nicht ausdrückbar, nicht blockiert“Der einzige cross-relationale Knoten ist ein Equijoin, dessen ON eine skalare
Gleichheit auf einem versiegelten Entity-Schlüssel ist (die entity_key_columns
des Modells oder das scalar_indexed-Feld einer Facette) auf beiden Beinen.
Jedes andere JOIN … ON → 400 E0514.
Es gibt keine Syntax, die einem Ähnlichkeits- oder LLM-Operator ein zweites relationales Argument übergibt — ein relation×relation-semantischer Join zur Query-Zeit (das Nicht-Ziel R3) ist eine strukturelle Eigenschaft der Grammatik, keine zu pflegende Blocklist.
Der cross-modale Join, ausgeführt
Abschnitt betitelt „Der cross-modale Join, ausgeführt“X JOIN RETRIEVE(...) ON X.k = R.k ist kein relationaler Join zweier
physischer Tabellen. Er läuft als:
- RETRIEVE (gesteuert) → Passagen, jede trägt ihren denormalisierten Schlüssel.
- Klartext-Gate → die Schlüsselwerte, oder Ablehnung (
403 E0515). - Strukturierter Prefilter:
… WHERE k IN (<keys>)→to_trino→ gesteuertes SQL (dieIN-Liste wird mit sqlglot-Literal-Konvertierung gebaut — injection-sicher). - In-Cell-Hash-Join auf dem versiegelten Schlüssel, projiziert die Spalten jedes Beins.
Projektionsoperatoren
Abschnitt betitelt „Projektionsoperatoren“In der RETRIEVE-Form ist <op>(col) im SELECT ein Projektionsoperator
(RFC 0004). Sie sind unäre Abbildungen — niemals ein Join.
| Klasse | Operatoren | Läuft | Falls fehlend |
|---|---|---|---|
| Encoder (deterministisch) | SIMILARITY, CLASSIFY, TAG, RANK, DEDUP, OUTLIER, CLUSTER |
Auf Embeddings, die bereits im Chunk sind | — |
| Decoder (Inferenz) braucht LLM | EXTRACT, SUMMARIZE, SCORE, GENERATE, COMPLETE |
Ein LLM-Backend | 503 E0521 |
Rohe SQL- & MetricFlow-Bodies
Abschnitt betitelt „Rohe SQL- & MetricFlow-Bodies“{ "sql": "<SELECT>" } ist ein read-only SELECT, validiert gegen die Allowlist
des Tenants, mit angewandtem Policy Enforcement Point (Zeilenfilter + Projektion
aus dem komponierten Snapshot). { "metrics": …, "group_by": … } folgt der
MetricFlow-Semantik. Beide teilen sich dieselbe gesteuerte Naht wie osql.
Statuscodes
Abschnitt betitelt „Statuscodes“| Code | Bedeutung |
|---|---|
200 |
Erfolg |
400 |
Fehlerhaft / außerhalb der Grammatik (E0511), nicht-deklariertes Objekt (E0512), Body mischt Formen (E0513), JOIN nicht auf versiegeltem Schlüssel (E0514), leeres sql (E0246) |
403 |
PDP-Deny (E2101/E2102), cross-modaler Schlüssel nicht Klartext (E0515), Objekt außerhalb der Allowlist (E0512) |
422 |
Gültig, aber nicht auflösbar — z. B. MetricFlow noch nicht implementiert (E1001) |
503 |
PDP-Snapshot fehlt (E2001, fail-closed), Decoder-Op ohne LLM-Backend (E0521) |
502 |
Trino-Ausführungsfehler (E0510) |
Siehe Fehler & Statuscodes für das vollständige Envelope.