NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

The published config/approvals.php, comments trimmed:

use RoundlyConsulting\Approvals\Models\Approval;
use RoundlyConsulting\Approvals\Models\ApprovalDelegation;
use RoundlyConsulting\Approvals\Models\ApprovalRequest;
use RoundlyConsulting\Approvals\Models\ApprovalRequestStage;

return [
    'model' => Approval::class,
    'request_model' => ApprovalRequest::class,
    'stage_model' => ApprovalRequestStage::class,
    'delegation_model' => ApprovalDelegation::class,

    'key_type' => env('APPROVALS_KEY_TYPE', 'bigint'),

    'authorization' => [
        'enabled' => env('APPROVALS_AUTHORIZATION', false),
        'ability' => 'decide-approval',
    ],

    'exclusions' => [
        'resolver' => null,   // a ResolvesExcludedApprovers class — see Decision guards
    ],

    'fingerprint' => [
        'on_change' => env('APPROVALS_FINGERPRINT_ON_CHANGE', 'ignore'),
    ],

    'expiry' => [
        'default' => null,
    ],

    'workflows' => [
        // named presets — see Workflow presets
    ],
];

Every key

KeyDefaultEnvPurpose
modelApproval::class—Model for decisions. Must extend the package’s Approval.
request_modelApprovalRequest::class—Model for multi-approver requests. Must extend ApprovalRequest.
stage_modelApprovalRequestStage::class—Model for the stages of a staged request. Must extend ApprovalRequestStage.
delegation_modelApprovalDelegation::class—Model for delegations. Must extend ApprovalDelegation.
key_typebigintAPPROVALS_KEY_TYPEType of every polymorphic id column — bigint, uuid or ulid. Read by the migrations, so set it before you migrate; anything else throws InvalidConfigurationException.
authorization.enabledfalseAPPROVALS_AUTHORIZATIONGate every decision path — approve, reject, toggle, ask and cancel — through a Gate ability. The env strings true, 1, yes and on enable it, false, 0, no and off disable it, a blank value is not set (so false), and anything else throws InvalidConfigurationException.
authorization.ability'decide-approval'—The Gate ability checked against the approvable. Not set (null or blank) means decide-approval; a non-string value throws InvalidConfigurationException rather than checking a different gate.
exclusions.resolvernull—A ResolvesExcludedApprovers class naming the actors who may never decide on an approvable — its author, say — app-wide; resolved from the container. Null or blank is no resolver; anything that is not an implementation throws InvalidConfigurationException. See Decision guards.
fingerprint.on_change'ignore'APPROVALS_FINGERPRINT_ON_CHANGEWhat a decision on a round whose subject changed since it opened does — for subjects implementing ProvidesApprovalFingerprint: ignore records it, refuse throws ChangedApprovalSubjectException, void voids the round and throws. Blank is the default; anything else throws InvalidConfigurationException. Planned to default to refuse in the next major.
expiry.defaultnull—Lifetime in seconds (≥ 1) of an approval given without an explicit expiry; it stops counting once that passes. Not set (null or blank) means approvals never expire unless a decision sets its own; anything else that isn’t a positive whole number throws InvalidConfigurationException.
workflows[]—Named workflow presets. Not set (null or blank) means none; any other non-array value throws InvalidConfigurationException.

Environment

Three keys are env-backed:

APPROVALS_AUTHORIZATION=true
APPROVALS_KEY_TYPE=uuid
APPROVALS_FINGERPRINT_ON_CHANGE=refuse

APPROVALS_KEY_TYPE is read when the migrations run, not at runtime — set it before you migrate. It has to fit every model approvals stores a morph id for, including models another package owns (see Models & schema).

php artisan about

The package adds an Approvals section to php artisan about. It reports the gate ability by presence and the workflow presets by count, so your authorization vocabulary and business-process names never appear in the output:

php artisan about --only=approvals
RowShows
Model / Request model / Stage model / Delegation modelThe class name of each configured model.
AuthorizationENFORCED or OFF.
AbilityDEFAULT (not set — null or blank — or decide-approval), SET (a custom name, never printed) or INVALID.
Default expiryThe expiry.default value in seconds, e.g. 86400s — NEVER, or INVALID when the value would throw.
Workflow presetsThe number of presets, e.g. 2 defined — NONE, or INVALID when workflows is not an array.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.