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.
| Command | Purpose | Schedule |
|---|---|---|
approval:escalate | Apply each overdue stage's escalation policy | Required |
approval:verify | Walk the audit trail's hash chains | Recommended |
approval:doctor | Find stranded stages | Recommended |
approval:status | Summarize state and list what needs attention | On demand |
approval:sync | Reconcile version-controlled workflow definitions | On deploy |
approval:resync | Rebuild a live request's approver assignments | On demand |
approval:escalate
php artisan approval:escalateFinds 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| Argument | Optional | Meaning |
|---|---|---|
request | yes | Verify 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.
approval:doctor
php artisan approval:doctor --limit=50| Option | Default | Meaning |
|---|---|---|
--limit | 50 | Maximum 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 requiredFix them with delegation, reassignment, or a resync.
approval:status
php artisan approval:status --limit=10| Option | Default | Meaning |
|---|---|---|
--limit | 10 | How 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 agoNothing 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| Option | Meaning |
|---|---|
--dry-run | Preview 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 / option | Required | Meaning |
|---|---|---|
request | yes | The request ULID, or its numeric id |
--operator | yes | A key of the configured user model, or type:id |
--prune | no | Also 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:9See 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.