Browse documentationOpen

byrcsc/laravel-approval · 1.x

Console commands.

Every Artisan command the package ships, what each reports, its exit code, and which belong on a schedule.

Six commands ship with the package. All of them accept a request's public ULID or its numeric key wherever they take a request, because both end up in people's terminals — the first from a URL, the second from a query.

CommandPurposeSchedule
approval:escalateApply each overdue stage's escalation policyRequired
approval:verifyWalk the audit trail's hash chainsRecommended
approval:doctorFind stranded stagesRecommended
approval:statusSummarize state and list what needs attentionOn demand
approval:syncReconcile version-controlled workflow definitionsOn deploy
approval:resyncRebuild a live request's approver assignmentsOn demand

approval:escalate

php artisan approval:escalate

Finds stages whose deadline has passed and applies whatever each one's policy says. Nothing escalates without it:

Schedule::command('approval:escalate')->everyFifteenMinutes();

The sweep is idempotent, so the interval is a floor on how late "late" is noticed rather than a correctness knob. Each stage gets its own transaction, so one misconfigured stage cannot stop the rest from being handled; a stage whose strategy throws rolls back entirely and is picked up on the next run.

Reports escalations, reminders, newly stranded stages, and failures. Exits non-zero if any stage's strategy threw, so a scheduler watching exit codes says something. See SLAs and escalation.

approval:verify

php artisan approval:verify
php artisan approval:verify 01JBK7QK5X8ZW2F0T3D9M4NA6E
ArgumentOptionalMeaning
requestyesVerify one request, by ULID or id

Walks each request's hash chain and reports any line or attachment that no longer holds. Reports findings, never repairs. Exits non-zero when anything was found, or when the named request does not exist.

See audit trail and evidence.

approval:doctor

php artisan approval:doctor --limit=50
OptionDefaultMeaning
--limit50Maximum stranded stages to list

Finds pending stages whose living assignment holders can no longer meet the required approvals — the stages nobody can finish, which nothing else in the engine will report. Exits non-zero when any are found.

  Found 1 stranded approval stage.
  01JBK7QK5X8ZW2F0T3D9M4NA6E ... Directors: 1 living / 2 required

Fix them with delegation, reassignment, or a resync.

approval:status

php artisan approval:status --limit=10
OptionDefaultMeaning
--limit10How many requests to list under each heading

A count per request state, then the three lists that need attention:

  • Overdue — waiting on an approver past the deadline;
  • Stranded — living holders cannot meet the required approvals;
  • Conflicted — approved every stage, then found the record had changed.

Always exits zero. It is a report, not a check.

  State ............................ Requests
  pending .................................. 7
  approved ................................ 41
  …

  Overdue
  01JBK7QK5X… ......... Finance, due 3 hours ago

  Conflicted, waiting on a person
  01JBK2M9YB… ......................... 2 days ago

Nothing in the package resolves conflicted requests automatically — they stay open until an administrator reapplies or discards the draft.

approval:sync

php artisan approval:sync --dry-run
php artisan approval:sync
OptionMeaning
--dry-runPreview changes without writing them

Creates and reconciles the workflows declared in approval.definitions. Additive and supported configuration changes are applied; removing or reordering existing stages or approvers is refused, and a refusal aborts the whole sync before writing anything.

Exits non-zero when anything was refused. See workflow definitions.

approval:resync

php artisan approval:resync 01JBK7QK5X8ZW2F0T3D9M4NA6E --operator=42
php artisan approval:resync 91 --operator="App\Models\Staff:7" --prune
Argument / optionRequiredMeaning
requestyesThe request ULID, or its numeric id
--operatoryesA key of the configured user model, or type:id
--prunenoAlso drop approvers the workflow no longer names

Re-runs a pending request's approver rules against the current workflow. This is the runbook entry for "an approver left and their requests are stuck".

Deliberately a command rather than anything automatic: rebuilding a live request's assignments is a decision somebody makes. --operator is required and recorded on the audit trail — shell history is not attribution. It accepts a morph alias or a class name in the type:id form.

Prints the change per stage, exits non-zero when the request or operator cannot be resolved:

  Stage 1 .................................. +1 / -0
    + App\Models\User:9

See delegation and reassignment.

A workable schedule

use Illuminate\Support\Facades\Schedule;

Schedule::command('approval:escalate')->everyFifteenMinutes();
Schedule::command('approval:doctor')->hourly();
Schedule::command('approval:verify')->dailyAt('03:00');

The first is required for deadlines to mean anything. The other two are checks whose non-zero exit is the signal — route them wherever your scheduler's failures go.