DB DevOps API

ChangeOps surface: scripts, releases, target connections, executions, approvals, and the enterprise audit trail. Base path /api/db-devops, Professional+ tier (audit is Enterprise, metrics is any licensed tier), authenticated. Governed by the 5000/min DB DevOps limiter. This surface persists to Postgres via the repository layer; the legacy in-memory /api/migrations environment endpoints (IDE side) are a separate, non-durable subsystem.

Scripts — /api/db-devops/scripts

MethodEndpointDescription
GET/scriptsList scripts with status, execution mode, environment, target
GET/scripts/:idSingle script
POST/scriptsCreate (draft)
PUT/scripts/:idPartial update (only supplied fields change)
DELETE/scripts/:idDelete; 409 if referenced by a release/execution/approval
POST/scripts/:id/approve{ "approvedBy": "email" }; notifies author
POST/scripts/:id/reject{ "rejectedBy": "email", "reason": "..." }; author may edit and resubmit
GET/scripts/:id/blast-radiusLatest computed blast-radius report (200 with null if none computed yet)
POST/scripts/:id/blast-radiusCompute/recompute now; optional { "approvalRequestId": "uuid" }. 409 if no target connection assigned
POST/scripts/:id/shadow-runStart an async shadow execution (202); poll /shadow-runs/:id
GET/scripts/:id/blast-radius/narrativeAI plain-English narration of the report (AI-tier)

POST /api/db-devops/scripts

FieldTypeRequiredDescription
namestringYes≤ 500 chars
sql_contentstringYesSQL or Mongo shell commands; ≤ 5MB (413 over cap)
execution_modestringNorelease (default) or asap
environmentstringNoDefaults to development
target_connection_iduuidNoTarget connection; may be assigned later, re-validated before execution
target_databasestringNoDatabase name on the target instance
authorstringNoFalls back to the authenticated caller
curl -X POST http://localhost:5002/api/db-devops/scripts \\
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \\
  -d '{ "name": "add-users-index",
        "sql_content": "CREATE INDEX idx_users_email ON users(email);",
        "execution_mode": "release", "environment": "production" }'
// 201 -> full script row; status "draft". Blast radius is computed asynchronously.

Releases — /api/db-devops/releases

MethodEndpointDescription
GET/releasesList releases
GET/releases/:idSingle release
GET/releases/:id/scriptsOrdered scripts in the release
POST/releasesCreate (name, optional description, scheduled_date, migration_ids[])
PUT/releases/:idUpdate
DELETE/releases/:idDelete
POST/releases/:id/signoffRecord a release-level sign-off

Connections — /api/db-devops/connections

Target databases for execution. The connection record's config JSONB holds dialect-specific fields plus Manager metadata (groupings, environment), so the IDE and DB DevOps share one connection list. Passwords are encrypted at rest and masked on read.

MethodEndpointDescription
GET/connectionsList
GET/connections/importableIDE connections eligible for import
POST/connections/importImport selected IDE connections
GET/connections/:idSingle (masked)
GET/connections/environment/:envFilter by environment
GET/connections/grouping/:groupingFilter by grouping
POST / PUT / DELETE/connections · /connections/:idCRUD
POST/connections/:id/testConnectivity probe
GET/connections/:id/databasesEnumerate databases on the instance
// POST /connections/:id/test
{ "success": true,  "message": "Connection successful", "latency_ms": 45 }
{ "success": false, "message": "ECONNREFUSED 10.0.0.5:5432" }
// GET /connections/:id/databases
[ { "name": "myapp_production", "size_bytes": 52428800 },
  { "name": "myapp_staging",    "size_bytes": 31457280 } ]

Database enumeration queries the dialect's catalog (Postgres pg_database, MySQL information_schema.schemata, SQL Server sys.databases, Mongo listDatabases, Oracle v$pdbs).

Executions — /api/db-devops/executions

Two concerns share this router: durable status records (start/complete/fail/rollback transitions) and live execution against a target, which opens a driver pool (pg / mysql2 / mssql / oracledb / mongodb) after decrypting the target password.

MethodEndpointDescription
GET/executionsFull history with status, duration, error
GET/executions/recentRecent runs
GET/executions/:idSingle record
POST/executionsCreate a status-tracking record
POST/executions/runExecute one script live against a target
POST/executions/run-releaseExecute all release scripts sequentially; stops on first failure
POST/executions/:id/start · /complete · /fail · /rollbackTransition state

POST /api/db-devops/executions/run

// body
{ "script_id": "uuid", "connection_id": "uuid", "database": "optional-override" }
// 200
{ "status": "COMPLETED", "rows_affected": 1, "execution_time_ms": 45, "result": [ ... ] }
// 500
{ "status": "FAILED", "error": "relation \\"users\\" already exists" }

POST /api/db-devops/executions/run-release

Each script runs against its own target_connection_id/target_database, falling back to the request's connection_id/database. Aggregate status is FAILED if any script fails; the per-script results[] pinpoints where it stopped.

{ "release_id": "uuid", "connection_id": "uuid", "database": "optional" }
// 200
{ "status": "COMPLETED", "results": [
    { "script_id": "abc", "script_name": "create-users-table", "status": "COMPLETED", "execution_time_ms": 32 },
    { "script_id": "def", "script_name": "add-users-index",    "status": "COMPLETED", "execution_time_ms": 18 } ] }
// partial failure
{ "status": "FAILED", "results": [
    { "script_id": "abc", "status": "COMPLETED", "execution_time_ms": 32 },
    { "script_id": "def", "status": "FAILED", "error": "syntax error at or near \\"SELEC\\"" } ] }

Approvals — /api/db-devops/approvals

Multi-signature approval workflow over approval_requests + approval_signatures. A request is satisfied when the required signatures are collected.

MethodEndpointDescription
GET/approvalsList requests
GET/approvals/:idSingle request with signatures
GET/approvals/status/:statusFilter by status (pending / approved / rejected)
GET/approvals/:id/blast-radiusBlast-radius report bound to the request
GET/approvals/:id/blast-radius/narrativeAI narration (AI-tier)
GET/approvals/:id/shadow-runsShadow runs for the request
GET/approvals/:id/snapshotsDecision snapshots captured at sign time
POST/approvalsOpen a request for a script/release
POST/approvals/:id/signAdd a signature (approve/reject with comments)
DELETE/approvals/:id/sign/:emailRevoke a signature

Audit — /api/db-devops/audit (Enterprise)

Append-only, tamper-evident audit trail. Every mutating request is recorded by auditMiddleware with sensitive fields redacted. Retention purge is the only permitted deletion.

MethodEndpointDescription
GET/auditPaginated log (?limit=&offset=)
GET/audit/user/:emailBy actor
GET/audit/action/:actionBy action
GET/audit/entity/:type/:idBy entity
GET/audit/range?start=&end=By date range (ISO)
GET/audit/count{ "count": n }
GET/audit/integrityVerify the hash chain over the entire trail
DELETE/audit/cleanup?days=90Retention purge; returns { "deleted": n }

GET /api/db-devops/audit/integrity

Recomputes the tamper-evident hash chain and reports whether the trail is intact. Any break identifies the first offending row so an operator can locate the tampering or gap.

{ "valid": true, "checked": 10432, "brokenAt": null }

Settings — /api/db-devops/settings

K/V store (AI provider, approval policy, notification/session config). Sensitive values are encrypted at rest.

MethodEndpointDescription
GET/settingsAll settings
GET / PUT / DELETE/settings/:keyRead / upsert / remove a single key
POST/settings/batchUpsert many keys atomically

Discovery — /api/db-devops/discovery

Fleet inventory: hosts, scans, discovered databases, and tags.

MethodEndpointDescription
GET / POST / PUT / DELETE/discovery/hosts · /discovery/hosts/:idHost CRUD
POST/discovery/hosts/:id/scanScan a host for databases
GET/discovery/hosts/:id/historyScan history
GET/discovery/databases · /discovery/databases/:idDiscovered databases
PUT/discovery/databases/:id/statusUpdate inventory status
POST / DELETE/discovery/databases/:id/tags · /tags/:tagIdTag assignment
GET / POST/discovery/tagsTag catalog

Metrics — /api/db-devops/metrics

GET /api/db-devops/metrics returns aggregate ChangeOps counters (scripts, releases, connections, pending approvals, execution outcomes) for dashboards. Any licensed tier.

Notifications — /api/notifications

MethodEndpointDescription
GET/notificationsCurrent user's notifications
GET/notifications/unread-countUnread badge count
POST/notifications/:id/read · /read-allMark read
DELETE/notifications/:idDismiss
GET / PUT/notifications/preferencesPer-user delivery preferences

The backend also emits these over Socket.IO (role-aware broadcast); polling these endpoints is the supported HTTP fallback.

Data protection — /api/data-protection

Subject-rights operations over user data.

MethodEndpointDescription
GET/data-protection/export/:userIdExport a user's data (portability)
GET/data-protection/access/:userIdAccess report
DELETE/data-protection/erase/:userIdErasure

IDE routes (Starter+)

The interactive IDE calls the connection/query/schema families directly. Connections are shared with DB DevOps.

MethodEndpointDescription
GET / POST/api/connectionsList / create (backend tests reachability, then encrypts password, before persisting)
GET / PUT / DELETE/api/connections/:idRead (masked) / update / delete
POST/api/connections/testProbe without persisting
POST/api/connections/:id/connect · /disconnectOpen / close a live pool
GET/api/connections/:id/databasesEnumerate databases
POST/api/queries/executeRun a query
POST/api/queries/execute-batch · /run-scriptMulti-statement / script execution
POST/api/queries/explain · /validate · /previewPlan / validate / preview
GET/api/databases/:connectionId/schemaSchema introspection
GET/api/databases/:connectionId/object-definitionDDL for an object
GET/api/navigator/:connectionId/objects · /object-properties · /tables/:schema/:name/columnsObject Explorer tree + inspector (per-dialect)
// POST /api/queries/execute
{ "connectionId": "conn-uuid", "query": "SELECT * FROM users LIMIT 10" }
// ->
{ "data": [ { "id": 1, "email": "admin@company.com" } ],
  "columns": ["id","email"], "rowCount": 1, "executionTime": 12 }

executionTime is server-measured database time in ms (excludes browser round-trip).