cd /news/ai-agents/show-hn-dbward-approval-workflows-fo… · home topics ai-agents article
[ARTICLE · art-92044] src=github.com ↗ pub= topic=ai-agents verified=true sentiment=· neutral

Show HN: Dbward – Approval workflows for production databases

Dbward, an open-core project, has launched approval workflows and audit logs for production databases, featuring multi-step approvals, tamper-evident audit trails, and AI agent guardrails. The core components are Apache-2.0 licensed, with some features under a commercial license. The tool includes standalone Rust binaries with embedded SQLite, MCP-native integration, Slack approvals, and a break-glass emergency bypass, aiming to prevent accidental or unauthorized database operations.

read10 min views1 publishedAug 11, 2026
Show HN: Dbward – Approval workflows for production databases
Image: source

Open-core project— core components are[Apache-2.0]. Some features and pre-built binaries include code under the[dbward Commercial License]. See[License]for details.

Approval workflows and audit logs for your production database.

Stop accidents before they hit production. Add approval gates, audit trails, and AI agent guardrails to every database operation — with standalone binaries and embedded SQLite. No external control-plane DB required.

  • 🔐 Approval workflows— multi-step, conditional auto-approve, TOML policy engine - 📋 Audit logs— tamper-evident hash chain, 24 event types, SQL redaction - 🤖 MCP-native— 12 tools, 6 prompts, elicitation support. AI agents operate safely. Remote HTTP transport for team setups - ⚡ Standalone binaries— CLI, server, and agent ship as self-contained Rust binaries with embedded SQLite. No external control-plane DB - 🔒 Agent isolation— DB credentials never leave the agent. CLI/AI never touch your database directly - 🛡️ SQL safety review— risk classification, DDL detection,DROP

blocking. Auto-approve safe queries, require approval for risky ones - 🔍 Preflight— analyze SQL before submitting. Get risk level, EXPLAIN plan, review findings, and fix hints without creating a request. AI agents converge on safe SQL before asking for approval - 🧠 Auto schema context— the agent collects table structures, columns, FKs, and row counts automatically. AI tools access schema via MCP resources — no manual documentation needed - 💬 Slack approvals— approve/reject from Slack with one click.dbward slack init

generates the app manifest - 🚨 Break-glass— emergency bypass with mandatory reason and audit. Operator/admin only, not available via MCP - 🆓 Core features free— approval, audit, MCP, Slack, break-glass all included underApache-2.0. Team features (OIDC, group auth) require acommercial license

┌─────────────────────────────────────────────────────────┐
│              dbward client (CLI / MCP)                    │
│  No DB credentials — sends requests, receives results    │
└──────────┬───────────────────────────────────────────────┘
           │ REST API
           ▼
┌─────────────────────────────────────────────────────────┐
│                    dbward server                          │
│  Approval engine │ Policy engine │ Audit log (hash chain) │
│  Ed25519 token signing │ OIDC/API auth │ Webhooks        │
│  In-memory result relay │ NO database credentials        │
└─────────────────────────────────────────────────────────┘
           ▲ Agent polls (outbound HTTPS)
           │
┌──────────┴───────────────────────────────────────────────┐
│                    dbward agent                           │
│  DB credentials here only │ Executes approved operations  │
│  Token verification (Ed25519) │ Multiple DB support       │
└──────────┬───────────────────────────────────────────────┘
           │
           ▼
      Target Database (PostgreSQL / MySQL)

Key principle: The client requests. The server decides. The agent executes. No component has more access than it needs.

Try the approval flow in 2 minutes (Docker):

git clone https://github.com/dbward-dev/dbward.git && cd dbward/examples/quickstart
docker compose up -d
docker compose run --rm alice execute "SELECT version()" -e development

Then submit → approve → execute → audit. Full walkthrough: Quickstart with Docker

Quick smoke test (local install):

curl -fsSL https://dbward.dev/install.sh | sh
dbward dev --database-url "postgres://user:pass@localhost:5432/mydb"
dbward --config ~/.dbward/dev/client.toml --database app execute "SELECT 1"

Dev mode auto-approves everything for fast iteration. See Connect Your Database for details.

Full reference:

[docs/reference/mcp.md]

{
  "mcpServers": {
    "dbward": {
      "command": "dbward",
      "args": ["mcp"]
    }
  }
}

MCP Tools (12):

Tool Description
dbward_execute_query
Execute SQL (SELECT/DML) via approval workflow
dbward_migrate_status
Show migration status
dbward_migrate_up
Apply pending migrations
dbward_migrate_down
Rollback migrations
dbward_migrate_create
Create migration file (local)
dbward_wait_request
Wait for request completion and return result
dbward_list_pending
List pending approval requests
dbward_who_can_approve
Show who can approve a request
dbward_find_similar_requests
Find similar past requests
dbward_preflight_sql
Analyze SQL safety without creating a request
dbward_explain_policy_failure
Explain why approval is needed
dbward_inspect_schema
Inspect database schema (list tables or describe columns)

MCP Prompts (6): review_migration

, explain_request

, draft_migration

, draft_rollback

, summarize_audit_trail

, prepare_approval_comment

Elicitation: On production operations, dbward asks the AI client for a reason before proceeding (if the client supports MCP elicitation).

Remote MCP (HTTP): For team setups, the server exposes MCP over HTTP — no local binary needed (9 tools, excludes local-only migration tools):

{
  "mcpServers": {
    "dbward": {
      "type": "streamable-http",
      "url": "https://your-server.example.com/mcp"
    }
  }
}

dbward uses on-demand execution: the agent does not execute on approval. Instead, the client explicitly resumes the request when ready to receive the result.

1. Client creates request → server evaluates policy → pending / auto_approved
2. (If pending) Human approves via CLI
3. Client resumes (`dbward request resume <id>`) → server marks as "dispatched"
4. Agent polls, claims, executes on DB → returns result to server
5. Server relays result in-memory to waiting client (long poll)
6. Client displays result (server persists to local FS or S3)

Results are persisted on the server by default (local filesystem or S3, configurable via [result_storage]

). The in-memory relay has a 10-minute TTL for streaming delivery. Use --no-result-store

to skip persistence for a single request.

Defined in server.toml

and hot-reloaded via SIGHUP. See Configuration Reference.

Control whether operations require approval:

[[workflows]]
database = "*"
environment = "production"
operations = ["execute_select", "migrate_up", "migrate_down"]

[[workflows.steps]]
type = "approval"

[[workflows.steps.approvers]]
role = "admin"
min = 1

[[workflows]]
database = "*"
environment = "staging"

[workflows.auto_approve]
mode = "risk_based"
risk = "low"

[[workflows.steps]]
type = "approval"

[[workflows.steps.approvers]]
role = "admin"
min = 1

Control re-execution limits (rate limiting):

[[execution_policies]]
database = "primary"
environment = "production"
max_executions = 10
execution_window_secs = 3600
retry_on_failure = false

Control who can access results and storage:

[[result_policies]]
database = "primary"
environment = "production"
delivery_mode = "stream"
access = ["requester", "admin"]

Route webhooks per database × environment:

[[notification_policies]]
database = "primary"
environment = "production"

[[notification_policies.webhooks]]
url = "https://hooks.slack.com/services/..."
format = "slack"

Full reference:

[docs/reference/cli.md]

dbward [OPTIONS] <COMMAND>

Commands:
  init          Interactive setup wizard
  doctor        Diagnose connectivity and configuration
  login         OIDC login (browser or --device for headless)
  logout        Revoke tokens and delete credentials
  whoami        Show current identity and role
  migrate       Run migrations (up/down/status/create)
  execute       Execute SQL (--emergency --reason for break-glass)
  audit         Search audit log (--verify for hash chain check)
  mcp           Start MCP stdio server
  server        Server management (start, token create/revoke, reload)
  agent         Start the agent
  dev           Start local dev server + agent
  self-update   Update dbward to the latest version
  request       Manage requests:
    list          List requests (--pending-for-me, --status)
    show          Show request detail
    approve       Approve a pending request
    reject        Reject a pending request
    resume        Resume and wait for result
    cancel        Cancel a pending request
  token         Manage API tokens (create/list/revoke)
  user          Manage users (list/suspend/activate)
  slack         Slack integration:
    init          Generate app manifest and creation URL
  policy        Policy tools:
    resolve       Resolve effective policy for a request

Global Options:
  --version, -v            Show version and exit
  --config <PATH>          Config file (standalone mode; omit for auto-detect)
  --database <NAME>        Target database [env: DBWARD_DATABASE]
  --environment <ENV>      Environment [env: DBWARD_ENV]

Full reference:

[docs/reference/api.md]

Method Path Description
POST /api/requests
Create request
POST /api/requests/:id/approve
Approve
POST /api/requests/:id/resume
Resume for on-demand execution
GET /api/requests/:id/result/stream
Long-poll for result
GET /api/audit/events
Audit events
GET /api/audit/verify
Verify hash chain integrity
POST /api/tokens
Create API token
GET /api/databases
List configured databases
GET /api/agents
List connected agents
POST /mcp
Remote MCP (HTTP)

See full API reference for all endpoints, parameters, permissions, and response formats.

Threat model and hardening guide:

[docs/security/]

Zero-trust client— developer machines never have DB credentials** Signed execution tokens**— Ed25519. Token includes SHA-256 hash of SQL + target database** Token replay prevention**— executed/failed requests don't issue new tokens** Multi-statement rejection**— prevents SQL injection via statement chaining** Writable CTE detection**—WITH x AS (DELETE ...) SELECT ...

classified as DMLRBAC— admin (system management), requester (SQL operations), operator (monitoring + break-glass), approver (review)** Network isolation**— server has no DB credentials; agent connects outbound only** API token auth**— SHA-256 hashed, prefix+hash composite lookup** OIDC auth**— JWT verification with JWKS caching, RS256/ES256, PKCE for CLI (Team)** Audit hash chain**— SHA-256 chain linking all events, tamper-evident

Target Status
Linux x86_64 (glibc) ✅ Supported
Linux aarch64 (glibc) ✅ Supported
macOS Apple Silicon ✅ Supported
macOS Intel ✅ Supported
Windows ❌ Not supported

Pre-built binaries are available on GitHub Releases. Docker images are published for linux/amd64

and linux/arm64

.

Note:Pre-built binaries and Docker images include commercial-licensed components. They are free to use within Free plan limits. See[LICENSE]for details.

Database Status
PostgreSQL ✅ Supported
MySQL ✅ Supported

Auto-detected from URL scheme (postgres://

or mysql://

).

Full guide:

[docs/guides/authentication.md]

cat ./data/admin-token     # admin token
cat ./data/agent-token     # agent token

dbward token create --subject alice --role admin
dbward login              # Browser-based (PKCE)
dbward login --device     # Headless (SSH, containers)
dbward whoami             # Check identity
dbward logout             # Revoke + delete tokens

Approve and reject requests directly from Slack with interactive buttons:

dbward slack init --server-url https://your-server.example.com

Configure in server.toml

:

[slack]
bot_token = "${SLACK_BOT_TOKEN}"
signing_secret = "${SLACK_SIGNING_SECRET}"
channel = "C0123ABC456"

See Notifications Guide for setup details.

[[webhooks]]
url = "https://internal.example.com/dbward"
format = "generic"
secret = "whsec_xxxx"  # HMAC-SHA256 in X-Dbward-Signature header

Events: request.created

, request.approved

, request.rejected

, execution.completed

, request.break_glass

.

Free: unlimited webhook destinations.

dbward execute "SELECT pg_terminate_backend(12345)" \
  --emergency --reason "connection pool exhausted at 3am"
  • Skips approval — agent executes immediately when dispatched
  • Fires request.break_glass

webhook (🚨 in Slack) - Reason recorded in audit log Operator or admin role(requiresrequest.break_glass_query

for SELECT,request.break_glass_dml

for writes)Not available via MCP(AI agents cannot trigger break-glass)

Full reference:

[docs/reference/configuration.md]

Config is resolved in two layers:

Global(~/.config/dbward/config.toml

): server URL, token/OIDCProject(./dbward.toml

): databases, migrations

[server]
url = "http://localhost:3000"
token = "dbw_..."
default_database = "app"
migrations_dir = "db/migrations"

[databases.app]
agent_id = "agent-prod"
poll_interval_ms = 1000
max_concurrent_tasks = 2

[server]
url = "https://dbward.internal:3000"
agent_token = "${DBWARD_AGENT_TOKEN}"

[databases.primary.production]
url = "${DATABASE_URL_PRIMARY}"

[databases.analytics.production]
url = "${DATABASE_URL_ANALYTICS}"
state_dir = "/data"

[auth]

[[webhooks]]
url = "https://hooks.slack.com/services/..."
format = "slack"

[[workflows]]
database = "*"
environment = "production"
operations = ["execute_select", "migrate_up", "migrate_down"]

[[workflows.steps]]
type = "approval"

[[workflows.steps.approvers]]
role = "admin"
min = 1

[[execution_policies]]
database = "*"
environment = "production"
max_executions = 10
execution_window_secs = 3600

[logging]
output = "stderr"              # "stderr" (default) or "file"

Free Team ($149/mo)
Database connections 3 20
Active users 20 50
Workflow rules Unlimited Unlimited
Webhooks Unlimited Unlimited
Agents Unlimited Unlimited
Approval + Audit + MCP + Break-glass
Slack approval UI
Result policies
Notification policies
OIDC / SSO
Group-based authorization
Audit export (CSV/JSON)

Safety features are always free. You pay for scale and organizational complexity.

Team plan is not yet available.[Join the waitlist]to get notified.

Migrations use single-file dbmate-compatible format:

migrations/
├── 20260501120000_create_users.sql
└── 20260502090000_add_email.sql
-- migrate:up
CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT NOT NULL);

-- migrate:down
DROP TABLE users;

dbward uses an open-core licensing model.

Core(crates/

):Apache-2.0— approval workflows, audit logs, MCP, SQL review, agent execution, break-glass. Use, modify, and redistribute freely.Commercial(commercial/

):dbward Commercial License— OIDC/SSO, group authorization, Team/Enterprise plan enforcement. Requires a paid subscription for production use.

No license key = Free plan. All core features work without restriction.

See LICENSE for the full structure.

── more in #ai-agents 4 stories · sorted by recency
── more on @dbward 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/show-hn-dbward-appro…] indexed:0 read:10min 2026-08-11 ·