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-Signatureheader 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 thev0=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.