Actions & Post-Decision Flows
Audience: Control authors, security engineers, compliance officers Time: ~10 min
Post-decision actions run after a control evaluates a request. They do not change the allow/deny outcome — they add operational side-effects: notifications, approvals, audit events, and integrations.
Action types reference
| Type | Trigger | What it does |
|---|---|---|
audit_log | Any | Writes a structured decision record to the Control Core audit trail |
notification | Any | Sends an alert via Slack, Teams, PagerDuty, or email |
webhook | Any | POSTs a payload to any HTTPS endpoint |
siem_log | Any | Forwards a structured event to Splunk, QRadar, or any SIEM |
approval_gate | on_allow | Pauses the request and requires human approval before it proceeds |
break_glass_notify | on_deny | Notifies on-call when a user requests emergency override access |
policy_trigger | Any | Activates a secondary control or workflow |
Supported triggers
| Trigger | Fires when… |
|---|---|
on_allow | The control decision is Allow |
on_deny | The control decision is Deny |
on_mask | The control applies a masking transformation |
on_error | An evaluation error occurs |
always | After every evaluation regardless of outcome |
Canonical action shape (JSON)
{
"type": "<action_type>",
"trigger": "<trigger>",
"enabled": true,
"config": {
"destination_ref": "<configured-destination-id>",
"credential_ref": "<credential-reference>"
}
}
Actions use references to destinations and credentials configured in Settings → Action Destinations — raw credentials are never stored inside a control. The Action Destinations page is the single source of truth for endpoint URLs, encrypted credentials, connection tests, and per-environment status badges that appear in the wizard.
Examples
audit_log — always write a decision record
{
"type": "audit_log",
"trigger": "always",
"enabled": true,
"config": {
"destination_ref": "control_core_audit",
"level": "info",
"message": "Decision for {{subject.id}} on {{resource.name}}: {{decision}}"
}
}
Best practice: Add an
audit_logaction to every control. It provides decision traceability without affecting request flow.
siem_log — forward denials to Splunk or QRadar
{
"type": "siem_log",
"trigger": "on_deny",
"enabled": true,
"config": {
"destination_ref": "splunk_hec",
"credential_ref": "siem_prod_token",
"severity": "high",
"event_type": "control_decision"
}
}
Recommended fields to include in SIEM events:
- Trigger and decision outcome
- Control name and version
- Resource path and method
- Environment and Bouncer ID
webhook — call an external API
{
"type": "webhook",
"trigger": "on_deny",
"enabled": true,
"config": {
"url": "https://hooks.example.com/control-event",
"method": "POST"
}
}
Webhook dispatch is asynchronous with a bounded request timeout. Use always only for low-cost telemetry endpoints to avoid adding latency.
notification — alert via Slack or Teams
{
"type": "notification",
"trigger": "on_deny",
"enabled": true,
"config": {
"destination_ref": "slack_security_channel",
"message": "Access denied: {{subject.id}} attempted {{action}} on {{resource.name}}"
}
}
Best practices:
- Use
on_denyfor actionable security alerts - Prefer role/group recipients over individual-only routing
- Use
alwayssparingly to avoid alert fatigue
Supported channels: in-app, Slack, Teams, PagerDuty, email.
approval_gate — pause and require human approval
{
"type": "approval_gate",
"trigger": "on_allow",
"enabled": true,
"config": {
"destination_ref": "approval_queue",
"approver_role": "security_manager",
"ttl_minutes": 30,
"reason_required": true,
"notify_destination_ref": "slack_security_channel"
}
}
approval_gate pauses request execution. The request only proceeds after an approver with the configured role approves it via the Controls → Approval Inbox or Settings → Approval Gates.
Full approval gate field reference
| Field | Type | Default | Description |
|---|---|---|---|
destination_ref | string | approval_queue | Approval queue destination profile |
approver_role | string | policy_manager | Role required to approve |
ttl_minutes | number | 30 | Minutes before auto-expiry |
reason_required | boolean | true | Approver must provide decision notes |
notify_destination_ref | string | — | Channel for approval notifications |
quorum | number | 1 | Required approvals (1 = single approver) |
escalation_enabled | boolean | false | Enable auto-escalation on timeout |
escalation_role | string | — | Secondary approver role |
escalation_after_minutes | number | 60 | Minutes before escalation triggers |
Fields omitted from a control's action config fall back to tenant-wide defaults configured in Settings → Approval Gates → Gate Configuration.
For admin configuration and queue management, see Approval Gates Admin Guide.
Rollout guidance (to avoid breaking flows):
- First deploy with
audit_log+notificationonly — verify approver receives the notification - Test the full approval loop in sandbox: request → notification → approve → confirm request proceeds
- Enable
approval_gateonly after routing is validated - Start with narrow scope (one endpoint or user group) before expanding
Troubleshooting: Requests blocked after adding approval gate?
- Check pending approvals in Controls → Approval Inbox and Settings → Approval Gates
- Confirm
approver_rolematches an existing role in your platform- Verify
notify_destination_refis configured so approvers are notified- For escalation, quorum, and TTL troubleshooting, see Troubleshooting Controls
break_glass_notify — emergency override path
{
"type": "break_glass_notify",
"trigger": "on_deny",
"enabled": true,
"config": {
"destination_ref": "break_glass_bridge",
"notify_channels": "email,siem",
"require_reason": true,
"ttl_minutes": 15
}
}
Pair break_glass_notify with audit_log on on_deny so every emergency access attempt produces a decision record for audit.
Troubleshooting: Break-glass path still fails after notification?
- Verify
destination_refandnotify_channelsdestination refs exist and are active in Settings → Integrations- Confirm TTL and reason requirements are documented in your runbook and communicated to users who need emergency access Full reference: Troubleshooting Controls
Safe staged rollout pattern
For high-impact controls (approval gates, break-glass, hard denies on critical paths):
Stage 1: audit_log (always) + notification (on_deny) → Confirm routing
Stage 2: Enable approval_gate in sandbox, narrow scope → Validate loop
Stage 3: Promote to production in narrow scope → Monitor audit logs
Stage 4: Expand scope → Confirm no disruption
Configuring destinations and credentials
Destinations and credentials are configured in two separate admin surfaces — never inside individual controls:
| Destination type | Configure in | What lives there |
|---|---|---|
webhook_generic, api_gateway, workflow_router, policy_engine, approval_queue, break_glass_bridge, SIEM | Settings → Action Destinations | Profile-based delivery (single endpoint per profile) and the SIEM forwarder |
Email, Slack, Microsoft Teams, PagerDuty, ServiceNow, generic Webhook (referenced as channel:<id>) | Settings → Notifications | Channel CRUD with per-channel auth, severity thresholds, and the delivery-log retry pipeline |
This separation gives you:
- Multiple controls sharing the same destination or channel
- Credential rotation without editing individual controls
- Centralised audit of outbound integration activity (per-table)
- Per-environment routing (sandbox / production) and severity-based filtering for notification channels
- Connection testing from the UI before deploying a control that depends on the destination
See the Action Destinations administrator guide for the destination-profile setup and SIEM, and the Notifications & Alert Channels guide for channel CRUD, custom alert rules, and the delivery log.
Troubleshooting
| Symptom | Check |
|---|---|
| Action did not fire | BOUNCER_ENABLE_POST_DECISION_ACTIONS=true in Bouncer config; trigger matches decision outcome |
| Webhook timeout | Use async/low-latency endpoint; avoid always trigger on high-traffic controls |
| Notification not delivered | For notification / email actions, check Settings → Notifications → Delivery Log; for webhook / siem_log actions, check Settings → Action Destinations profile config and credentials |
| Approval gate blocking all requests | approver_role is set and approver can access Approval Inbox |
Full: Troubleshooting Controls