Skip to content

feat(seed): pre-configured database connections via YAML/JSON config#50

Merged
cevheri merged 37 commits into
mainfrom
feat/seed-connections
Mar 25, 2026
Merged

feat(seed): pre-configured database connections via YAML/JSON config#50
cevheri merged 37 commits into
mainfrom
feat/seed-connections

Conversation

@cevheri
Copy link
Copy Markdown
Contributor

@cevheri cevheri commented Mar 25, 2026

Summary

  • Seed Connections module (src/lib/seed/) — YAML/JSON config file loading with TTL cache, ${ENV_VAR} credential injection, role-based filtering (admin, user, * wildcard), and hybrid managed/unmanaged connection model
  • New API endpoint GET /api/connections/managed — returns role-filtered connections with credential stripping for managed connections
  • 13 DB API routes updated with shared resolveConnection() utility for server-side credential resolution via seed: prefixed connection IDs
  • Client hooks updated to send connectionId instead of full credentials for managed connections (7 fetch sites across useQueryExecution, useTransactionControl, useConnectionManager)
  • UI — lock icon + hidden edit/delete for managed connections in sidebar
  • Helm chart — ConfigMap template, values.yaml, deployment.yaml volume mount + env vars
  • 69 new tests (unit + API + integration), all CI checks pass

How It Works

  1. Mount a YAML/JSON config file at /app/config/seed-connections.yaml
  2. Define connections with roles (whitelist) and managed flag (read-only vs editable copy)
  3. Credentials use ${ENV_VAR} syntax — resolved server-side from K8s Secrets or env vars
  4. managed: true connections never expose passwords to the client
  5. Config is TTL-cached (60s default) — hot-reload without restart

Config Example

version: "1"
defaults:
  managed: true
  environment: production
connections:
  - id: "prod-analytics"
    name: "Production Analytics"
    type: postgres
    host: analytics-db.internal
    password: "${ANALYTICS_DB_PASSWORD}"
    roles: ["admin"]
  - id: "dev-sandbox"
    name: "Dev Sandbox"
    type: mysql
    host: dev-mysql.internal
    password: "${DEV_DB_PASSWORD}"
    roles: ["*"]
    managed: false

Test plan

  • Lint (0 errors)
  • TypeScript strict (clean)
  • 489 tests pass (69 new seed tests)
  • Production build succeeds
  • Helm lint --strict passes
  • Helm template renders seed ConfigMap, env vars, volume mount

🤖 Generated with Claude Code

cevheri and others added 16 commits March 25, 2026 18:23
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…SON configuration and role-based access control
Add managed/seedId fields to DatabaseConnection interface and create
src/lib/seed/types.ts with SeedConnectionSchema, SeedConfigSchema,
SeedDefaultsSchema validated by Zod v4 with 19 passing unit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ts merge

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…and audit

Add SeedConnectionError class with statusCode, resolveConnection utility
that differentiates between 403 (role denied) and 404 (not found), and
extend AuditEventType with 'managed_connection'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements role-filtered managed connections API with password sanitization,
cache hint header, and 401 guard. Fixes pre-existing SSLConfig type error
in connection-filter.ts (optional ssl.mode cast to SSLConfig).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add seed connection support to all 13 DB API routes (query, multi-query,
schema, transaction, cancel, maintenance, monitoring, pool-stats,
profile, provider-meta, test-connection, schema-snapshot, health).

Each route now calls getSession() + resolveConnection() to support both
traditional connection objects and seed connectionId references. Added
SeedConnectionError handling to the centralized createErrorResponse
utility. Updated all corresponding test files with auth and seed
resolution mocks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…merge

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ch calls

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nnections

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a “Seed Connections” system to the app so operators can pre-configure DB connections via a mounted YAML/JSON file, resolve credentials from ${ENV_VAR} server-side, filter by user role, and expose managed connections through a dedicated API endpoint—while updating client/server flows to use seed: connection IDs instead of sending secrets to the browser.

Changes:

  • Introduces src/lib/seed/ module (schemas, config loader w/ TTL cache, env credential resolver, role filtering, and resolveConnection()).
  • Adds GET /api/connections/managed and wires resolveConnection() into multiple DB API routes for server-side credential resolution.
  • Updates client hooks/UI to support managed connections (send connectionId, lock icon, merge managed + user connections) and adds Helm/Docker/env docs + extensive tests/fixtures.

Reviewed changes

Copilot reviewed 64 out of 65 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tests/unit/seed/types.test.ts Unit tests for Zod schemas (seed config/connection/defaults).
tests/unit/seed/resolve-connection.test.ts Unit tests for resolveConnection() behavior (seed IDs, role gating, errors).
tests/unit/seed/index.test.ts Unit tests for seed module orchestrator APIs.
tests/unit/seed/credential-resolver.test.ts Unit tests for ${ENV_VAR} resolution and plaintext warnings.
tests/unit/seed/connection-filter.test.ts Unit tests for defaults merge + role filtering + mapping to managed connections.
tests/unit/seed/config-loader.test.ts Unit tests for YAML/JSON parsing, caching, and error handling.
tests/integration/seed/seed-pipeline.test.ts Integration coverage of end-to-end seed pipeline behavior.
tests/fixtures/seed-connections/valid-config.yaml Seed config fixture (YAML).
tests/fixtures/seed-connections/valid-config.json Seed config fixture (JSON).
tests/fixtures/seed-connections/multi-role-config.yaml Seed fixture to validate role filtering.
tests/fixtures/seed-connections/mixed-credentials.yaml Seed fixture to validate partial credential resolution.
tests/fixtures/seed-connections/minimal-config.yaml Minimal seed fixture for required fields.
tests/fixtures/seed-connections/invalid-config.yaml Invalid seed fixture for schema rejection.
tests/api/seed/managed-route.test.ts API tests for /api/connections/managed (auth, filtering, sanitization).
tests/api/db/transaction.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/test-connection.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/schema.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/schema-snapshot.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/query.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/provider-meta.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/profile.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/pool-stats.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/multi-query.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/monitoring.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/maintenance.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/health.test.ts Updates DB route tests to accommodate seed resolution mocking.
tests/api/db/cancel.test.ts Updates DB route tests to accommodate seed resolution mocking.
src/lib/types.ts Adds managed + seedId to DatabaseConnection.
src/lib/seed/types.ts Defines seed schemas/types + ManagedConnection.
src/lib/seed/resolve-connection.ts Implements server-side resolution of seed: connection IDs with role checks.
src/lib/seed/index.ts Public seed module API for listing/lookup of managed connections.
src/lib/seed/credential-resolver.ts Resolves ${ENV_VAR} credentials; logs plaintext password warnings.
src/lib/seed/connection-filter.ts Applies defaults + role filtering and maps seed -> managed connection objects.
src/lib/seed/config-loader.ts Loads YAML/JSON seed config from disk with TTL caching.
src/lib/audit.ts Adds new audit event type for managed connections.
src/lib/api/errors.ts Adds API error mapping for SeedConnectionError.
src/hooks/use-transaction-control.ts Sends connection payload via connectionId for managed connections.
src/hooks/use-query-execution.ts Sends connection payload via connectionId for managed connections across fetch sites.
src/hooks/use-connection-payload.ts Centralizes {connection} vs {connectionId} request body construction.
src/hooks/use-connection-manager.ts Fetches/merges managed connections into client connection list; updates schema/health calls.
src/components/sidebar/ConnectionItem.tsx Shows lock icon + hides edit/delete for managed connections.
src/app/api/db/transaction/route.ts Uses session + resolveConnection(); supports seed connection IDs.
src/app/api/db/test-connection/route.ts Uses session + resolveConnection(); supports multiple request body shapes.
src/app/api/db/schema/route.ts Switches to JSON parsing + session + resolveConnection().
src/app/api/db/schema-snapshot/route.ts Uses session + resolveConnection().
src/app/api/db/query/route.ts Uses session + resolveConnection().
src/app/api/db/provider-meta/route.ts Uses session + resolveConnection().
src/app/api/db/profile/route.ts Uses session + resolveConnection().
src/app/api/db/pool-stats/route.ts Uses session + resolveConnection().
src/app/api/db/multi-query/route.ts Uses session + resolveConnection().
src/app/api/db/monitoring/route.ts Uses session + resolveConnection().
src/app/api/db/maintenance/route.ts Resolves seed connections under existing admin session check.
src/app/api/db/health/route.ts Uses session + resolveConnection() for connection-level health check.
src/app/api/db/cancel/route.ts Uses session + resolveConnection().
src/app/api/connections/managed/route.ts New endpoint to return role-filtered managed connections with sanitization.
package.json Adds yaml dependency for YAML parsing.
docs/superpowers/specs/2026-03-25-seed-connections-design.md Design spec for seed connections feature.
docs/superpowers/plans/2026-03-25-seed-connections.md Implementation plan for the feature.
docker-compose.yml Documents seed config volume mount and env usage.
charts/libredb-studio/values.yaml Adds seedConnections Helm values.
charts/libredb-studio/values.schema.json Adds schema for seedConnections values.
charts/libredb-studio/templates/seed-configmap.yaml Adds ConfigMap template for inline seed config.
charts/libredb-studio/templates/deployment.yaml Adds volume mount + env vars for seed config.
bun.lock Locks yaml dependency.
.env.example Documents SEED_CONFIG_PATH and SEED_CACHE_TTL_MS.
Comments suppressed due to low confidence (4)

src/app/api/db/multi-query/route.ts:36

  • The validation checks if (!sql) but the error message says “Connection and query are required”. Since connection is already resolved/validated earlier, this message is now misleading. Consider updating it to only mention the missing field (e.g., “SQL is required”).
    if (!sql) {
      return NextResponse.json(
        { error: 'Connection and query are required' },
        { status: 400 }
      );

src/app/api/db/cancel/route.ts:23

  • The validation checks if (!queryId) but the error message says “Connection and queryId are required”. Since connection is already resolved/validated earlier, this message is now misleading. Consider updating it to only mention the missing field (e.g., “queryId is required”).
    if (!queryId) {
      return NextResponse.json(
        { error: 'Connection and queryId are required' },
        { status: 400 }
      );

src/app/api/db/query/route.ts:23

  • The validation checks if (!sql) but the error message says “Connection and query are required”. Since connection is already resolved/validated earlier (and missing-connection cases will throw a different error), this message is now misleading. Consider updating it to only mention the missing field (e.g., “SQL query is required”).
    if (!sql) {
      return NextResponse.json(
        { error: 'Connection and query are required' },
        { status: 400 }
      );

src/app/api/db/transaction/route.ts:41

  • The validation checks if (!action) but the error message says “Connection and action are required”. Since connection is already resolved/validated earlier, this message is now misleading. Consider updating it to only mention the missing field (e.g., “action is required”).
    if (!action) {
      return NextResponse.json(
        { error: 'Connection and action are required' },
        { status: 400 }
      );

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return conn;
});

const cacheTTL = Number(process.env.SEED_CACHE_TTL_MS) || 60_000;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cacheTTL uses Number(process.env.SEED_CACHE_TTL_MS) || 60_000, so setting SEED_CACHE_TTL_MS=0 won’t be reflected in cacheHint (it will report 60000). Consider aligning this with the loader’s TTL parsing via an explicit Number.isFinite() check (and optionally allow 0 to mean “no caching”).

Suggested change
const cacheTTL = Number(process.env.SEED_CACHE_TTL_MS) || 60_000;
const rawCacheTTL = Number(process.env.SEED_CACHE_TTL_MS);
const cacheTTL = Number.isFinite(rawCacheTTL) ? rawCacheTTL : 60_000;

Copilot uses AI. Check for mistakes.
Comment thread src/lib/api/errors.ts
Comment on lines +56 to +59
return NextResponse.json(
{ error: error.message, code: ApiErrorCode.CONFIG_ERROR, statusCode: error.statusCode },
{ status: error.statusCode }
);
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SeedConnectionError is mapped to ApiErrorCode.CONFIG_ERROR for all statuses, including 403/404. That makes client-side error handling ambiguous (403 is auth/authorization, 404 is missing resource). Consider setting the code based on error.statusCode (e.g., AUTH_ERROR for 401/403, keep CONFIG_ERROR for 400), and potentially omit code for 404 if there’s no matching enum value.

Suggested change
return NextResponse.json(
{ error: error.message, code: ApiErrorCode.CONFIG_ERROR, statusCode: error.statusCode },
{ status: error.statusCode }
);
let code: ApiErrorCode | undefined;
switch (error.statusCode) {
case 400:
code = ApiErrorCode.CONFIG_ERROR;
break;
case 401:
case 403:
code = ApiErrorCode.AUTH_ERROR;
break;
case 404:
code = undefined;
break;
default:
code = ApiErrorCode.CONFIG_ERROR;
break;
}
const body: ApiErrorResponse = {
error: error.message,
statusCode: error.statusCode,
...(code ? { code } : {}),
};
return NextResponse.json(body, { status: error.statusCode });

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +10
const FIXTURES = path.resolve(__dirname, '../../fixtures/seed-connections');
process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'multi-role-config.yaml');
process.env.ADMIN_PG_PASS = 'admin-secret';
process.env.USER_MYSQL_PASS = 'user-secret';
process.env.SHARED_PG_PASS = 'shared-secret';
process.env.BOTH_PG_PASS = 'both-secret';

Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test sets process.env.SEED_CONFIG_PATH and credential env vars at module load time and never restores them. That can leak state into other tests and cause order-dependent failures. Prefer moving these env assignments into beforeEach (or beforeAll) and cleaning them up in afterEach/afterAll.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +12
const FIXTURES = path.resolve(__dirname, '../../fixtures/seed-connections');
process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'multi-role-config.yaml');
process.env.ADMIN_PG_PASS = 'admin-secret';
process.env.USER_MYSQL_PASS = 'user-secret';
process.env.SHARED_PG_PASS = 'shared-secret';
process.env.BOTH_PG_PASS = 'both-secret';

import { resolveConnection, SeedConnectionError } from '@/lib/seed/resolve-connection';
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test sets process.env.SEED_CONFIG_PATH and credential env vars at module load time and doesn’t clean them up. That can leak state across test files (especially when the runner reuses the same process). Prefer setting env vars in beforeEach/beforeAll and deleting/restoring them in afterEach/afterAll.

Copilot uses AI. Check for mistakes.
Comment thread src/lib/seed/index.ts Outdated
Comment on lines +1 to +2
import { loadConfig, resetCache } from './config-loader';
import { resolveAllCredentials } from './credential-resolver';
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resetCache is imported but never used (the file already re-exports it via export { resetCache } from './config-loader'). This will trip lint rules in many setups; please remove the unused import from line 1.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +14
function getCacheTTL(): number {
return Number(process.env.SEED_CACHE_TTL_MS) || 60_000;
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getCacheTTL() uses Number(process.env.SEED_CACHE_TTL_MS) || 60_000, which treats a configured value of 0 as falsy and silently falls back to 60s. If you want to allow 0 (disable caching) or reject non-numeric values explicitly, switch to a NaN check (e.g., const ttl = Number(...); return Number.isFinite(ttl) ? ttl : 60_000;) and optionally clamp negative values.

Copilot uses AI. Check for mistakes.
Comment thread src/app/api/db/profile/route.ts Outdated
const connection = await resolveConnection(body, session);

if (!tableName) {
return NextResponse.json({ error: 'Connection and tableName required' }, { status: 400 });
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation checks if (!tableName) but the error message says “Connection and tableName required”. Since connection is already resolved/validated earlier, this message is now misleading. Consider updating it to only mention the missing field (e.g., “tableName is required”).

Suggested change
return NextResponse.json({ error: 'Connection and tableName required' }, { status: 400 });
return NextResponse.json({ error: 'tableName is required' }, { status: 400 });

Copilot uses AI. Check for mistakes.
cevheri and others added 11 commits March 25, 2026 20:09
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove demo type checks, isDemo flags, showcase-queries imports, and
the demo-connection fetch block from all source files. Source files
now have 0 typecheck errors related to demo removal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove all demo connection references from test fixtures, hook tests,
API tests, component tests, and configuration files. Replace
/api/demo-connection mock intercepts with clean fetch mocks, drop
isDemo/type:'demo' from mock objects, and remove the Helm demo: section,
configmap DEMO_MODE block, schema demo property, DEMO_DB_* env vars from
CI and playwright config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace 'demo' type with 'sqlite' in factory cache tests
- Update DEFAULT_TAB query to empty string (demo showcase removed)
- Remove DemoProvider mock from 6 test files
Add beforeEach/afterEach to always restore JWT_SECRET, and use
try/finally in the "throws when not set" test to prevent leaked
state on failure. Fixes flaky encryptState/decryptState failures
in CI coverage mode.
…ation

auth.test.ts was using mock.module('jose') which is process-wide in bun.
When CI ran auth.test.ts before oidc.test.ts in the same process,
the jose mock replaced real SignJWT/jwtVerify, causing encryptState/
decryptState tests to fail.

Fix: Remove jose mock from auth.test.ts, use real JWT sign/verify
with JWT_SECRET from test setup. Only next/headers (cookies) remains
mocked. This eliminates the process-wide contamination.
- Add managed:false credential pass-through test (covers line 21-22)
- Add invalid config 500 error test (covers line 28-32)
- Add 401 no-session test for POST /api/db/health (covers line 30)
- Add 400 missing-type test for POST /api/db/health (covers line 36-39)
- logout/route.ts: add error-path tests that trigger the catch block
  (lines 22-23) by making logout() throw both synchronously and
  asynchronously, verifying createErrorResponse returns HTTP 500
- db/factory.ts: add targeted tests for previously uncovered branches:
  - getOrCreateProvider connect-failure path (no tunnel) hits line 218
  - SSH tunnel cleanup when connect fails (lines 220-222)
  - removeProvider disconnect-error gracefully caught (line 244)
  - removeProvider closeSSHTunnel-error gracefully caught (line 253)
  - clearProviderCache disconnect-error via .catch callback (line 272)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cevheri added 9 commits March 25, 2026 22:42
- config.test.ts: Introduced controllable mock for getStorageConfig to simulate different storage configurations and added a test for error handling, ensuring a 500 response on config read failures.
- storage-routes.test.ts: Added tests for missing data field in PUT requests, returning a 400 status, and for handling errors when provider.setCollection fails, returning a 500 status.
- factory.test.ts: Added tests for getStorageProvider and closeStorageProvider functions, ensuring correct behavior for local paths and proper cleanup.
- sqlite.test.ts: Expanded tests for SQLite provider, verifying singleton behavior and proper closure of the provider.
Reverts coverage test additions that caused test:coverage:core to hang
in CI. The SQLite factory singleton tests and db factory connect-failure
tests manipulated module-level state that caused deadlocks in coverage
mode. Coverage improvements will be done in a separate PR.
- Add comprehensive Seed Connections section with config format,
  Docker/docker-compose/Helm examples, and full config reference table
- Add SEED_CONFIG_PATH and SEED_CACHE_TTL_MS to Environment Variables
- Remove DEMO_DB_* env vars from Koyeb deploy button URL
- Update Live Test section to reference seed connections
- Add seed-connections.yaml to .gitignore
…nents

Components were calling storage.getConnections() directly, which only
returns localStorage user connections — missing managed seed connections.

- Add useAllConnections() hook: merges user + managed connections
- Update MonitoringDashboard, OverviewTab, OperationsTab, SchemaDiff
  to use useAllConnections() instead of storage.getConnections()
- Update Studio.tsx delete/save handlers to preserve managed connections
- Fix: seed connections now appear in Monitoring, Admin, and Schema Diff
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 123 out of 125 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/app/api/db/transaction/route.ts:41

  • This 400 response is returned when action is missing, but by this point the connection has already been resolved/validated (and missing connections would have thrown earlier). The error message "Connection and action are required" is now misleading—consider changing it to only mention the missing action (or validate action before calling resolveConnection).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 220 to 224
const res = await fetch('/api/admin/fleet-health', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ connections: nonDemo }),
body: JSON.stringify({ connections }),
});
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

connections may include managed: true seed connections (password/connectionString stripped on the client). /api/admin/fleet-health currently calls getOrCreateProvider(conn) directly and will fail for these because credentials are missing. Consider sending { connectionId: "seed:..." } for managed connections (or splitting managed vs unmanaged payloads) and updating the fleet-health route to resolve seed credentials server-side before creating providers; alternatively filter managed connections out here if fleet-health can’t support them yet.

Copilot uses AI. Check for mistakes.
Comment on lines +72 to +76
// Load connections (user + managed seed connections)
const { connections: allConns } = useAllConnections();
useEffect(() => {
const loadedConnections = storage.getConnections();
setConnections(loadedConnections);
if (allConns.length === 0) return;
setConnections(allConns);
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useAllConnections() now includes managed: true seed connections (credentials stripped), but useMonitoringData() still posts the full connection object to monitoring/maintenance endpoints. Selecting a managed connection will likely break monitoring actions because the server won’t receive credentials unless you send a connectionId and resolve it server-side. Recommend updating the monitoring requests to use the same managed-connection payload pattern as query/transaction (e.g., build a {connectionId} payload when conn.managed && conn.seedId).

Copilot uses AI. Check for mistakes.
Comment on lines 90 to +94
} = useMonitoringData(selectedConnection, monitoringOptions);

const { connections: allConns } = useAllConnections();
useEffect(() => {
const loadedConnections = storage.getConnections();
setConnections(loadedConnections);
if (loadedConnections.length > 0) {
const savedId = storage.getActiveConnectionId();
const saved = savedId ? loadedConnections.find((c) => c.id === savedId) : null;
setSelectedConnection(saved ?? loadedConnections[0]);
}
}, []);
if (allConns.length === 0) return;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same managed-connection issue as MonitoringDashboard: this tab allows selecting connections from useAllConnections() (including managed seed connections without credentials), but useMonitoringData() currently sends connection: currentConnection in its requests. That will fail for managed connections unless the payload uses connectionId and the server resolves it. Please align monitoring/maintenance calls with the new seed connection resolution flow.

Copilot uses AI. Check for mistakes.
Comment on lines 101 to 105
// Get all connections for cross-connection comparison
const allConnections = useMemo(() => storage.getConnections(), []);
const { connections: allConnections } = useAllConnections();
const [fetchingRemote, setFetchingRemote] = useState(false);

// Fetch schema from a remote connection
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useAllConnections() can include managed: true seed connections (credentials stripped). Downstream, fetchRemoteSchema() posts a connection object to /api/db/schema-snapshot; for managed connections this will fail because the server won’t receive credentials and no connectionId is provided for seed resolution. Consider filtering managed connections out of the “Fetch from connection” list, or switch the request payload to send connectionId for managed connections and update the schema-snapshot route to resolve it server-side.

Copilot uses AI. Check for mistakes.
Critical fixes:
- Use buildConnectionPayload() in useMonitoringData (3 fetch sites)
- Use connectionId for managed connections in SchemaDiff fetchRemoteSchema
- Resolve seed credentials server-side in fleet-health route

Improvements:
- Map SeedConnectionError 403→AUTH_ERROR instead of CONFIG_ERROR
- Use Number.isFinite() for SEED_CACHE_TTL_MS (allow 0 value)
- Remove unused resetCache import from seed/index.ts
- Fix misleading error message in profile route
@sonarqubecloud
Copy link
Copy Markdown

@cevheri cevheri merged commit b91c8da into main Mar 25, 2026
9 checks passed
@cevheri cevheri deleted the feat/seed-connections branch March 25, 2026 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants