QueryProxy

Approving SQL queries from Slack and Teams, safely

How to approve production SQL from Slack or Teams without weakening the control, covering signatures, replay protection, tokens and identity mapping.

4 min read

You can approve production SQL from Slack or Teams safely if the button is not trusted on its own. A click is only an HTTP callback, so the safety lives in what the server checks before it acts: who signed it, how old it is, whether it answers a real message, and which person it maps to. That is where chat approvals usually go wrong, and where QueryProxy spends its effort.

Why approve in chat at all?

Because a queue nobody opens is a queue that blocks. A DBA already lives in chat, so the request arrives where they are, with the requester, the connection and a preview of the SQL, and they decide in place. The approval workflow is the same either way; chat only changes where the decision is taken.

What can go wrong with a chat button?

  • Forgery. Anyone who finds the callback URL can post to it.
  • Replay. A genuine approval, captured and sent again later.
  • Wrong person. A valid signature says the caller holds a secret. It does not say a particular person clicked.
  • A stale message. Someone decides a request twice from an old card.

How does Slack approval work in QueryProxy?

New requests are announced in a channel with Approve, Reject and Open in QueryProxy, and after a decision the message is updated so the buttons disappear. Setup is in the Slack integration guide. Each callback is verified before anything happens:

  • Signature. The X-Slack-Signature header must match the HMAC-SHA256 of the timestamp and raw body, signed with the app’s signing secret. Slack describes the scheme in its guide to verifying requests from Slack, including the v0= prefix. (Read on 2026-10-13.)
  • Replay window. Slack’s guide says to reject a request whose timestamp differs from local time by more than five minutes, and QueryProxy rejects requests outside plus or minus five minutes. (Read on 2026-10-13.)
  • Single-use token. Each button carries a token bound to one request, valid for 24 hours and spent on the first recorded decision. A click that is turned away by authorization does not use it up.
  • Identity. The Slack user must be mapped to a QueryProxy user with the DBA role in the request’s team. An administrator fills each reviewer’s Slack member ID, which is what ties a click to a person.
  • Rules. No self-approval, exactly as on the web.

A forged or expired callback is refused and changes no state.

Why is the secret administrator-only?

Because of what an HMAC can and cannot say. The guide is blunt about it: it proves the caller knows the secret, never that a particular person approved. If a DBA could choose the secret, they could sign a callback approving their own request in a colleague’s name, and the trail would record the colleague. So only a system administrator can set or rotate it, and rotating needs the current one.

What about Microsoft Teams?

Teams works differently, and it is worth being plain about it. QueryProxy posts a card for each new request with a Review in QueryProxy link, and announces decisions back to the channel. Approving from Teams happens through an action endpoint that your automation, such as a Power Automate flow or an outgoing webhook, calls with an HMAC-signed request. The approver is identified by an Azure AD object ID that an administrator has linked to a user. Full interactive card buttons, as in Slack, need a Teams bot registration and are on the roadmap.

If you want a click-to-approve flow in Teams today, you build it in your automation. If you do not want to, approve from the web.

Does the trail record chat decisions?

Yes: a decision is written to the audit log with its channel, so a reviewer can tell a web approval from a Slack one. See what a production query audit trail should record and the SOC 2 page for how that maps to evidence.

What are the limits?

A rejection from Slack records only a generic reason, so write a justification in the web UI when one matters. The SQL preview in a card is cut at 400 characters, and you can turn it off with QUERYPROXY_CHAT_INCLUDE_SQL=false if chat history is not a place you want statements to land. Buttons in messages posted before the single-use tokens were introduced no longer work.

Frequently asked

Can you approve a SQL query from Slack?
Yes. QueryProxy posts each new request to a channel with Approve, Reject and Open in QueryProxy actions. A click is verified, mapped to a QueryProxy user with the DBA role in that team, and subject to the same rules as the web, including no self-approval.
Does Teams have approve buttons?
Not as interactive card buttons yet; those need a Teams bot registration and are on the roadmap. Today QueryProxy posts a card with a Review in QueryProxy link and exposes an HMAC-signed action endpoint that a Power Automate flow or outgoing webhook can call.
What stops a forged or replayed approval?
Each callback is checked for a valid HMAC signature and a timestamp within five minutes. Each Approve or Reject also carries a single-use token, valid for 24 hours and bound to one request, so a captured call cannot be replayed and the secret alone cannot create a decision.
Can a chat approval be a self-approval?
Not for regular reviewers. The same rule as the web applies, and the approver must have the DBA role in the request's team. A system administrator can override both the DBA-role rule and the self-approval block, and an approval that does so is flagged in the audit log.
Should every approval happen in chat?
No. Chat is convenient for routine changes. For a request that needs a written justification, use the web UI, since a rejection from Slack records only a generic reason.
Share

Related posts

Arrow keys to move, Enter to open.