Skip to content

Slack Integration

dbward integrates with Slack to provide interactive approval workflows, real-time notifications, and self-service user onboarding — all without leaving your workspace.

The [slack] configuration enables a bidirectional integration:

DirectionCapability
OutboundRich notifications with approve/reject buttons, thread replies, @mentions
InboundSlash commands (/dbward), review modals, onboarding flow

This differs from [[webhooks]] format = "slack", which is outbound-only (Incoming Webhook, no buttons or interactions). Both can be enabled simultaneously — see Notifications for webhook setup.

  • A publicly reachable HTTPS URL for your dbward server (Slack requires HTTPS for Request URLs)
  • A Slack workspace where you can create apps
  • Users must be linked (see Account Linking) to use approval and execution features. Onboarding (/dbward join) does not require a linked account.
Section titled “1. Create a Slack App (recommended: manifest)”

The fastest path is dbward slack init, which generates a complete App Manifest:

Terminal window
dbward slack init --server-url https://dbward.example.com
dbward slack init --server-url https://dbward.example.com --open # opens browser

This outputs:

  • A pre-filled Slack App creation URL with all required scopes and URLs
  • Step-by-step instructions to copy the Bot Token and Signing Secret

If you prefer to configure the app manually:

  1. Go to api.slack.com/appsCreate New App → From scratch
  2. Add Bot Token Scopes:
    • chat:write — send messages and thread replies
    • im:write — send DMs (token delivery, rejection notices)
    • channels:join — auto-join public channels
    • channels:read — channel info lookup
    • groups:read — private channel info lookup
    • commands — receive slash commands
    • users:read — user info lookup
    • users:read.email — resolve email → Slack UID
  3. Interactivity & Shortcuts → Enable → Request URL: https://your-server.com/api/slack/interactions
  4. Slash Commands → Create: /dbward → URL: https://your-server.com/api/slack/commands
  5. Install to Workspace → copy Bot Token (xoxb-...)
  6. Basic Information → copy Signing Secret

Note: Event Subscriptions are not required. dbward uses Request URLs exclusively.

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

See Configuration Reference: [slack] for all options.

/invite @dbward

Run diagnostics:

Terminal window
dbward-server validate --config server.toml --preflight

Checks: bot token format (xoxb- prefix) and auth.test API call. (Channel existence, bot membership, and signing secret format are not verified; use the smoke test below to confirm end-to-end.)

Limitation: --preflight only confirms the bot token is valid via auth.test. It cannot verify channel access, slash command registration, or Request URL routing. Use the smoke test below to confirm end-to-end.

After setup, type /dbward help in any channel where the bot is present. You should see an ephemeral message listing available commands.

Interactive features (slash commands, approval buttons) require that each Slack user is linked to a dbward user account.

Terminal window
dbward user update alice --slack-user-id U02CR3TMKKJ

Or via API:

PATCH /api/users/alice
{"slack_user_id": "U02CR3TMKKJ"}

Users who interact without a linked account receive an ephemeral message with linking instructions.

Outbound mention resolution (for notifications) uses a fallback chain:

  1. slack_user_id from DB
  2. Email → users.lookupByEmail API
  3. Plain-text subject ID (no @mention)

Inbound authentication (slash commands except /dbward join, button clicks) requires a linked account — there is no email fallback for interactive actions. /dbward join is exempt to allow onboarding of new users.

All commands are registered under a single /dbward slash command with subcommands:

CommandAction
/dbward executeOpen SQL execution modal (DB/env selection filtered by user permissions)
/dbward joinRequest onboarding — see Onboarding
/dbward helpShow available commands (ephemeral)

When a request lifecycle event occurs, dbward posts or updates messages in the configured channel.

EventTrigger
request.createdRequest submitted
request.break_glassEmergency request (bypass approval)
request.auto_approvedAuto-approved by policy

Messages include: requester, database, environment, operation type, risk level (🔴/🟡/🟢), required approvers (@mentioned), and a Review Request button (for request.created).

As the request progresses, dbward adds thread replies and updates the original message in-place:

EventDescription
step.approvedApproval step completed — mentions next approver
request.approvedFully approved — mentions requester
request.rejectedRejected with comment
request.expiredTTL expired
request.cancelledCancelled by user
execution.completedExecution succeeded
execution.failedExecution failed
execution.lostAgent connection lost during execution
request.dispatch_timeoutNo agent picked up the request

SQL content is never shown in channel messages. Full SQL is only visible inside the approval modal after clicking Review Request.

The interactive approval flow works through Slack modals:

  1. Approver clicks Review Request in channel
  2. Modal opens showing: full SQL, risk analysis, EXPLAIN output (if available)
  3. Approver selects Approve or Reject, adds optional comment
  4. Request state updates → channel message updates → thread reply posted

Additional interactions:

ButtonAction
ResumeConfirm re-dispatch of a stalled request
View ResultShow execution results in a modal (truncated; use CLI for full output)

⚠️ SQL content shown in the Review Modal and execution results displayed via View Result are transmitted through Slack’s API servers. If your SQL or query results contain sensitive data, consider using CLI-only approval workflows instead.

Self-service user provisioning via /dbward join. Requires [slack.onboarding] to be enabled.

1. User types /dbward join
2. System checks for existing account or pending request
3. Modal opens: role selection, group selection, reason
4. User submits → request stored (status=pending, expires_at calculated)
5. Notification posted to approval channel with Review Request button
6. Admin clicks Review Request (requires user.write permission)
7. Admin modal: all roles (incl. restricted), groups, approve/reject
8a. Approve → user created atomically + API token delivered via DM
8b. Reject → rejection notice sent via DM

⚠️ The API token is delivered via Slack DM. This means the token passes through Slack’s servers. For environments requiring end-to-end confidentiality, consider delivering tokens through a separate secure channel.

[slack.onboarding]
enabled = true
assignable_roles = ["requester", "dba", "approver"]
assignable_groups = ["backend-team", "dba-team"]
restricted_roles = ["admin"]
request_ttl_hours = 72
FieldDefaultDescription
enabledfalseEnable /dbward join
assignable_rolesRoles shown to applicants
assignable_groups[]Groups shown to applicants
restricted_roles[]Hidden from applicants, available to admins during review
request_ttl_hours72Hours before pending request auto-expires

A background worker checks every 60 seconds for expired requests. When a request expires:

  • Status set to expired
  • Applicant receives a DM (“request expired — run /dbward join again”)
  • Channel message updated to ”⏰ Expired”
IssueSolution
No notifications sentVerify [slack] is configured, bot token is valid, channel ID is correct
not_in_channel errorInvite bot: /invite @dbward or add channels:join scope
Signature verification failedEnsure signing secret matches; check server clock (±5 min tolerance)
Button click errorVerify Interactivity URL: {server}/api/slack/interactions
”Account not linked”Run dbward user update <user> --slack-user-id <SLACK_UID>
/dbward not recognizedRegister slash command in Slack App settings pointing to {server}/api/slack/commands
”No databases available”User needs request.query or request.dml permission
Onboarding button does nothingEnsure [slack.onboarding] enabled = true

Run dbward-server validate --config server.toml --preflight to diagnose configuration and Slack API connectivity issues.