›
byrcsc/laravel-approval · 1.x
Inspect, repair, escalate, verify, and maintain approvals through Artisan.
Every command that takes a request accepts its public ULID or its numeric key. People copy the ULID from a URL and the key from a query, so both forms work.
| Command | Purpose | Schedule |
|---|---|---|
approval:escalate | Apply each overdue stage's escalation policy | Required |
approval:delegations | Move assignments as delegation windows open and close | Required for future windows |
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:escalatephp artisan approval:escalateFinds stages whose deadline has passed and applies each stage's escalation policy. Nothing escalates unless this command runs, so schedule it:
Schedule::command('approval:escalate')->everyFifteenMinutes();The sweep is idempotent. The interval sets how soon after a deadline the command notices it, and does not affect correctness. Each stage runs in its own transaction, so one misconfigured stage cannot stop the others. If a stage's strategy throws, that stage rolls back entirely and the next run retries it.
Reports escalations, reminders, newly stranded stages, and failures. Exits non-zero if any stage's strategy threw, so a scheduler that watches exit codes reports the failure. See SLAs and escalation.
approval:delegationsphp artisan approval:delegationsMoves assignments to delegates when a standing delegation window opens, and back to approvers when it closes. Granting, revoking, and stage activation already move assignments, so this command only matters for windows that open or close later:
Schedule::command('approval:delegations')->everyFifteenMinutes();The command is idempotent. The interval sets how soon after a window opens or closes the command moves assignments. Each stage runs in its own transaction.
Reports how many assignments moved. When the delegations migration has not run, it prints a warning and exits zero.
approval:verifyphp 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 action or attachment that fails verification. Reports findings and never repairs them. Exits non-zero when it finds anything, or when the named request does not exist.
approval:doctorphp 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. Nobody can finish these stages, and no other part of the engine reports them. Exits non-zero when it finds any.
Found 1 stranded approval stage.
01JBK7QK5X8ZW2F0T3D9M4NA6E ... Directors: 1 living / 2 requiredFix them with delegation, reassignment, or a resync.
approval:statusphp artisan approval:status --limit=10| Option | Default | Meaning |
|---|---|---|
--limit | 10 | How many requests to list under each heading |
Prints a count per request state, then lists the requests that need attention under these headings:
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:syncphp 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. The
command applies additive and supported configuration changes. It refuses to
remove or reorder existing stages or approvers. A refusal aborts the whole sync
before it writes anything.
Exits non-zero when anything was refused. See workflow definitions.
approval:resyncphp 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. Use it when an approver has left and their requests are stuck.
Resync never runs automatically, because rebuilding a live request's
assignments is a decision a person makes. --operator is required, and the
command records the operator on the audit trail. Shell history does not record
who ran a command. --operator 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.
use Illuminate\Support\Facades\Schedule;
Schedule::command('approval:escalate')->everyFifteenMinutes();
Schedule::command('approval:delegations')->everyFifteenMinutes();
Schedule::command('approval:doctor')->hourly();
Schedule::command('approval:verify')->dailyAt('03:00');approval:escalate is required for deadlines to have any effect.
approval:delegations is required when standing delegations start or end in
the future. approval:doctor and approval:verify are checks that signal a
problem with a non-zero exit. Send their failures to the same place as your
other scheduler failures.