# `Cairnloop.Workers.ApprovalResumeWorker`
[🔗](https://github.com/szTheory/cairnloop/blob/main/lib/cairnloop/workers/approval_resume_worker.ex#L1)

Oban worker that re-validates a governed tool approval before it can proceed to execution.

This is the Phase 15 deliverable: the "stale-plan" re-validation gate (Terraform semantics).
An approval valid at decision time is re-checked against the CURRENT policy/scope at resume
time before transitioning to `:execution_pending`.

## Branch Logic

The resume worker is enqueued by `Governance.approve/3`, which has already transitioned the
lane to `:approved`. It therefore acts on `:approved` approvals (the documented state axis:
`:approved → resume → :execution_pending`). A still-`:pending` lane (awaiting an operator
decision) is a no-op — re-validation must never bypass the approval gate.

1. `nil` approval (deleted) → `:ok` — idempotent no-op.
2. `:approved` + `expires_at < now` → `:expired` + `:expired` event (lazy guard, D15-12).
3. `:approved` + re-validation pass → `:execution_pending` + `:revalidation_passed` event.
   STOP — does NOT call `run/3` (Phase 16 seam, D15-10).
4. `:approved` + re-validation fail → `:invalidated` + `:revalidation_failed` event with
   humanized reason (fail-closed, APRV-03).
5. Any other status (`:pending`, `:rejected`, etc.) → `:ok` — idempotent no-op.

## Idempotency

`unique: [period: :infinity, keys: [:approval_id]]` prevents double-enqueue (D15-09).
`perform/1` re-checks status so a duplicate job is a true no-op.

## Telemetry

`:approval_transition` event emitted AFTER the `with` pipeline succeeds (D-29).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
