Connections
Connections
Tenant-supplied database endpoints. Configure at
/admin/connections.
Supported kinds
The kind column is a stable identifier — never renamed. New
driver kind → new id added to the registry.
| Kind | Driver |
|---|---|
postgres | PostgreSQL 12+ |
mysql | MySQL 8+ / MariaDB |
bigquery | Google BigQuery (Standard SQL) |
snowflake | Snowflake |
databricks | Databricks SQL warehouse |
duckdb | DuckDB (local file or HTTP) |
generic_sql | Other SQLAlchemy-compatible engines |
Postgres + MySQL + BigQuery + Snowflake have full first-class support (planner schema embeddings, EXPLAIN preflight where applicable, scope predicate injection).
Per-connection fields
| Field | Notes |
|---|---|
kind | Stable id from the table above |
host / port / database | Or BigQuery project / dataset |
creds_encrypted | secret_box (Fernet) — username + password / service account JSON / OAuth token |
config | JSONB — connection options (SSL, role, warehouse, etc.) |
scope_predicates | RLS-like row filters the planner injects |
schema_snapshot_at | When schema was last introspected |
Creating a connection
/admin/connections→ New connection.- Pick the kind, fill connection details, save.
- Click Test — the driver does a round-trip ping.
- Click Introspect schema — driver enumerates tables + columns + types; planner indexes them via embeddings.
The introspection step is what makes NL→SQL work — the planner retrieves the most-relevant tables for a question by embedding the question and looking up similar column descriptions.
Scope predicates
Scope predicates are SQL fragments the planner inlines into the generated SQL. They look like:
- table: orders predicate: "tenant_id = '00000000-0000-0000-0000-000000000000'"- table: customers predicate: "tenant_id = '00000000-0000-0000-0000-000000000000'"Use them to:
- Enforce row-level isolation when the source DB isn’t natively RLS-aware.
- Restrict a connection to “production data only” or “redacted PII set only” via WHERE clauses the user can’t escape.
The validator AND-injects every applicable predicate before the query runs. Predicates can’t be bypassed — that’s the contract.
Grants
Each connection can be granted to specific users or roles via Connection grants. A user who can’t see a connection in the workbench picker isn’t on the grant list.
Schema refresh
Schema drift is real. Re-introspect from the connection detail page when you’ve added tables or columns. The embedding index updates in place.