feat: external databases — register, probe, encrypted credentials

Databases hosted outside Containr can now be registered alongside
managed ones. The connection is probed before storing (protocol-level
for postgres/redis-family via real drivers, TCP dial for the rest),
credentials are encrypted at rest and never returned, and external rows
skip managed lifecycle actions, backups, and Docker metrics.

- POST /databases/register-external — probe + create
- POST /databases/test-connection — ad-hoc probe (ok/latency_ms/error)
- POST /databases/{id}/test-connection — re-probe stored credentials
- provider/external fields on database services; privileged reads get a
  composed connection URL with loopback hosts rewritten to the caller's
- CLI: databases register + test-connection; MCP: 3 new tools
- UI: managed/external toggle in the create modal, external badge and
  host display, per-row test button, backups section hidden
- Migration widens the plan CHECK to admit 'external'

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-10-08 22:09:42 +02:00
1 parent 3664eaed1a
commit 5dc9b5f115
19 files changed
+1274 -48

No files matched your search

+7
View File
@@ -139,6 +139,13 @@ CREATE TABLE database_services (
connection_url TEXT,
backup_schedule VARCHAR(100),
next_backup_at TIMESTAMP WITH TIME ZONE,
provider VARCHAR(20) NOT NULL DEFAULT 'managed',
external_host VARCHAR(255),
external_port INTEGER,
external_name VARCHAR(255),
external_username VARCHAR(255),
external_password TEXT NOT NULL DEFAULT '',
external_ssl BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);