Overview

WolfStack unified Database Manager

One Database Manager, cluster-wide. The πŸ—„οΈ Databases page at the top of the sidebar is the single place in WolfStack to reach every configured database β€” MariaDB, MySQL, or PostgreSQL β€” regardless of which node in the cluster actually owns it. The old per-node MySQL editor has been retired: there is now one manager at the datacenter level that serves every connection.

Connections are stored as profiles: a label, engine type, host/port/user/password, and the cluster+node that can reach it. Because profiles replicate to every WolfStack peer, any node can proxy queries β€” if the main node goes down, the others pick up seamlessly.

Supported Databases

DatabaseDriverNotes
MariaDBmysql_async (pure Rust)All MariaDB versions, TCP + SSL/TLS
MySQLmysql_async (pure Rust)MySQL 5.7+ and 8.0+
Percona Servermysql_async (pure Rust)Compatible with MySQL protocol
PostgreSQLtokio-postgres + deadpoolPooled connections, SSL prefer/require/disable

Cluster-Aware Routing

When you add a connection you pick the target cluster, then the owning node, then the IP reachable from that node β€” the dropdown includes host interfaces, Docker containers, LXC containers, and VMs with their names so you can find them at a glance. You can also paste a shorthand like WolfStack-Proxmox:wolfstack-1:10.10.10.105.

Queries execute on the node that owns the connection. If you open a connection from a different node, WolfStack proxies the query to the owning peer over the cluster-secret-authenticated inter-node channel β€” no exposing database ports on the public network, no copying credentials between nodes. Profile changes replicate automatically.

Database Manager β€” Features

The Manager takes the whole page when a connection is open. Six tabs across the top:

πŸ“Š Data

  • Browse rows with pagination (50 / 100 / 250 / 500 / 1000 rows per page)
  • Click column headers to sort ascending, click again for descending
  • Quick text filter across all visible cells
  • Inline row editing: click ✏️ for a full row-edit modal with one input per column, NULL toggles, PK fields protected, only-changed-columns UPDATE
  • Edit / Delete buttons pinned to the left β€” always visible, even on wide rows
  • βž• Row β€” insert a new row via prompts for each column
  • πŸ“₯ Import CSV β€” upload a CSV, header row maps to columns, rows inserted in a single batch
  • πŸ“€ Export β€” CSV / JSON / SQL INSERTs of the current page

πŸ—οΈ Structure

  • Full DDL editing with Schema permission: Add column / Drop column, Add index / Drop index, Add foreign key / Drop foreign key
  • Engine-aware syntax: DROP CONSTRAINT on Postgres, DROP FOREIGN KEY on MySQL/MariaDB

πŸ—ΊοΈ Diagram (ERD)

  • SVG schema diagram β€” tables rendered as draggable boxes with PK πŸ”‘ markers
  • Foreign-key relationships drawn as bezier arrows
  • Mousewheel zoom, drag-empty-space pan, double-click a table to jump to its Structure tab
  • Auto-layout places tables in a grid (heights variable so wide tables don't overlap)
  • πŸ’Ύ Save SVG β€” exports a standalone .svg file for docs and hand-off

🧱 Build (Visual Query Builder)

  • Drag tables from the picker onto the canvas
  • Tick columns to include in the SELECT
  • Click-drag column-to-column to draw a JOIN (INNER by default)
  • Add WHERE conditions in the bottom panel (table/column/operator/value, one row per condition)
  • Configurable row limit
  • Generated SQL updates live at the bottom β€” hit Send to Query to open it in the Query tab

⚑ Query

  • Multi-tab editor (+ new tab, βœ• close, double-click to rename)
  • Lightweight SQL syntax highlighting (keywords / strings / numbers / comments / operators)
  • Live sqlparser-backed validation with tier badge (Read / Update / Delete / Schema)
  • Ctrl+Space autocomplete with context: after FROM/JOIN suggests tables, after . suggests columns, otherwise keywords + tables. Each candidate shows its source ("table in schema", "column in schema.table", "SQL keyword")
  • πŸ’Ύ Saved queries β€” named, per-user, server-side (follow you across devices)
  • Recent β€” auto ring-buffer of the last 20 executed queries per connection, per user
  • πŸ” Explain / ✨ Format / πŸ“‚ Run SQL file (splits on ;, handles DELIMITER, runs via /query-multi)
  • Per-tab schema context (Navicat-style): new tabs inherit the currently-selected schema, existing tabs keep theirs
  • Destructive-query confirm on TRUNCATE, DROP TABLE, unqualified DELETE, unqualified UPDATE
  • Unlimited-query warning when a SELECT/WITH has no LIMIT
  • Draggable splitter between editor and result panel
  • β›Ά Fullscreen toggle for the whole Databases page

πŸ–₯️ Server

  • Server version, database, current user, host, port
  • Key variables β€” click ✏️ to change (modal with session / global / ALTER SYSTEM scope, requires Schema permission, auto-runs pg_reload_conf() after Postgres ALTER SYSTEM)
  • Active sessions (process list) β€” click βœ• to kill via KILL <id> (MySQL) or pg_terminate_backend(pid) (Postgres)

Schema tree β€” left panel

  • Tables + Views grouped per schema with counts
  • Procedures / Functions / Triggers listed read-only β€” click to view the CREATE definition in a modal
  • Per-schema + New table, Dump schema, Dump + data actions
  • β—€ / πŸ“ β–Ά toggle to hide the tree and give the editor full width

Create Table & Dump / Restore

Create Table wizard β€” form with a column grid (name, type, NOT NULL, PK, default), live SQL preview, runs at Schema permission.

Dump to SQL β€” client-driven export of a whole schema. Choose schema-only (fast) or schema + data (paginated 500-row batches). Writes a standalone .sql file with DROP TABLE IF EXISTS / CREATE TABLE / INSERT statements ready for restore. Postgres uses information_schema reconstruction since it has no SHOW CREATE TABLE.

Restore from SQL β€” the Query tab's πŸ“‚ Run SQL file button accepts any .sql upload. The client splits on ; honouring comments, string literals, and DELIMITER directives; the new /query-multi endpoint executes each statement sequentially with stop-on-error and reports per-statement outcomes including the line number where any failure occurred.

Schema Compare

The 🧭 Compare schemas button on the Databases page header opens a side-by-side diff of two schemas (same connection or different). Reports:

  • Tables only in source / only in target / in both-with-differences
  • Per-table: column additions, removals, type / nullability / default changes
  • Index and foreign-key additions / removals

Click πŸ“œ Generate migration SQL to produce CREATE TABLE / DROP TABLE / ALTER TABLE statements that would bring the target in line with the source. The generator leaves complex type-changes as TODO comments for the operator to review β€” always treat the output as a starting point.

Enterprise ACL

Each connection profile can be restricted to a list of named WolfStack users. Operators without access don't see the profile at all β€” not in the Databases page, not in the Settings editor, not via the API. A πŸ”’ badge next to the connection in the list indicates ACL is active.

ACL is an Enterprise feature; on Community installs all authenticated operators share every profile. The restriction applies uniformly to the UI, the REST API, and the AI agent tool surface β€” there is no bypass path.

AI Agents & WolfFlow

AI agents can talk to the database. Agents configured with SQL permissions use the same pipeline as the UI β€” same profiles, same cluster routing, same audit log, same sqlparser classifier, same enterprise ACL. An agent asked "how many customers signed up yesterday?" can issue SELECT COUNT(*) FROM customers WHERE created_at > NOW() - INTERVAL 1 DAY and feed the result back into its reply.

Per-agent settings gate what the agent can touch via three independent checks:

  1. Flags β€” each agent has separate sql_read, sql_update, sql_delete switches (all default off). DDL via sql_schema is never granted to agents β€” AI writing ALTER TABLE unsupervised is not a surface we want open.
  2. Allowlist β€” an operator-set list of connection IDs the agent is allowed to query (empty list = none).
  3. Parser β€” every query is classified by sqlparser before dispatch. An UPDATE pretending to be a SELECT is rejected before it hits the database. Multi-statement queries are refused outright.

WolfFlow workflows get a matching SQL Query action node with the same gates β€” operators pick a connection, pick a permission tier, write the query; the workflow runs it on schedule or trigger and can feed the result into subsequent steps. Every execution β€” agent, workflow, or UI β€” is appended to /var/log/wolfstack/sql-audit.log with caller tag, connection ID, query, outcome, row count, and elapsed time.

Security Model

  • Encrypted at rest β€” passwords stored AES-256-GCM encrypted with the cluster secret (same scheme as OIDC client secrets); only decrypted in memory at connect time
  • Cluster-secret auth on inter-node calls β€” session cookies can't reach the /query-proxy, /receive, or /audit endpoints; only trusted peers
  • Hardcoded API denylist β€” agents using the generic wolfstack_api tool cannot POST to /api/sql-connections/* or the node-IP enumerator; the only way to run SQL is through the dedicated sql_query tool, which respects all three permission gates
  • Filesystem denylist β€” /etc/wolfstack/sql-connections.json, /etc/wolfstack/sql-saved-queries.json, and /var/log/wolfstack/sql-audit.log are off-limits to agent filesystem tools
  • Per-user saved queries β€” operators' pinned SQL is keyed to their username, not shared across the cluster
  • Bounded execution β€” 5s connect timeout, 30s default query timeout (configurable per query), 10,000-row / 10 MB result cap; hung databases can't starve the actix workers
Esc