dejwcake/craftable
Craftable is an admin panel and CRUD generator for Laravel that scaffolds management screens, forms, and data tables with authentication and permissions built in, so you can ship back-office tools without repetitive boilerplate.
This package sits on top of spatie/laravel-permission and is version-locked to the same line as dejwcake/admin-auth (both 2.1.0 now target spatie/laravel-permission ^8.3).
composer.json pins spatie/laravel-permission to ^7, this release will not install — you must upgrade that package in the same change. composer why-not spatie/laravel-permission ^8.3 will show you what's holding it back.spatie/laravel-permission ^8.3, dejwcake/admin-auth 2.1.0, and this package 2.1.0. Do them in one branch so you only run the migration/verification pass once.AGENTS.md / CLAUDE.md — new in this release and the fastest way to get an AI pair-programmer oriented to the conventions.$user->hasPermissionTo(...) returns true in Tinker. That single loop exercises the config, the cache, and the guard wiring.Role matrix in a seeder, permissions in code. Define role names and their permission sets in a seeder (idempotent via firstOrCreate/syncPermissions), and reference permissions in middleware and policies by name. This keeps authorization declarative and re-runnable on every deploy.
Use enums for role names. With the v8 upgrade, findByName() / findOrCreate() accept BackedEnum|string. Pass a UserRole::Admin enum rather than a magic string — it gives you static analysis coverage on permission checks and removes a whole class of typo bugs.
$user->assignRole(UserRole::Admin);
$user->hasPermissionTo(Permission::PostsEdit);
Guarding routes. Use the package's middleware aliases (role:, permission:, role_or_permission:) on route groups rather than scattering abort_unless calls in controllers. Reserve explicit Gate::authorize / policy checks for per-record authorization.
Custom Role / Permission models. If you implement the contracts yourself (common when you add team_id or extra columns), this is the one place the upgrade can break your code — see Gotchas.
Deployment. Add php artisan permission:cache-reset to your deploy script after migrations and seeders. The permission cache is the single most common source of "it works locally" bugs in this ecosystem.
Dist installs are now lean. .gitattributes excludes tests, CI, and QA configs from the archive. If you vendor-patch this package, use --prefer-source (or a path repository) so you retain the test suite for verification.
This is a transitive major bump, and it is a hard blocker. The version constraint is ^8.3, not ^7.4|^8.3. Nothing in this package's code changed — the risk is entirely in the spatie upgrade and in whatever else in your app depends on spatie v7. Treat it as a breaking change for your application and schedule it deliberately, not as a patch bump.
Custom contract implementations will fatal-error at runtime, not install time. If you implement Spatie\Permission\Contracts\Role or Permission, update the signatures to accept BackedEnum|string:
public function findByName(BackedEnum|string $name, ?string $guardName = null): RoleContract;
public function findOrCreate(BackedEnum|string $name, ?string $guardName = null): RoleContract;
Composer will happily install; you'll only find out when a role lookup runs. Grep for findByName and findOrCreate in your app/ before you merge.
Cache is per-guard and survives deploys. After changing role/permission definitions, run php artisan permission:cache-reset. In tests, clear the cache in setUp or use RefreshDatabase plus an explicit reset — stale cache across test methods causes flaky, order-dependent failures.
Seeders must be idempotent. With an ^8.3 upgrade you'll likely re-run seeders against existing data. firstOrCreate + syncPermissions (not givePermissionTo, which accumulates) keeps repeat runs safe.
Debugging checklist: php artisan permission:cache-reset → check config/permission.php guard names match your auth guards → php artisan tinker and inspect $user->getAllPermissions() → verify the role is attached to the correct guard. Guard mismatch is the second most common failure after cache.
Extension points to prefer: custom Role/Permission models via the config file, a PermissionRegistrar-aware service provider for cache invalidation on model events, and policies for row-level rules. Avoid re-implementing the role hierarchy inside controllers.
CI/QA context is for maintainers, not consumers. PHPMD 3, coverage on the pgsql job, and MariaDB 12.3 in docker-compose describe the package's own pipeline — you don't need to mirror them, but they're a reasonable signal of what the maintainers test against (Postgres and MariaDB both first-class).
How can I help you explore Laravel packages today?