Connection sources
Connections are managed like DataGrip data sources: first-class, named, testable objects the user adds and organizes — not a deployment detail.
This is an engineering document. Specs are written for people building DataGripe: they record what a subsystem does and why the alternatives were rejected, and some of them describe things that are not built yet. If you are using DataGripe, the documentation is the place to be — it is maintained for you and this is not.
Supersedes: nothing (extends docs/initial_idea.md §6, §8)
Goal
Connections are managed like DataGrip data sources: first-class, named, testable objects the user adds and organizes — not a deployment detail. In addition to user-created connections stored in the application database, operators can predefine connections via configuration (environment variables or a config file) so a deployment can ship with ready-made data sources.
Non-goals
- Editing predefined connections in the UI (they are read-only in the UI; change the config and restart/reload).
- Per-user overrides of predefined connections (v1: predefined connections are visible to every member of the workspaces listed in their definition).
- Hot reload of the config file (restart required; hot reload is an open question below).
Definitions
| Term | Meaning |
|---|---|
| Managed connection | Created in the UI, stored in connections + connection_secrets |
| Predefined connection | Declared in server configuration; materialized read-only |
| Git datasource | Read from a repository's .datagripe/ (docs/spec/git-datasources.md) |
Both kinds implement the same ConnectionMetadata contract
(packages/contracts/src/connections.ts) so the explorer, editor, and
execution paths never branch on origin.
Design
Configuration format
Predefined connections come from one JSON file, path given by
CONNECTIONS_FILE (default: connections.json at the repo root, ignored by
git). Environment variables may supply secrets by reference so the file
itself stays commit-safe:
{
"connections": [
{
"id": "local-dev",
"name": "Local Dev Postgres",
"adapter": "postgres",
"host": "localhost",
"port": 5432,
"database": "datagripe",
"username": "datagripe",
"passwordEnv": "DEV_PG_PASSWORD",
"tlsMode": "disable",
"params": { "search_path": "sales,public" },
"readOnly": true,
"workspaces": ["*"]
}
]
}
idis stable, kebab-case, unique within the file.- Secrets are declared as
passwordEnv: "VAR_NAME"(indirection into the process environment). Inlinepasswordis accepted but documented as development-only. paramsare PostgreSQL runtime parameters sent when the connection opens (packages/contracts/src/connectionParams.ts). An allowlist, not free-form: an unrecognised one is a FATAL at connect time rather than a warning, so a typo here would be a datasource that cannot connect at all. Optional, and never a secret.workspaceslists workspace names or"*"for all workspaces.- The file is validated at startup with a Zod schema in
packages/contracts(predefinedConnectionsFileSchema); invalid files fail boot with per-entry error messages.
Server behavior
- At boot,
apps/server/src/config.tsloads and validates the file. - Predefined connections are exposed through the same
workspace.openpayload andconnection.testaction as managed ones. The response marks themsource: "predefined"(managed connections reportsource: "managed");ConnectionMetadatagains this field. - Secrets for predefined connections never touch the application database:
the server resolves
passwordEnvinto memory at boot, decrypt-where-used semantics do not apply, and the value is held only in the connection manager. connection.create/update/deletetargeting a predefined id returnsFORBIDDENwith codeCONNECTION_READ_ONLY.- Authorization: a predefined connection is usable only in the workspaces its definition names.
Schema impact
connections rows remain managed-only. Predefined connections are not
inserted into connections; query_executions.connection_id gains a
companion connection_ref text (e.g. predefined:local-dev) so history and
audit survive without a foreign key. The documents.default_connection_id
column cannot reference predefined ids; documents opened against a
predefined connection store that preference client-side (IndexedDB) until a
nullable default_connection_ref column is added in a later migration —
tracked as an open question.
ConnectionMetadata.id is a plain string (UUID for managed, kebab-case
slug for predefined) with a source: "managed" | "predefined" field, so
clients never branch on id shape.
Conflict rules
- A predefined
idcolliding with another predefinedidfails boot. - Predefined and managed connections live in disjoint id namespaces (predefined ids are slugs, managed ids are UUIDs), so no runtime collision is possible.
Client behavior
- The explorer renders one list, with a subtle badge on predefined entries.
- The connection dialog's save button is disabled for predefined entries; the form renders read-only with a "Defined by server configuration" hint.
- Test-connection works identically for both kinds.
Open questions
- Hot reload of
CONNECTIONS_FILE(SIGHUP or file watch) vs restart-only. - Whether documents should be able to persist
default_connection_refserver-side (schema change) instead of client-side. - Per-workspace visibility scoping UX once real auth exists (
workspacescurrently matches by name; switch to ids when seeded workspaces exist).
This page as Markdown, for an agent or a diff.