Skip to main content
A refund above the desk limit should be answered in the channel where the support lead already lives. WebhookApprovalProvider sends the request to your Slack service as one signed POST; your service turns the button click into a signed POST back. This recipe runs the inbound half in process, with the real signing and the real handler, so what a Slack service must send is shown exactly.

The policy

runnable

The code

runnable file=main.py

What the agent sees

The answer names the request, the hash the human saw, the decision and the approver; the approver is what the receipt records. The signature is an HMAC-SHA256 over timestamp.body on the exact bytes, and a timestamp outside the five-minute window is refused even with the right secret.

The receipt

runnable
approve/committed, approver slack:dana. The same shape as an approval given with ctrlrun approve, because it went through the same call.

When an AMBIGUOUS appears

Approvals never make an effect ambiguous; the remote does. If the approved refund’s reply is lost, the effect is AMBIGUOUS and the approval is already spent: resolve the effect with ctrlrun resolve refund:txn_5 --committed or --failed. On --failed a retry needs a new approval, because the old one authorized one execution.

Next