Repository navigation
LibreDB Studio 1.0.0 is a major release.
Its headline is governance: Studio can now run under a control plane that decides who may open which database with which credential, and that keeps a record of what each person ran (#1785).
LibreDB Platform, our paid control plane for teams, is published as source-available software alongside it, while Studio itself stays MIT-licensed and free.
The release also adds twelve connection types, taking Studio to forty-one external engines, and agent mode now executes statements on MySQL and MariaDB, MongoDB and Kubernetes.
It carries one security fix: a disconnect request now closes only the caller's own connections (GHSA-78jw-7pvp-64h3), so operators of a server shared by several accounts should upgrade.
Studio runs under a control plane
A control plane is a separate service, and the two never call each other.
The control plane publishes a governance source, a set of PostgreSQL views and tables in one schema, and Studio reads it with a role of its own and writes its heartbeat and its query events back into it.
docs/GOVERNANCE.md is that contract, version 1, for anyone who builds or operates a control plane, and every release tag carries the three files a control plane pins: that document, the manifest tests/fixtures/governance/contract-v1.json and the lsb1 test vectors tests/fixtures/governance/lsb1-vectors.json.
Governance is off unless an operator sets GOVERNANCE_SOURCE=postgres, and a Studio without that variable behaves as 0.18.3 did, apart from the disconnect fix below and the changes listed under Upgrading.
With it on:
- The identity provider is the only way in: Studio accepts only an OIDC session from
OIDC_ISSUERfor an account with the admin or the user role, and password, passkey and launch sign-in are off.
A session the control plane revokes is refused, typically within a second. - The governance source is the only catalog of connections: a person sees a connection only while they hold an effective grant on it, and an admin sees only the connections granted to them.
Custom connections, the embedded samples, seed files and discovery are off. - A credential reaches Studio only as an
lsb1envelope, sealed with HPKE (RFC 9180) to Studio's public key, so the control plane can seal a credential and never open it.
Studio opens it with the private keys of a keyring file (GOVERNANCE_PRIVATE_KEYS_FILE), and areadgrant opens the read credential and awritegrant the write credential. - Each person runs on database providers of their own, with a pool of at most 3 sessions by default, so one person's session state, interactive transaction, cancel or disconnect never reaches another person's.
- A grant that is taken away or changed closes that person's providers right after the reload, rolling back an open transaction first.
- Studio records a query event for each statement it runs from the editor, a multi-statement run, an interactive transaction, an object edit, a maintenance action, the data profiler and a key scan.
The control plane decides whether the statement text is recorded: not at all (the default), redacted of its literals, or in full, in which case the editor says so. - Changes reach Studio through PostgreSQL notifications, typically within a second, with a reload every 30 seconds otherwise.
When the governance source stays unreachable for longer than the maximum staleness, 120 seconds by default, data routes answer 503 instead of serving old grants, andGET /api/readyanswers 503 until the first load succeeds, so an instance takes no traffic before it can serve grants. - Studio refuses to start when its configuration would undercut governance, such as a password account, custom connections, MCP or the agent switched on, and names every variable to fix.
- MCP and the agent stay off under governance in this release.
The engines a governed install admits are GOVERNANCE_ALLOWED_ENGINES, by default PostgreSQL, MySQL, SQL Server, Oracle, MongoDB and Redis.
The open items of this first contract version are filed in docs/BACKLOG.md as the GOV entries, among them that a changed query timeout closes an open transaction's provider without rolling the transaction back first (GOV24).
LibreDB Platform is source-available
LibreDB Platform is the control plane we build for teams that want one place to manage database access: the connections, who may open each one and with which credential, and the audit log of the queries Studio records.
Its source is published under the Elastic License 2.0, with Sekoya Tech as the licensor, and Studio 1.0.0, the first release that can run under it through the governance contract above, is the Studio release it pairs with.
Studio is unchanged by it: open source under the MIT license, free, and complete on its own, with or without Platform.
Platform is the paid product: a self-hosted install runs on a free tier of 1 admin seat and 3 user seats, and a larger team needs a license key, for which write to info@libredb.org.
How Platform and Studio work together walks through the design with diagrams, and the Docker install guide describes an install.
Security fix
POST /api/db/disconnect used to close every cached database provider of the connection id a request named, with that connection's SSH tunnels, for every user of the server, and it checked only that the caller was signed in.
So any signed-in account could close a connection other users had open, which could fail their running statements and roll back an interactive transaction they had open, by naming a managed connection's seed: id, which every user who may open that connection sees, or the id of another user's own connection.
From 1.0.0 a disconnect closes only the caller's own providers.
Without governance a seed: id closes nothing, because one provider serves every user of that connection and the idle sweep reclaims it, and a connection of the caller's own closes only the providers its own server and credentials name; under governance only the caller's per-user providers close (#1785, GHSA-78jw-7pvp-64h3).
Every release that carries the route is affected, from v0.8.19 through 0.18.3, and on npm from 0.9.7, the first version published there.
Twelve new connection types
A BigQuery connection runs GoogleSQL over the REST API v2 with no Google SDK, signed in with a pasted service-account key or access token, or for a seeded connection the server's own identity behind BIGQUERY_SERVER_CREDENTIALS=true; it is not read-only.
The tree lists datasets with their tables and views, Explain is a free dry run, and the editor shows the bytes a statement will process before it runs.
It was checked by hand on a live project, and the integration test replays answers recorded from a live EU project (#1672, #1705).
An MQTT connection speaks MQTT 5.0 with Studio's own client: it subscribes once to a discovery filter, collects what the broker delivers until a budget ends the read, and disconnects.
It is read-only by construction, since the encoder has no PUBLISH and CONNECT carries no Will, and shared subscriptions are refused, because they would take messages meant for a device; topics become the tree in the Keys panel, and since MQTT cannot list topics, the panel says what a read could not establish.
Mosquitto, EMQX, HiveMQ CE and NanoMQ were measured (#1676, closes #1635).
A Firestore connection reads one Native mode database over the REST API v1 with no SDK, and with FIRESTORE_EMULATOR_HOST set it talks to the emulator and sends no credential.
The tree lists collections, the Keys panel walks documents and subcollections, and the editor takes one Admin SDK query chain, which Studio parses into REST requests and never runs as JavaScript; only read requests can leave Studio.
It is tested against emulator 1.22.0 captures and was checked by hand on a real project (#1695, #1702).
A RabbitMQ connection browses virtual hosts, streams, queues and exchanges through the management API, and reads a stream's messages through Studio's own AMQP 0-9-1 client, from a JSON request such as {"vhost": "/", "stream": "orders", "from": "last", "limit": 50}.
It never takes a message from a queue, publishes, declares or deletes anything, and with the new AMQP port field empty it browses only (#1689).
It needs RabbitMQ 4.2 or later and is verified on 4.3.6 and 4.2.9 (#1703, closes #1656).
A Snowflake connection speaks the SQL API v2 with Studio's own client and no driver, signs in with a key pair or a programmatic access token, and shows databases and schemas, cancellable statements, results under a 16 MiB budget, and an Explain that never starts a warehouse.
It is not read-only, and the confirmation dialog asks before the billed and account-level forms the provider doc lists.
It was captured on a Snowflake Enterprise trial, and an end-to-end sweep on a trial fixed 46 findings, among them out-of-range timestamps, the export of DECFLOAT, VECTOR and geography types, and a session time zone that now follows the user's own setting instead of UTC (#1714, #1727, #1728, #1729, #1730, #1762).
An OPC UA connection is one opc.tcp endpoint URL, read with a client that names eight read services and no Write, Call or subscription.
The Keys panel browses the address space one level at a time, a node opens with its value, status and attributes, and a JSON request reads current values or raw history; a server certificate can be pinned by its SHA-256 fingerprint.
It was measured against Microsoft OPC PLC 2.15.10, open62541, asyncua and Eclipse Milo (#1719, closes #1677).
An Apache Spark connection reaches a Spark Connect server, Spark 4.1 or later, over gRPC with Arrow results, each request on a Spark session of its own and every result bounded by rows and bytes.
Studio treats every Spark statement as able to write, so a read-only connection, agent mode and MCP run_read_query refuse it, plan mode drafts Spark SQL, and the confirmation dialog asks before replacing, overwriting, deleting and code-loading forms.
It was checked live on Spark 4.2.0 and 4.1.3 (#1759, closes #1736).
An MTConnect connection reads one agent over HTTP: the device model becomes the tree of data items, conditions and assets, and the editor takes one request line such as GET /current, which Studio checks before a socket opens.
Every route is a GET, and it is verified against the mtconnect/agent 2.8 image fed by an SHDR adapter (#1781, closes #1722).
A Modbus connection reads one Modbus TCP device with Studio's own client, which sends the four read function codes and device identification and nothing else.
Modbus has no discovery, so the coils and registers list points only where the connection's register map names them, and the editor reads by name, by address or for identification; it is verified against a pinned oitc/modbus-server fixture (#1792).
A Sparkplug B connection subscribes to an MQTT broker for the window a read asks for, decodes the payloads with Studio's own decoder and resolves metric aliases against the birth certificates; it never publishes.
The tree shows groups and edge nodes with each metric's datatype, last value, quality and defining certificate, and it was measured against Mosquitto 2.1.2 and HiveMQ CE with their Sparkplug Aware extensions (#1798).
A NETCONF connection opens the NETCONF subsystem over SSH and sends <get-config>, <get>, <get-data>, <get-schema> and <close-session>, nothing else.
The tree shows datastores and the modules the device implements, the Keys panel reads below a node one level at a time, and the host key can be pinned; it is measured against Netopeer2 2.8.7 (#1802).
An SNMP connection speaks SNMPv2c over UDP with Studio's own BER code, using Get, GetNext and GetBulk, and has no write path.
The editor takes get, next, walk and table, a read returns each value with the type the agent gave it, and the SSL panel and SSH tunnel are not offered over UDP; it is verified against a Net-SNMP 5.9.4 agent (#1803).
Agent mode executes on MySQL and MariaDB, MongoDB and Kubernetes
Agent mode executed statements on PostgreSQL, SQLite, DuckDB and SQL Server in 0.18.3; it now also executes on MySQL and MariaDB, MongoDB and Kubernetes, and plan mode and the operations workflow run everywhere as before.
On MySQL and MariaDB, Studio first verifies that the connection's user holds nothing past SELECT and SHOW VIEW, because DDL, GRANT and SET GLOBAL commit implicitly and so end a read-only transaction, and START TRANSACTION READ ONLY sits behind that check.
Each call runs one statement, the server's sql_select_limit bounds the rows, a timer Studio owns ends an overrun with KILL QUERY, and session settings are reset after the call; it was measured on MySQL 26.7.0 and MariaDB 13.0.2 (#1629, closes #1612).
On MongoDB the boundary is the user: the server must report that the user holds only read privileges on the bound database and must refuse a delete that matches nothing, so an admin connection, a server without authorization and the wire-compatible servers are refused before any model turn.
Studio's command fence refuses writes, write stages and server-side JavaScript, every command carries maxTimeMS with a session kill behind it, and auto-execute is not offered; Setting up the agent's user shows the user to create (#1790, closes #1614).
On Kubernetes the boundary is Studio's request allowlist, checked on the final method and path of every request, together with the RBAC of the identity the agent runs as, which can be an agent-only token.
Query optimization becomes resource efficiency and assessment becomes cluster health, auto-execute is off, and env values, Secret and ConfigMap data and Secret names are redacted before the model sees them, with what still passes stated in section 9 of the provider doc (#1764).
Also in this release
Studio
- A PostgreSQL connection saved without a database lists every database the role can connect to, and a sidebar picker points the editor, the ERD, the AI, monitoring and the agent at the chosen one (#1649, closes #1530).
- SQL completion reads the clause and the scope: a
SELECTlist offers the columns, aliases and CTEs of the statement instead of tables, andFROMandJOINoffer only names (#1700). - Stop and a closed tab cancel the statement running on the database, and the idle sweep no longer disconnects a provider that is still running one (#1690, #1692, #1762).
- The confirmation dialog asks before
MERGEon every engine and before a PostgreSQLDOblock (#1772). - The export menu says a cut result writes the rows shown, not all rows (#1693).
- Secret and key fields turn off spell checking, so their text cannot reach a browser spelling service (#1707).
- Credentials are cleared when the engine changes in the connection dialog, and a Test Connection answer is scrolled into view (#1762, #1719).
- New optional variables, each keeping today's behaviour while unset:
AUTH_SESSION_TTL_SECONDS,STORAGE_POSTGRES_SCHEMA,OIDC_PROMPT,OIDC_AUTO_REDIRECT,OIDC_LOGOUT_HINTandOIDC_USER_ROLES(#1785). DEV_ALLOWED_ORIGINSlets a LAN host load the dev server (#1670).
Engines
- SQLite: on-disk statements run in a child process Studio can kill, so Cancel stops a long statement instead of blocking the server (#1623), and a statement that changes no row reports 0 on
node:sqlite(#1779). - SQLite and DuckDB: the database size counts the WAL (#1673, closes #1449).
- SQL Server:
DATETIMEandSMALLDATETIMEread as the engine's own text and export so they replay under every DATEFORMAT (#1639, closes #1452), and table stats no longer multiply row counts (#1682, closes #1406). - CockroachDB: table stats list the tables (#1548, closes #1540).
- Oracle: a BC date exports with its sign (#1674, closes #1498).
- Elasticsearch and OpenSearch: generated queries leave out fields the SQL engine cannot project (#1671, closes #1459).
- Kafka: a classic group with a member the client cannot decode is refused instead of shown partial (#1788, closes #1520).
- ClickHouse:
infandnanfloats are shown and exported instead of NULL (#1762). - Databend: the paste notice names only BendSQL's own parameters (#1706).
- SSH tunnels no longer add about 40 ms to each small query under Node (#1717).
The agent and AI
- Fence markers in the model's own messages are defanged before they enter the transcript (#1740).
- A run holding no data read no longer loops between
compose_reportandpresent_answer(#1681). - A run whose execution profile is refused ends before any model turn (#1790), and the grounding walk skips a parent it cannot list instead of losing the capture (#1759).
Distribution
- The image runs Node 26.11.1 (#1696), and the dependencies move to Next.js 16.4.0,
mssql12.7.4 and framer-motion 14 (#1709, #1699). - Pethost joins the one-click deploy options (#1780),
fly.tomland the Railway docs move to 0.18.3 (#1797), and the AWS AMI and DigitalOcean snapshot builds work again (#1810).
Documentation
- The README lists ScyllaDB, Valkey, the ClickHouse SQL client guide and Apache Doris, closes with a line for everyone who works with data, and has a new hero demo (#1745, #1746, #1769, #1811, #1770, #1806).
- The ClickHouse doc covers private CAs (#1708), and the Redis, DOCKERHUB, SECURITY, CONTRIBUTING, Spanish README and Rancher pages and the README's BrowserStack link are corrected (#1775, #1765, #1757, #1777, #1662, #1738, #1741, #1739).
- Stale counts and lists are dropped from docs and comments (#1675, #1687, #1716, #1718, #1742, #1758, #1760, #1763, #1767, #1776, #1782).
Upgrading from 0.18.3
- A refusal for a missing privilege answers 403
PERMISSION_DENIEDinstead of 401, and a statement timeout 504 instead of 408; a client of the HTTP API that branches on these must follow (#1785). POST /api/db/disconnectanswers 400 for a bare id outsideseed:(#1785).- A PostgreSQL connection with no database now opens server-wide, with up to five small pools, which matters behind PgBouncer (#1649).
- On-disk SQLite runs in a child process;
LIBREDB_SQLITE_WORKER=0restores the synchronous driver (#1623). - For hosts of
@libredb/studio:DatabaseTypeandqueryDialectgain the new engines, so an exhaustive switch over either must add them, andDatabaseConnection,ObjectSourcePartandDatabaseProvidergain optional members (#1703, #1689, #1684, #1683, #1692).
Helm chart: 0.1.100
Tracks app release 1.0.0; no template, value or default moves in this version.
Chart 0.1.99 added the governance values (governance.*, the Secret keys governance-postgres-url and governance-private-keys, and stickySessions.enabled) and typed values for OIDC_USER_ROLES, OIDC_PROMPT, OIDC_AUTO_REDIRECT, OIDC_LOGOUT_HINT, AUTH_SESSION_TTL_SECONDS and STORAGE_POSTGRES_SCHEMA, all off or empty by default.
Its default image, 0.18.3, does not read them, and with governance.enabled the readiness probe asks /api/ready, which 0.18.3 does not serve, so governance needs chart 0.1.100 or later, or an image of 1.0.0 or later.
Charts 0.1.86 to 0.1.98 named each new engine in the description and keywords as it landed, from MQTT in 0.1.86 to Sparkplug B in 0.1.98; there is no 0.1.96.
artifacthub.io/containsSecurityUpdates is true for 0.1.100, for the disconnect fix.
helm repo add libredb https://libredb.org/libredb-studio/
helm upgrade --install libredb-studio libredb/libredb-studio --version 0.1.100
Contributors
- @yusuf-gundogdu built the MQTT, OPC UA, MTConnect, Modbus, Sparkplug B, NETCONF and SNMP providers (#1676, #1719, #1781, #1792, #1798, #1802, #1803), fixed an agent loop (#1681), the image builds and deploy pins (#1810, #1797), corrected the Spark and MTConnect type comments (#1794), and steadied tests (#1799, #1800, #1801, #1804).
- @Dariusch built the BigQuery provider (#1672, #1705), scope-aware completion (#1700) and
DEV_ALLOWED_ORIGINS(#1670). - @KodYazicam made agent mode execute on MySQL and MariaDB (#1629) and MongoDB (#1790).
- @kaya-abdullah swept Snowflake end to end (#1762), fixed SQLite row counts (#1779), and did the ClickHouse doc and README work (#1708, #1745, #1746, #1769, #1770, #1806, #1811).
- @kkj-buildstr made one PostgreSQL connection browse every database (#1649), and @stroexd gave CockroachDB table stats (#1548).
- @koraysrn made SQLite statements killable (#1623) and defanged agent fence markers (#1740).
- @Aditya-XR fixed SQL Server datetimes (#1639), @Totopo27 its row counts (#1682), and @evgessshkin the WAL size (#1673).
- @siddxwar04 fixed Oracle BC dates (#1674), @Maaz2212 search query generation (#1671), and @T-Zaid the Kafka group refusal (#1788).
- @Vardhan2006 added the live PostgreSQL read-only check (#1648), @sloemo01 steadied the RabbitMQ tests (#1737), and @sadfun added Pethost (#1780).
- Documentation: @HannaSalinas (#1662), @CodeByPeace (#1675), @niukanen1 (#1687, #1775), @samusagbt (#1716), @siddxwar04 (#1738, #1777), @notlakshitha (#1739), @Vardhan2006 (#1741, #1742), @Jah-yee (#1757), @daemon-tech (#1758), @0x0000x (#1760), @SwatiManjari (#1763), @sadhana-s-codez (#1765), @KrishanKumarAwasthi (#1767), @Fineturkey (#1776) and @yash8233 (#1782).
- Reported by @kaya-abdullah (#1406, #1449, #1452, #1459) and @Aditya-XR (#1498).
Governance, the disconnect fix, the Firestore, RabbitMQ, Snowflake and Apache Spark providers, agent execution on Kubernetes, the cancel and idle-sweep fixes of #1690 and #1692, and the MERGE and DO confirmation are by @cevheri.
Full changelog: 0.18.3...1.0.0