openapi: 3.0.3 info: title: OpsxDB Server version: 0.3.0 description: Database workbench API — sessions, metadata, SQL exec, cancel, DDL, search, export servers: - url: http://127.0.0.1:8788 paths: /health: get: summary: Health check responses: "200": description: OK /api/health: get: summary: Health check responses: "200": description: OK /api/db/test-connection: post: summary: Ping a database without creating a session /api/db/open: post: summary: Ping and create a server-side session (password stays on server) /api/db/close: post: summary: Close a session /api/db/databases: post: summary: List databases (sessionId or full conn) /api/db/tables: post: summary: List tables in a database /api/db/columns: post: summary: List columns of a table /api/db/exec: post: summary: Execute SQL or Redis command (timeoutMs/requestId honored; dangerous SQL two-phase confirm) /api/db/explain: post: summary: Execution plan (rows for mysql/pg/sqlite, SHOWPLAN_XML for mssql, DBMS_XPLAN for oracle) /api/db/cancel: post: summary: Cancel an in-flight exec/explain by requestId → {"ok":true,"cancelled":bool} /api/db/ddl: post: summary: Show CREATE TABLE DDL for a table → {"ddl":"...","error":""} /api/db/search: post: summary: Fuzzy search tables/views by keyword (max 50) → {"results":[...],"error":""} /api/db/export: post: summary: Stream query results as csv/json/insert attachment (read-only SQL only, two-phase confirm on danger hits) /api/db/redis/keys: post: summary: Redis SCAN keys (whitelist-guarded commands) /api/db/redis/key: post: summary: Redis key value (type/ttl + rows) /api/db/redis/key/delete: post: summary: Delete a Redis key /api/ai/chat: post: summary: AI actions (stub fallback when unconfigured) /api/ai/config: get: summary: Get masked AI config post: summary: Save AI provider config (apiKey stored 0600, responses masked) /api/ai/generate: post: summary: AI SQL generation (action=generate) components: schemas: ConnReq: type: object properties: driver: { type: string } host: { type: string } port: { type: integer } user: { type: string } password: { type: string } database: { type: string } service: { type: string } sql: { type: string } table: { type: string } limit: { type: integer } offset: { type: integer } key: { type: string } pattern: { type: string } keyword: { type: string } format: { type: string, enum: [csv, json, insert] } sessionId: { type: string } ssl: { type: boolean } sslMode: { type: string, enum: [disable, require, skip-verify, verify-ca] } sslCA: { type: string } sslCert: { type: string } sslKey: { type: string } sslCAContent: { type: string } sslCertContent: { type: string } sslKeyContent: { type: string } tlsServerName: { type: string } sshEnabled: { type: boolean } sshHost: { type: string } sshPort: { type: integer } sshUser: { type: string } sshAuth: { type: string, enum: [password, privateKey] } sshPassword: { type: string } sshPrivateKey: { type: string } sshPassphrase: { type: string } confirmDanger: { type: boolean } timeoutMs: { type: integer } requestId: { type: string } CancelReq: type: object properties: requestId: { type: string } CancelResp: type: object properties: ok: { type: boolean } cancelled: { type: boolean } DDLResp: type: object properties: ddl: { type: string } error: { type: string } ObjectHit: type: object properties: schema: { type: string } name: { type: string } type: { type: string, enum: [table, view] } SearchResp: type: object properties: results: type: array items: $ref: "#/components/schemas/ObjectHit" error: { type: string } ExecResult: type: object properties: columns: type: array items: { type: string } rows: type: array items: type: object rowCount: { type: integer } timeMs: { type: integer } error: { type: string } truncated: { type: boolean } limit: { type: integer } offset: { type: integer } needConfirm: { type: boolean } ExplainResult: type: object properties: columns: type: array items: { type: string } rows: type: array items: type: object text: { type: string } timeMs: { type: integer } error: { type: string }