QQL Gateway
Connect RPC gRPC gRPC-Web
The QQL Gateway is a Connect RPC server (gRPC + gRPC-Web + HTTP/1.1 JSON) that sits in front of Qdrant. It accepts QQL queries over HTTP, enforces policy, executes them, and returns structured responses.
┌──────────┐ Connect RPC ┌───────────┐ gRPC ┌──────────┐│ Client │ ──────────────────────▶ │ Gateway │ ──────────────▶ │ Qdrant ││ (any) │ HTTP POST / JSON / gRPC │ (this) │ go-client │ │└──────────┘ └───────────┘ └──────────┘Any language can call it — curl, Python, TypeScript, Go, or an LLM agent.
When to Use the Gateway
Section titled “When to Use the Gateway”| Situation | Use |
|---|---|
| Multi-tenant app — isolate tenant data | Gateway with policy + AST injection |
| Auth-protected Qdrant access | Gateway with JWT validation |
| Multi-language clients (Python + TypeScript + Go) | Gateway as unified RPC surface |
| Audit trail of all queries | Gateway with audit logging |
| Rate-limit per user | Gateway with token bucket |
| Agents calling named operations | Gateway with query templates |
| Simple single-service Go app | Embed pkg/qql directly |
Without Gateway Flags
Section titled “Without Gateway Flags”A plain gateway with no auth or policy is a transparent QQL proxy:
qql-go serve --qdrant-url http://localhost:6334Any query passes through. Useful for development or trusted internal networks.
With Gateway Features
Section titled “With Gateway Features”The gateway becomes a policy enforcement point when configured:
| Feature | Flag |
|---|---|
| JWT auth | --jwks-url, --jwt-issuer, --jwt-audience |
| YAML policy | --policy-file |
| Hot-reload policy | --policy-reload |
| Audit logging | --audit, --audit-file |
| Rate limiting | --rate-limit, --rate-limit-capacity |
| Query templates | --templates |
Key Differentiator — AST Injection
Section titled “Key Differentiator — AST Injection”The gateway doesn't just proxy requests — it parses QQL into an AST and rewrites it before execution.
When a user sends:
QUERY 'company' FROM docs LIMIT 500The gateway rewrites it to:
QUERY 'company' FROM docs LIMIT 50 WHERE tenant_id = 'acme-corp'- Tenant filter comes from the JWT claim — never written by the user
- LIMIT is capped by policy
- For CTE-based queries, injection is recursive — every CTE stage gets the filter
Next Steps
Section titled “Next Steps”- Quickstart — start a basic gateway
- Authentication — configure JWT + JWKS
- Policy Engine — YAML rules and filter injection
- RPC Reference — all five RPCs