ActionBoxBlog

SecurityPlatformSREDevOps

Policy exception management workflow: approve, expire, and audit

A copy-paste policy exception management workflow that records approvals, expiry, renewal, owners, and compliance evidence for deviations.

Every team deviates from policy sometimes: an emergency change skips review, a prod fix bends the change window, a customer promise bends the refund rule. The risk isn't the deviation — it's the unrecorded deviation, found by an auditor six months later with no context, no approver, and no expiry. A policy exception workflow makes each deviation a structured, time-bounded, signed record: who asked, what they bypassed, why, for how long, and who approved.

Policy exception management workflow: exceptions are borrowed time

StepWhat happensWhy it matters
RequestStructured: policy, deviation, reason, durationThe auditor can reconstruct intent
Approve/denyNamed approver, with the policy text visibleDeviations are decisions, not accidents
ExpireException auto-closes at its end dateNo exception outlives its justification
RenewNew request, new recordExtensions re-earn approval — nothing rolls over
AuditOne query lists every open exceptionYour compliance answer is a dashboard, not a spreadsheet

Step 1: the exception request is structured

A free-text "please allow this" thread is not a record. The request carries the policy, the deviation, and the justification up front:

bash
#!/usr/bin/env bash
# exception.sh — file a policy exception with the decision layer
set -euo pipefail

POLICY_ID="${1:?policy id}"
DEVIATION="${2:?what deviates from the policy}"
REASON="${3:?business justification}"
DURATION="${4:-30d}"
EXPIRES_AT=$(date -u -d '+72 hours' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date -u -v+72H '+%Y-%m-%dT%H:%M:%SZ')

actionbox ask \
  "Policy exception: ${POLICY_ID}" \
  --option approve="Approve for ${DURATION}" \
  --option deny="Deny — comply with the policy" \
  --context-json "[{\"type\":\"key_value\",\"items\":{\"policy\":\"${POLICY_ID}\",\"deviation\":\"${DEVIATION}\",\"reason\":\"${REASON}\",\"duration\":\"${DURATION}\",\"requested_by\":\"$(whoami)\"}}]" \
  --expires "$EXPIRES_AT" \
  --on-expire-json '{"type":"resolve","response":{"type":"single_choice","value":"deny"},"reason":"exception request expired"}' \
  --callback-url https://ops.acme.com/actionbox/exception-callback

The callback writes the approved exception into your register — with the decision id, so the "yes" is traceable to the approver and the reason.

Step 2: the approver sees the policy, not just the ask

An approver who can't see what they're overriding is signing blind. Attach the policy text to the request:

bash
actionbox ask \
  "Policy exception: ${POLICY_ID} (${DEVIATION})" \
  --option approve="Approve for ${DURATION}" \
  --option deny="Deny — comply with the policy" \
  --context-json "[{\"type\":\"key_value\",\"items\":{\"policy\":\"${POLICY_ID}\",\"policy_text\":\"Change windows: production changes require 48h prior approval. Emergency changes may proceed, but must be documented within 24h.\",\"deviation\":\"Change applied outside the window; retro-approval requested.\",\"reason\":\"${REASON}\",\"expires\":\"${EXPIRES_AT}\"}}]" \
  --expires "$EXPIRES_AT"

Now "approved" means the approver weighed the actual rule against the justification — and the exception record quotes the rule, so the file survives people leaving the company.

Step 3: expiry is the point

A policy exception without an end date is a permanent rewrite of the policy by a side door. Expiry is what keeps exceptions exceptional:

Use the Actionbox History/API view to find open exceptions whose expiry has passed, then cancel or resolve each Action by its ID. The CLI get command requires one Action ID; there is no actionbox list command in the current CLI surface.

The renewal is a new request: the exception does not roll over, and each extension re-earns an approver's signature. Audit evidence stays crisp — every open exception has a date it stops being true.

Full example: the compliance dashboard query

Use the dashboard History view or the documented user-scoped Actions API to review current exceptions by Source, owner, decision, and expiry. Keep the exception ID in your compliance register so renewal and revocation operate on the exact Action that was approved.

That list is your answer to "show me all current deviations from policy" — in an auditor's meeting, in one command, with the approval history one lookup away.

Why this beats "we've always done it that way"

  • Deviations become decisions — each one has a named approver and a recorded reason
  • Exceptions expire — nothing bypasses policy indefinitely by default
  • Renewals are visible — the same exception re-approved twice is a policy problem, now detectable
  • Audit is a query, not a scramble — open exceptions, owners, and dates on demand

Try it

  1. Install the CLI on your compliance or ops host
  2. Create a Source → ACTIONBOX_TOKEN
  3. Route exception requests through the ask pattern

Create a free Source · CLI + cron reference · Cron jobs that ask before acting · Refund approval workflow

Try this workflow in minutes

Create a free Source, then run the exact commands from this post against the live API — no approval infrastructure to build.

S
Suson Sapkota

Founder, Actionbox