Skip to content

Release v2.0.0 - #10

Merged
mikaelpopowicz merged 2 commits into
masterfrom
release/v2.0.0
Jul 27, 2026
Merged

mikaelpopowicz merged 2 commits into
masterfrom
release/v2.0.0

Conversation

@mikaelpopowicz

@mikaelpopowicz mikaelpopowicz commented Jul 26, 2026 •

Copy link
Copy Markdown
Contributor

A correctness, quality and tooling overhaul of bbs-lab/nova-permission. The existing general/granular permission features (which were partly broken in 1.x) now actually work, the package is modernized to PHP 8.2+ / Nova 4 & 5 / spatie-permission 6, and it gains a full test suite, PHPStan level 8, Pint and GitHub Actions CI. This is not a feature release — the permission model already existed; v2.0.0 fixes and hardens it.

Warning

Breaking release. See Upgrading at the bottom and UPGRADE.md.

Breaking changes

  • Requires PHP ^8.2, Laravel Nova ^4.0 || ^5.0, spatie/laravel-permission ^6.0.
  • Package migrations are now real .php files that auto-run on php artisan migrate (the .php.stub publish step is gone); only spatie's migration is published.
  • The gate_cache config key is replaced by an opt-in cache section (disabled by default).
  • The base Policy methods now return ?bool.

Fixed

  • Granular (per-instance) permissions now work. They shipped in 1.x but were effectively dead: the migration only added the authorizable/group columns and never replaced spatie's unique(name, guard_name), so a same-name per-instance permission could not be created; and Authorizations::scopeAuthorize() filtered against a hardcoded chambers.id column left over from another project. Now a composite unique index on (name, guard_name, authorizable_id, authorizable_type) (explicit, MySQL-safe name) + a dynamic scope.
  • Permission builder search filters as you type (debounced + loading state); it previously did nothing.
  • Correct permission/role class resolution, per-model cache invalidation, and hardened request/controller handling. The workbench boots again and the front-end no longer spins forever on a failed request.

Changed

  • Gate cache is now opt-in and centralized (config('nova-permission.cache.enabled'), default false); was always-on via gate_cache.
  • Documentation rewritten (Requirements, granular-permission guide, caching, Testing); the workbench is now a manual test harness + demo (seeded admin/writer/reader roles, Post + Service resources for general vs granular, Nova impersonation).

Added

  • Full test suite (Pest, 100% line coverage, mutation, architecture tests), PHPStan level 8, Pint, a CI matrix (Nova 4 & 5 × Laravel 11–13 × PHP 8.3–8.5) and Dependabot.

Upgrading from 1.x

  1. Bump to PHP ^8.2 and spatie/laravel-permission ^6.
  2. On your authenticatable model use BBSLab\NovaPermission\Traits\HasRoles (not Spatie's) and implement CanOverridePermission — the policies call hasPermissionToOnModel(), which only exists on the package trait. (This was already required in 1.x; it is now documented.)
  3. Run php artisan migrate (package migrations apply automatically). The new composite unique index replaces spatie's unique(name, guard_name); existing rows are unaffected.
  4. If you extend the base Policy, keep overrides typed Model $model and returning ?bool.
  5. Replace any gate_cache config with the new opt-in cache section.

Copilot AI review requested due to automatic review settings July 26, 2026 19:34
@cursor

cursor Bot commented Jul 26, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Release v2.0.0 of bbs-lab/nova-permission, adding granular (per-instance) permissions + an optional gate cache, tightening policy/contract typing, and substantially raising the project quality bar with full Pest coverage and CI automation.

Changes:

  • Added instance-scoped (“authorizable”) permissions with an instance-override rule, plus query-level scopeAuthorize() support.
  • Introduced an optional, config-driven permission/gate cache (nova-permission.cache.*) with invalidation hooks.
  • Added comprehensive Pest test suite + CI workflows (tests matrix, Pint, PHPStan L8, mutation tests) and refreshed workbench/demo.

Reviewed changes

Copilot reviewed 87 out of 103 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
workbench/routes/web.php Redirect / to Nova for the workbench app.
workbench/database/seeders/DatabaseSeeder.php Seed demo users/roles and add granular-permissions demo data.
workbench/database/migrations/2024_06_14_091717_create_services_table.php Add services table for the demo resource.
workbench/database/factories/UserFactory.php Add factory for seeded/test users.
workbench/database/factories/ServiceFactory.php Add factory for Service demo model.
workbench/database/factories/PostFactory.php Add factory for Post demo model.
workbench/config/view.php Add strict_types.
workbench/config/session.php Add strict_types.
workbench/config/services.php Add strict_types.
workbench/config/queue.php Add strict_types.
workbench/config/permission.php Workbench Spatie config tweaks + imports cleanup.
workbench/config/nova.php Adjust impersonation redirects to /nova.
workbench/config/nova-permission.php Workbench config updated to new cache shape + imports.
workbench/config/mail.php Add strict_types.
workbench/config/logging.php Add strict_types.
workbench/config/hashing.php Add strict_types.
workbench/config/filesystems.php Add strict_types.
workbench/config/database.php Workbench DB config improvements + MySQL SSL constant compatibility.
workbench/config/cors.php Add strict_types.
workbench/config/cache.php Add strict_types.
workbench/config/broadcasting.php Add strict_types.
workbench/config/auth.php Add strict_types and import-based model binding.
workbench/config/app.php Add strict_types.
workbench/app/Providers/NovaServiceProvider.php Register Nova routes correctly for Nova 4/5.
workbench/app/Policies/ServicePolicy.php Add policy for new Service demo model.
workbench/app/Nova/Service.php Add Nova resource for Service with abilities mapping.
workbench/app/Nova/Resource.php Minor typing/import cleanup for Scout query docs.
workbench/app/Models/User.php Use package HasRoles, add factories + impersonation support.
workbench/app/Models/Service.php Add demo model implementing authorizations.
workbench/app/Models/Post.php Add factories + generic return annotation for relation.
workbench/app/Http/Middleware/HandleInertiaRequests.php Doc/import cleanup for Response typing.
tests/Unit/PermissionCacheTest.php Add unit tests for PermissionCache wrapper.
tests/TestCase.php Add Testbench base testcase, migrations + Nova resource registration.
tests/Pest.php Configure Pest to use the package TestCase.
tests/Feature/ToolAndProviderTest.php Add coverage for tool boot, provider hooks, and branches.
tests/Feature/SmokeTest.php Add basic boot/schema/index-name regression coverage.
tests/Feature/ScopeAuthorizeTest.php Add query-scope tests for instance-override semantics.
tests/Feature/OverrideTest.php Add tests for override-role (“super admin”) behavior.
tests/Feature/NovaResourcesTest.php Add coverage for resource trait auth + package resources/policies.
tests/Feature/ModelTest.php Add coverage for authorizable relation + cache invalidation.
tests/Feature/HttpApiTest.php Add coverage for API controllers, middleware, and validation.
tests/Feature/GranularPermissionTest.php Add end-to-end granular permission behavior tests.
tests/Feature/GenerateResourcePermissionsTest.php Add generator action/command coverage.
tests/Feature/GeneralPermissionTest.php Add general (model-wide) permission behavior tests.
testbench.yaml Enable package provider + adjust workbench settings.
src/Traits/HasRoles.php Add instance memoization, general-vs-scoped permission resolution, cache wrapper.
src/Traits/Authorizations.php Implement scopeAuthorize() matching instance-override semantics.
src/Traits/Authorizable.php Switch gate check caching from Cache facade to PermissionCache wrapper.
src/Support/PermissionCache.php Add config-driven cache wrapper for gate/permission checks.
src/Resources/Role.php Typing/docs improvements and override-permission UI hook.
src/Resources/Permission.php Typing/docs improvements and conditional MorphTo for authorizables.
src/Policies/Policy.php Tighten signatures/return types to ?bool and improve typing.
src/PermissionBuilder.php Add return type for translation loader.
src/NovaPermissionServiceProvider.php Auto-run migrations + typed model binding for resources.
src/Models/Role.php Minor typing/docs cleanup.
src/Models/Permission.php Add authorizable relation typing + cache invalidation via PermissionCache.
src/Http/Requests/PermissionRequest.php Add rules return typing doc.
src/Http/Requests/PermissionByGroupRequest.php Add rules return typing doc.
src/Http/Requests/PermissionByAuthorizableRequest.php Add rules return typing doc.
src/Http/Requests/AttachRequest.php Add rules return typing doc + refine property type doc.
src/Http/Middleware/Authorize.php Import-based typing/doc cleanup.
src/Http/Controllers/PermissionController.php Fix null checks, orphan handling, and add stronger typing.
src/Contracts/Role.php Simplify contract and update mixin typing.
src/Contracts/Permission.php Add authorizable + serialization contract methods.
src/Contracts/HasAuthorizations.php Add generic return typing for authorizations relation.
src/Actions/GenerateResourcePermissionsAction.php Switch to updateOrCreate using new composite uniqueness semantics.
resources/js/stores/permission.ts URL handling + robustness for fetch/generate flows.
resources/js/pages/Tool.vue Debounced search UX + spinner + stable keys.
resources/js/helpers/client.ts Guard against missing Axios response on network errors.
resources/js/components/PermissionGroup.vue Re-fetch permissions on search and improve error handling.
README.md Major documentation rewrite (granular permissions, caching, upgrading).
ray.php Remove Ray config from repo/workbench sync.
phpstan.neon.dist Raise PHPStan to level 8 and target relevant paths.
dist/css/tool.css Rebuilt compiled tool CSS for updated UI.
database/migrations/add_override_permission_to_roles_table.php Add override_permission flag to roles table.
database/migrations/add_authorizable_and_group_to_permissions_table.php.stub Remove old stub migration approach.
database/migrations/add_authorizable_and_group_to_permissions_table.php Add authorizable + group columns and fix MySQL index name length.
config/permission.php Package Spatie config defaults pointing to package models.
config/nova-permission.php New cache config shape + clarified comments.
composer.json Update supported versions + add scripts for analysis/coverage/mutation + dev deps refresh.
.styleci.yml Remove StyleCI config.
.scrutinizer.yml Remove Scrutinizer config.
.gitignore Update ignored paths for build/auth/cache artifacts.
.github/workflows/update-changelog.yml Add release-triggered changelog automation.
.github/workflows/run-tests.yml Add CI test matrix for Nova/Laravel/PHP and enforce 100% on primary job.
.github/workflows/run-mutation-tests.yml Add mutation testing workflow.
.github/workflows/phpstan.yml Add PHPStan workflow.
.github/workflows/code-style.yml Add Pint workflow.
.github/dependabot.yml Add Dependabot config for composer/actions/npm.
.gitattributes Exclude dev/test/workbench sources from Composer package export.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Resources/Role.php
Comment on lines +23 to +27
/**
* @extends resource<Model>
*
* @property-read string $guard_name
*/
Comment on lines +22 to +26
/**
* @extends resource<Model>
*
* @property-read string $guard_name
*/
Comment on lines +4 to 10
use Laravel\Nova\Actions\ActionResource;
use Workbench\App\Nova\Post;

return [
'authorizable_models' => [
\Workbench\App\Nova\Post::class,
Post::class,
],
Comment on lines +106 to +112
const searching = ref<boolean>(false)
const commitSearch = _.debounce((value: string) => {
store.setSearch(value)
store.data().finally(() => {
searching.value = false
})
}, 500)
@mikaelpopowicz
mikaelpopowicz force-pushed the release/v2.0.0 branch 2 times, most recently from ea4c9b0 to bb91385 Compare July 27, 2026 06:57
Modernize the package to the bbs-lab quality bar (Pint, PHPStan level 8,
100% test coverage, mutation, GitHub Actions CI) and fix several real
permission bugs surfaced while writing the tests.

Breaking changes:
- Require PHP ^8.2, Laravel Nova 4 & 5, spatie/laravel-permission ^6.
- Your authenticatable model must use BBSLab\NovaPermission\Traits\HasRoles
  (not Spatie's) and implement CanOverridePermission.
- Package migrations are now real .php files that auto-run on `migrate`
  (no publish step); only spatie's migration must be published.
- The base Policy methods now return ?bool.

Highlights:
- General vs granular (per-instance) permissions with a clear instance-override
  rule; Authorizations::scopeAuthorize() mirrors it for index filtering.
- Optional, config-driven gate cache (disabled by default).
- Permission builder search (debounce + loader); impersonation-ready workbench
  that doubles as a manual test harness and usage demo.

See the pull request description for the full changelog.
- Resources/Permission, Resources/Role: use `@extends \Laravel\Nova\Resource<Model>`
  in the class docblock. Pint's phpdoc_types had lowercased it to `resource`,
  which reads as the PHP `resource` keyword and is fragile for PHPStan generic
  inference; the fully-qualified form is correct and survives formatting.
- Tool.vue: guard the permission-builder search spinner with a monotonic token
  so a slower earlier request can no longer clear it while a newer, still
  in-flight search is running. Rebuilt dist/.

(The third review point — registering Service in the workbench's
authorizable_models — was already addressed in the release commit.)
@mikaelpopowicz
mikaelpopowicz merged commit 912f502 into master Jul 27, 2026
9 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants