feat(credentials): saved PostgreSQL, MySQL, and SQL Server connections
Merged
WA
3d ago+2008+2008+0123456789012345678901234567890123456789-218-218-012345678901234567890123456789
Summary
- Adds saved database connections for PostgreSQL, MySQL and SQL Server under three new service-account provider ids (
postgresql-service-account,mysql-service-account,mssql-service-account). A connection stores host, port, database, login and password, plus the SSL mode (or SQL Server's encrypt and trust-certificate settings). It is modeled on the existing Oracle Database credential. - Saving runs
SELECT 1through each family's own guarded connection path, sovalidateDatabaseHost, IP pinning and TLS match a real run. The connection is encrypted only after the database answers. Driver errors are never shown, and there is no connection cache. - One list per provider (
databaseConnectionFieldIds: the login fields plus the descriptor's TLS fields) says what a saved connection holds. The stored schema picks exactly those fields from the operation's own connection schema, with tighter bounds, and is strict. The tools'credentialSuppliedParamscome from the same list. The TLS values and defaults therefore have one source, and the modal's options are keyed by the same value types. A field added to an operation later (like SQL Server's per-block connection timeout) never enters the stored blob and is never pinned by a saved connection. - The tools read the connection server-side inside the operation (
withSavedDatabaseConnection), bound to the run's workspace or organization. It replaces every connection field in the call, so a caller or model cannot point a shared credential at another host. The three families are wrapped when they are registered (registerSavedDatabaseFamily, likeregisterAwsFamily). A registry test fails if any tool that names a saved database connection runs outside a wrapped family. - New
postgresql_v2,mysql_v2andmssql_v2blocks offer only the connection picker. The legacy blocks keep their inline inputs and run unchanged; they are hidden from the toolbar and marked as replaced. - The Oracle lookup now goes through the shared owner-scoped secret read. Its behavior is unchanged.
- Out of scope, with design notes: MongoDB, ClickHouse, Neo4j and IAM database auth (RDS, Cloud SQL, Entra).
Compatibility
- Existing provider ids, stored secrets and legacy blocks are untouched. The new stored blobs keep their v1 shape, and the stored schemas accept the same fields and defaults as before.
- The 18
postgresql_*,mysql_*andmssql_*tools now declare an optional saved credential. Besides gaining an optionalcredentialId, their Copilot and v2 schemas no longer list the connection fields (host, port, database, username, password, ssl or encrypt/trustServerCertificate) asrequired. Those fields are now checked at runtime byenforceCopilotCredentialSelection, which refuses a call that has neither acredentialIdnor the inline fields. This is the repo's documented hybrid-tool pattern.
Product update (if relevant)
Workspace and organization admins can save a database connection once in Integrations and share it across workflows and agents, so the password no longer sits in block fields. Setup is documented on the PostgreSQL, MySQL and SQL Server integration pages, including what each TLS mode actually guarantees.
Type of Change
- Bug fix
- New feature
- Breaking change
- Documentation
- Other: ___________
Testing
- Unit tests in
lib/credentials/database-connections/server.test.ts:- For each engine, a saved connection round-trips: save proves the exact login with
SELECT 1, and a later run gets that login plus the stored TLS defaults. - For each engine, a run on a saved connection replaces exactly the params its tools declare as credential-supplied. A block-set SQL Server connection timeout is kept. Revert proof: building the SQL Server stored schema from the whole operation schema, or dropping a TLS field from the declared params, turns it red.
- Invalid input is refused without connecting, and driver errors are kept out of messages.
- A call without a credential passes through, and a credential for another service is ignored.
- These return 403 without running: another engine's row, an organization row, a foreign blob type, an unknown stored field.
- Abort is honored.
- For each engine, a saved connection round-trips: save proves the exact login with
- Saved-credential version cases were added for all three blocks.
lib/internal/tool-operations/registry.server.test.ts: every tool whose provider is a saved-database service is registered in a wrapped family for that service. Revert proof: registering MySQL without the wrapper turns it red.- Integration test
lib/credentials/__integration__/database-connection.integration.tsruns against real Postgres through the registeredpostgresql_queryoperation. It checks that:- a valid save is accepted, and a save of a missing database is refused;
- a run uses the saved connection despite bogus inline fields;
- runs are refused in another workspace and after revocation.
- Revert proof: weakening the field override or the service guard turns the matching tests red.
- Checks run: biome, a type-check of the changed files, block-successors, tool-metadata, deployment-config, docs, boundaries, client-boundary, egress-boundary, tool-registry-boundary, unused-exports, explicit-any, source-conventions, file-names, utils, comment-hygiene, test-patterns, and
check-block-registryagainst staging (saved-credential contract). - Reviewers should look at
withSavedDatabaseConnection(field override and owner binding) and the TLS hints, which describe Sim's driver mapping:- MySQL Required checks the certificate chain but not the host name (like
VERIFY_CA), and Preferred never falls back to plaintext. - SQL Server Encrypt requests TLS, but tedious continues unencrypted when the server answers
NOT_SUP. - PostgreSQL Preferred can be downgraded by an on-path attacker.
- MySQL Required checks the certificate chain but not the host name (like
Checklist
- Code follows project style guidelines
- Self-reviewed my changes
- Tests added/updated and passing
- No new warnings introduced
- I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)