Skip to content

[Bug]: external plugin drivers cannot receive a full connection URI (mongodb+srv rejected, then decomposed) #494

Description

@Robbyfuu

Describe the bug

External plugin drivers cannot receive a full connection URI. Two independent gaps in src/utils/connectionStringParser.ts combine to make SRV-based drivers (MongoDB Atlas, and any future driver whose scheme carries semantics) unusable.

Gap 1 — the protocol is rejected

buildProtocolRegistry only registers two things per driver: normalizeProtocol(driver.id) and the protocol extracted from capabilities.connection_string_example. A plugin whose id is mongodb-atlas therefore only registers mongodb-atlas://. Pasting a real Atlas URI fails at connectionStringParser.ts:171:

Unsupported database driver: mongodb+srv. Supported: mongodb-atlas, mysql, postgres, postgresql, sqlite

PROTOCOL_ALIAS_GROUPS is a hardcoded list (postgres/postgresql, mysql/mariadb, sqlite/sqlite3), so a plugin cannot register an alias pair such as mongodb + mongodb+srv even by declaring an example — the example only registers one of the two.

Gap 2 — the URI is destroyed even when the protocol is accepted

Once parsing succeeds, parseConnectionString decomposes the URI into discrete fields (connectionStringParser.ts:200-228) and toConnectionParams forwards only those:

return {
  driver: parsed.driver,
  host: parsed.host,
  port: parsed.port,
  username: parsed.username,
  password: parsed.password,
  database: parsed.database,
};

The scheme and the entire query string are discarded. For mongodb+srv:// this is not recoverable:

  • mongodb+srv mandates a DNS SRV lookup to discover the replica-set members. A bare hostname with no port is not a valid substitute — the driver has no way to know it should resolve SRV records.
  • Atlas URIs carry retryWrites, w=majority, authSource, replicaSet and appName in the query string. All are dropped.
  • url.port is empty for SRV URIs, so port arrives as undefined and the plugin falls back to default_port (27017), which is wrong for a sharded Atlas cluster.

The observable result is that a connection can appear to be established while database enumeration returns nothing, because the reconstructed connection no longer points at the real cluster.

Grepping current main (39f5ab2) confirms there is no path that preserves the original string — there is no connection_uri / full_uri field anywhere in src-tauri/src or src/utils.

To Reproduce

  1. Install an external plugin driver that accepts a full URI. I used a MongoDB Atlas plugin whose manifest.json declares "id": "mongodb-atlas", "default_port": 27017 and no connection_string_example.
  2. Open New Connection and paste a standard Atlas connection string:
    mongodb+srv://user:pass@cluster0.xxxxx.mongodb.net/mydb?retryWrites=true&w=majority&appName=Cluster0
    
  3. The modal rejects it with Unsupported database driver: mongodb+srv.
  4. Work around gap 1 by adding "connection_string_example": "mongodb+srv://user:pass@host/db" to the plugin manifest so the protocol registers.
  5. Paste the same URI again. It now parses, but the plugin receives only host=cluster0.xxxxx.mongodb.net, port=undefined, database=mydb — no SRV scheme, no query parameters.
  6. The connection does not resolve to the real cluster and databases fail to load.

OS Version

macOS 26.4 (25E246), arm64

Tabularis Version

v0.14.0 (also verified against main @ 39f5ab2)

Relevant Log Output

Unsupported database driver: mongodb+srv. Supported: mongodb-atlas, mysql, postgres, postgresql, sqlite

Suggested direction

The core need is that a plugin should be able to declare "I take the raw connection string, do not decompose it", and the host should carry that string through to the driver over JSON-RPC.

Roughly:

  1. A capability flag (e.g. connection_string_passthrough) that makes parseConnectionString skip decomposition and preserve the original URI verbatim.
  2. A connection_uri field on the connection model, forwarded to the external plugin on connect.
  3. Allow plugins to declare multiple protocols rather than deriving a single one from driver.id plus one example, so alias pairs like mongodb / mongodb+srv work.

Because the URI embeds credentials, it should be treated as a secret: stored in the OS keychain rather than in connections.json, with the cached secret rolled back if persistence fails. A transient URI is acceptable for Test Connection, but a saved connection should require keychain availability.

I have a prototype of this against the v0.14.0 codebase. It predates the capability-driven protocol registry that main now has, so it needs to be reworked to fit the current architecture, and I have not yet verified end-to-end that databases enumerate correctly with it. I am happy to open a PR once it is rebased and properly verified — let me know if the direction above is one you would accept.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions