dgtlss/clearance
Clearance is a lightweight Laravel package for simple, expressive access control. Define permissions and check authorization with clean, readable code, integrating smoothly with Laravel’s gates and policies while keeping authorization logic organized and easy to maintain.
Clearance is a Laravel access-control guard: it verifies that the access configuration in your working tree still matches the approved state recorded in clearance.lock.json. v1.0.1 is a security patch — the v1.0.0 gate could be bypassed by a PR that widened access, regenerated its own lock, and then passed clearance:check.
composer require --dev <vendor>/clearance:^1.0.1
php artisan clearance:check
- uses: actions/checkout@v4
with:
fetch-depth: 0 # required: the trusted ref must exist locally
- run: php artisan clearance:check --baseline=origin/main
clearance.lock.json in any PR that touches access rules, and at the baseline_ref / lock_changed fields in the JSON output when a check fails.First real use case: a contributor opens a PR that broadens a role or permission. Without --baseline the widened lock self-certifies; with it, the check compares against origin/main's lock, refuses to let the PR's own approvals override it, and fails with exit code 3 if the baseline is missing or invalid.
PR gate (the primary pattern). Fetch full history, then verify against the destination branch:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: php artisan clearance:check --baseline=origin/${{ github.base_ref }}
Using github.base_ref keeps the trusted ref correct for release branches and monorepos with protected trunks.
Same command locally, before pushing. Keep local and CI behaviour identical so failures are not surprises:
git fetch origin main
php artisan clearance:check --baseline=origin/main
Add it to a Composer script (composer check) alongside Pint/PHPStan so it runs in the same loop developers already use.
Run it alongside Warden and Advisor, not instead of them. Those integrations retain checkout-lock behaviour after the upgrade; they do not inherit the Git baseline. In PR CI the sequence should be: Warden/Advisor → clearance:check --baseline=….
Machine-readable reporting. The JSON output carries baseline_ref and lock_changed, so you can post a PR comment or annotate a check run distinguishing "lock changed in this PR, needs review" from "verification failed". Treat lock_changed: true as a reviewer trigger even when the exit code is 0.
Lock updates as deliberate, reviewed changes. When access genuinely should change, regenerate the lock in a dedicated commit/PR so the CODEOWNERS rule on clearance.lock.json, the workflow file, and the verification config produces a required code-owner review. Never let CI auto-commit a regenerated lock back into the PR that triggered it.
Monorepos. The baseline comparison handles monorepo paths and symlink redirection (both covered by regression tests in this release), but the fetch-depth: 0 requirement still applies to the whole repo — don't scope the checkout to a subdirectory unless your baseline ref resolves.
--baseline, v1.0.1 keeps the old checkout-lock behaviour for backwards compatibility. If you only bump the version and change nothing else, you are still exposed. Audit every workflow that invokes clearance:check and add the flag.3, not 1. actions/checkout defaults to fetch-depth: 1, so origin/main is unresolvable and the check aborts. Make sure your CI failure handling distinguishes 3 (missing ref / missing or invalid baseline lock — usually an infrastructure problem) from a genuine verification failure. A blanket || exit 1 will mask the difference in logs.origin/main exists but main may not, and HEAD~1 is meaningless. Prefer explicit remote-tracking refs and derive the branch from the PR target rather than hardcoding main when you also use develop/release/*.clearance:check is a gate, not a formatter. It will not rewrite the lock for you. Regeneration is a separate action; committing the result is a separate, reviewed step.clearance.lock.json, .github/workflows/*, and the verification config — plus required code-owner review — is what makes the baseline meaningful. A PR that can edit the workflow can simply drop the --baseline flag.3: verify git rev-parse --verify origin/main succeeds inside the job, confirm the baseline ref was pushed to the remote (not just fetched locally), and check the lock file actually exists at that commit.How can I help you explore Laravel packages today?