PHPackages                             byrcsc/laravel-checklist - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. byrcsc/laravel-checklist

ActiveLibrary[Database &amp; ORM](/categories/database)

byrcsc/laravel-checklist
========================

Run versioned Laravel checklists from template authoring through completion and review, with evidence, scoring, reports, and a tamper-evident audit trail.

v1.0.0(today)00MITPHPPHP ^8.3CI passing

Since Aug 9Pushed todayCompare

[ Source](https://github.com/byrcsc/laravel-checklist)[ Packagist](https://packagist.org/packages/byrcsc/laravel-checklist)[ Docs](https://github.com/byrcsc/laravel-checklist)[ Fund](https://www.buymeacoffee.com/ryancatapang)[ RSS](/packages/byrcsc-laravel-checklist/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (19)Versions (2)Used By (0)

Laravel Checklist
=================

[](#laravel-checklist)

[![Latest Version on Packagist](https://camo.githubusercontent.com/e60707a946bc66950b41766dc58bd52a954d0599d3588ca7e926ed107634e8f1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6279726373632f6c61726176656c2d636865636b6c6973742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/byrcsc/laravel-checklist)[![GitHub Tests Action Status](https://camo.githubusercontent.com/a5f4b10218fa278cd095f589c45304b529452145638e0cbcd205faf36098aab4/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6279726373632f6c61726176656c2d636865636b6c6973742f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/byrcsc/laravel-checklist/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub PHPStan Action Status](https://camo.githubusercontent.com/fa5e86a953edadd19ad13797517feb72f542aaff847fb82a26994b8a419bc273/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6279726373632f6c61726176656c2d636865636b6c6973742f7068707374616e2e796d6c3f6272616e63683d6d61696e266c6162656c3d7068707374616e267374796c653d666c61742d737175617265)](https://github.com/byrcsc/laravel-checklist/actions?query=workflow%3APHPStan+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/db446d06c1439c308155d7d8248deb5aa581207d389c0d6ee082aceea256f341/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6279726373632f6c61726176656c2d636865636b6c6973742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/byrcsc/laravel-checklist)

Vehicle checks, site inspections, maintenance jobs, opening and closing routines: work that records answers to a fixed list of questions, and that somebody may have to account for months later.

Laravel Checklist runs that work from template authoring through completion and review, with evidence, scoring, reports, and a tamper-evident audit trail. Publishing a template freezes its questions, so a checklist answered last year still shows the questions it was actually asked.

The package supplies the engine and the Eloquent models. It has no user interface and registers no routes.

**[Read the documentation](https://docs.rcsc.dev/laravel-checklist/v1)** for the full reference. This README covers installation and the main flows.

LaravelTested PHP versions12.x8.3, 8.413.x8.3, 8.4Tested on MySQL and PostgreSQL.

Installation
------------

[](#installation)

```
composer require byrcsc/laravel-checklist
php artisan vendor:publish --tag="checklist-migrations"
php artisan migrate
```

Publish the configuration **before** migrating if you need custom table names or non-integer user identities:

```
php artisan vendor:publish --tag="checklist-config"
```

Notification wording publishes separately, and only if you want to change it:

```
php artisan vendor:publish --tag="checklist-translations"
```

Every configuration key is documented in [Configuration](https://docs.rcsc.dev/laravel-checklist/v1/configuration).

Key terms
---------

[](#key-terms)

A **template** publishes immutable **versions** holding **sections** and **items**. A **checklist** is one run of a version, optionally about a **subject** such as a vehicle. A **response** holds the answer to one item, and every change is recorded in an append-only **audit trail**.

[Key terms](https://docs.rcsc.dev/laravel-checklist/v1/introduction) covers the rest.

Item types
----------

[](#item-types)

The set below is fixed in v1. Validation settings live on the item, and each type decides how its answer is validated, stored, and scored.

TypeConfigStored asScore`checkbox`nonebooleanchecked `1`, unchecked `0``yes_no`nonebooleanyes `1`, no `0``pass_fail`nonebooleanpass `1`, fail `0``text``max_length`stringunscored`number``min`, `max`floatunscored`rating``min`, `max` (both required, `min` &lt; `max`)intnormalized from `0` to `1``date`none`Y-m-d` stringunscored`select``options`, `multiple`option value, or a list of themthe option's `score`, or their meanSingle and multiple select share one item type, separated by the `multiple`flag rather than by a type of their own.

An answer fails when its score is exactly `0`. The same definition decides whether the item-failed notification is sent and whether a critical item fails the checklist, so the two always agree. Unscored answers never fail, and an unanswered item is not a failed one.

> **Word yes/no questions so that the passing answer scores.** "Any body damage?" scores an undamaged vehicle at `0` and reports it as a failure, because the accurate answer is no. "Is the bodywork free of damage?" scores an undamaged vehicle at full weight. Nothing in the package enforces this. The scoring is correct either way; only the second question maps a good vehicle to a passing score.

Full details in [Items and sections](https://docs.rcsc.dev/laravel-checklist/v1/items-and-sections).

Quick start
-----------

[](#quick-start)

Author and publish a template with the builder. It validates the whole template before writing anything: rule targets must exist, branches must not be orphaned, and the section tree must stay inside the depth limit.

```
use ByRcsc\LaravelChecklist\Authoring\TemplateBuilder;

$version = TemplateBuilder::make('Vehicle pre-trip inspection')
    ->passThreshold(80)
    ->section('Exterior', function (TemplateBuilder $builder): void {
        $builder->passFail('Tires are roadworthy')->critical()->weight(2);
        $builder->passFail('No fluid leaks underneath')
            ->requireEvidenceWhen('fail', 'photo');
        $builder->yesNo('Bodywork is free of damage?');
    })
    ->section('Cabin', function (TemplateBuilder $builder): void {
        $builder->checkbox('Registration and insurance present');
        $builder->rating('Interior cleanliness', min: 1, max: 5);
    })
    ->publish();
```

Nothing is written until `publish()`, and it writes everything in one transaction. A template that fails validation leaves no rows behind.

To edit a published template, draft the next version:

```
$draft = $version->newDraft();   // deep copy as version N+1, lineage carried
$draft->items()->where(...)->first()->update(['label' => 'Reworded']);
$v2 = $draft->publish();         // version N is left exactly as it was
```

Give any model checklists:

```
use ByRcsc\LaravelChecklist\Concerns\HasChecklists;

class Vehicle extends Model
{
    use HasChecklists;
}
```

Run one:

```
$checklist = $version->start(subject: $vehicle, assignedTo: $driver);

$checklist->answer($item, 'fail');   // validated and cast by the item's type,
                                     // and auto-transitions to in_progress

$checklist->addEvidence($response, $uploadedFile, 'photo');  // via Storage

$checklist->submit();   // refuses while anything required is unanswered,
                        // reporting everything outstanding at once

$checklist->review($inspector, outcome: 'accepted');
```

A checklist moves through `pending`, `in_progress`, `completed`, and `reviewed`. The first answer starts it. You can reopen it from `completed` or `reviewed`, which clears the review and is recorded in the audit trail. Any other transition throws.

Work through a full run in the [Quick start](https://docs.rcsc.dev/laravel-checklist/v1/quick-start).

What the package does
---------------------

[](#what-the-package-does)

**[Rules](https://docs.rcsc.dev/laravel-checklist/v1/conditional-rules).** Two kinds, both written against the item whose answer decides them. Requirement rules (`requireEvidenceWhen()`, `requireNoteWhen()`) ask for more than an answer. They are reported when the answer is given and enforced at `submit()`. Visibility rules (`showWhen()`, `hideWhen()`) change which questions apply, and hiding a section hides everything inside it. If a show rule and a hide rule both apply, the item is hidden. Hidden answers and their evidence are kept and marked not applicable, so they are left out of scoring, progress, and completion checks. Reopen the branch and the earlier answer is still there.

**[Scoring](https://docs.rcsc.dev/laravel-checklist/v1/scoring).** Each scorable answer maps to a value from `0` to `1`, and each item can carry a weight. The checklist score is the earned weight divided by the weight of the items that applied, so a hidden question lowers the total the score is measured against instead of counting as a failure. Section scores and the total are calculated once at submission and stored, so a report run years later returns what was recorded then. A checklist with nothing scorable has no score at all, which is not the same as a score of `0`. A failed critical item fails the checklist whatever the score.

**[Evidence](https://docs.rcsc.dev/laravel-checklist/v1/answers-and-evidence).**Photos, files, and signatures attach to an answer and are written through Laravel Storage, with no media-library dependency. Each row records the disk, path, MIME type read from the file contents, size, SHA-256, and who captured it when. Files are stored under a new ULID, and extensions that a web server might execute are dropped. The package writes and deletes files. Your application decides who may see one and builds the URL.

**[Recurrence](https://docs.rcsc.dev/laravel-checklist/v1/recurring-schedules).**A schedule pairs a template with a frequency, a timezone, and optionally a subject and an assignee. Daily, weekly, monthly, and every-N-days are supported; iCal RRULE expressions are not. One command creates the checklists that are due:

```
Schedule::command('checklist:generate-due')->everyFifteenMinutes();
```

Each due date is calculated in the schedule's own timezone from its own `next_due_at`, so running the command late does not shift the schedule. However long the command has been down, a schedule creates at most one catch-up checklist.

**[Events and notifications](https://docs.rcsc.dev/laravel-checklist/v1/events-and-notifications).**Every transition fires an event, and each one implements `ShouldDispatchAfterCommit`, so it is safe to wrap a checklist operation in your own transaction. The package also ships mail and database notifications for every lifecycle event, which most engine packages leave to the application. They are included because an unassigned or overdue checklist usually needs someone told before it gets done. One `RecipientResolver` class decides who is notified, and turning the notifications off leaves the events running so you can send your own.

**[Audit trail](https://docs.rcsc.dev/laravel-checklist/v1/audit-history).**Every change is recorded in an append-only `checklist_actions` table, both per item and per checklist. Rows cannot be updated or deleted, and one class writes all of them. Each row's SHA-256 covers its own contents and the hash of the row before it, and the checklist stores the latest hash.

```
php artisan checklist:verify   # exits non-zero if any chain is broken
```

This detects an edited row, a deleted row, and a row inserted in the middle. It does not stop someone who can already write to the table: the hash uses no secret, so that person can recalculate the whole chain and verification will pass. Treat it as a strong check against mistakes and casual tampering, not as a cryptographic guarantee.

**[Export and reports](https://docs.rcsc.dev/laravel-checklist/v1/export-and-report).** The package generates no PDFs; it assembles the data and documents how to render it. `$checklist->toExport()` returns the whole checklist in reading order. Scores come from what was stored at submission and are never recalculated, and answers a branch set aside are included and flagged rather than dropped. Eleven query scopes and five reports read the stored results. `mostFailedItems()` groups by lineage ULID, so rewording a question does not restart its count.

**[Composing with sibling packages](https://docs.rcsc.dev/laravel-checklist/v1/composing-with-siblings).**This package depends on none of its siblings. `byrcsc/laravel-comments`, `byrcsc/laravel-approval`, and `byrcsc/laravel-assignment` attach through polymorphic relations for discussion, multi-stage sign-off, and assignment routing.

Not included in v1
------------------

[](#not-included-in-v1)

No user interface. No authorization, file URLs, or thumbnails. No PDF rendering, though the documentation includes a Blade and dompdf recipe. No threaded comments, assignment routing, or multi-stage approval; the sibling packages above cover those. No iCal RRULE recurrence. No repeatable sections, such as one copy per room. No custom item types, though the internal type handlers mean a public registry could open in a later minor release. No cached or materialized statistics tables.

Testing
-------

[](#testing)

```
composer test        # the suite
composer analyse     # PHPStan, level max
composer format      # Pint
```

The `workbench/` directory holds a demo application that installs the package the way a real application does and drives one checklist through every feature:

```
composer build                                   # migrate and seed from clean
php vendor/bin/testbench checklist:demo          # the whole engine, narrated
```

It exits non-zero if no notification was sent or an audit chain fails to verify, and CI runs it on every push. [`workbench/README.md`](workbench/README.md) lists what it seeds and which JSON routes it serves. It is the quickest way to see how an integration fits together before writing your own.

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for how to set up, the three checks every pull request must pass, where tests go, and what falls outside the package's scope. Everybody taking part is expected to follow the [Code of Conduct](CODE_OF_CONDUCT.md).

Security
--------

[](#security)

Please review [our security policy](SECURITY.md) on how to report security vulnerabilities. Do not open a public issue for one.

Credits
-------

[](#credits)

- [Ryan Catapang](https://github.com/byrcsc)
- [All Contributors](https://github.com/byrcsc/laravel-checklist/contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9258c643a563d82b6ae3f5b1c71158ed150c5bfd95ec48b52f837dbf8caf55d6?d=identicon)[rcscatapang](/maintainers/rcscatapang)

---

Top Contributors

[![rcscatapang](https://avatars.githubusercontent.com/u/60214290?v=4)](https://github.com/rcscatapang "rcscatapang (25 commits)")

---

Tags

laraveleloquentrecurrencetemplatesaudit-trailinspectionschecklistscoringevidence

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/byrcsc-laravel-checklist/health.svg)

```
[![Health](https://phpackages.com/badges/byrcsc-laravel-checklist/health.svg)](https://phpackages.com/packages/byrcsc-laravel-checklist)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[laravel/ai

The official AI SDK for Laravel.

1.1k4.6M293](/packages/laravel-ai)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k31.8M158](/packages/laravel-cashier)[spatie/laravel-backup

A Laravel package to backup your application

6.0k25.4M269](/packages/spatie-laravel-backup)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45844.8k1](/packages/pressbooks-pressbooks)[spatie/laravel-health

Monitor the health of a Laravel application

88212.7M185](/packages/spatie-laravel-health)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
