Skip to content

feat(authz): install Bouncer and establish baseline RBAC#35

Merged
ibourgeois merged 1 commit into
mainfrom
codex/10-bouncer-rbac
Apr 10, 2026
Merged

feat(authz): install Bouncer and establish baseline RBAC#35
ibourgeois merged 1 commit into
mainfrom
codex/10-bouncer-rbac

Conversation

@ibourgeois
Copy link
Copy Markdown
Contributor

Closes #10\n\nSummary:\n- Installs Bouncer and adds the Bouncer database tables\n- Marks the User model as role-aware\n- Seeds baseline admin and user roles\n- Adds a centralized admin gate and a protected admin route\n- Adds Pest coverage for baseline role seeding and route protection\n\nValidation:\n- vendor/bin/pint --dirty --format agent\n- php artisan test --compact\n- npm run build

Copilot AI review requested due to automatic review settings April 10, 2026 10:19
@ibourgeois ibourgeois merged commit 8aa9636 into main Apr 10, 2026
5 checks passed
@ibourgeois ibourgeois deleted the codex/10-bouncer-rbac branch April 10, 2026 10:24
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds baseline role-based authorization (RBAC) using Silber Bouncer, including database tables, role-aware users, initial role seeding, an admin-only route, and feature tests to validate seeding and access control.

Changes:

  • Install silber/bouncer and add Bouncer tables migration.
  • Make User role/ability-aware and seed baseline admin/user roles.
  • Add an access-admin gate + /admin route protected by auth + can:access-admin, with Pest coverage.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
composer.json Adds Bouncer dependency.
composer.lock Locks Bouncer package version and dependencies.
database/migrations/2026_04_10_101826_create_bouncer_tables.php Introduces Bouncer RBAC tables.
app/Models/User.php Adds Bouncer role/ability trait to the User model.
database/seeders/DatabaseSeeder.php Seeds baseline admin and user roles.
app/Providers/AppServiceProvider.php Defines centralized admin gate logic (Gate::before, access-admin).
routes/web.php Adds /admin route protected by auth and can:access-admin.
tests/Feature/Auth/RbacTest.php Adds feature tests for role seeding and admin-route protection.

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

public function boot(): void
{
//
Gate::before(function (User $user): ?bool {
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

Gate::before callbacks are invoked with at least ($user, $ability, $arguments) by Laravel. This closure only accepts User $user, which will trigger an ArgumentCountError when the gate runs. Update the signature to accept the ability (and optionally arguments), e.g. function (User $user, string $ability, array $arguments = []): ?bool or use a variadic/ignored parameter.

Suggested change
Gate::before(function (User $user): ?bool {
Gate::before(function (User $user, string $ability, array $arguments = []): ?bool {

Copilot uses AI. Check for mistakes.
Comment on lines +70 to +73
Schema::drop(Models::table('permissions'));
Schema::drop(Models::table('assigned_roles'));
Schema::drop(Models::table('roles'));
Schema::drop(Models::table('abilities'));
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

down() uses Schema::drop(...) which will error if a table is already missing (e.g. partial rollbacks, manual cleanup). Other migrations in this repo use dropIfExists, so these should too (still in reverse dependency order).

Suggested change
Schema::drop(Models::table('permissions'));
Schema::drop(Models::table('assigned_roles'));
Schema::drop(Models::table('roles'));
Schema::drop(Models::table('abilities'));
Schema::dropIfExists(Models::table('permissions'));
Schema::dropIfExists(Models::table('assigned_roles'));
Schema::dropIfExists(Models::table('roles'));
Schema::dropIfExists(Models::table('abilities'));

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +15

$user = User::where('email', 'test@example.com')->first();

expect($user)->not->toBeNull();
expect($user?->isAn('admin'))->toBeFalse();
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

This test doesn't actually assert that the baseline admin and user roles were created; it only checks that the seeded test@example.com user exists and isn't an admin. Consider asserting the roles exist in the database (and ideally that they are unique / idempotent) so the test directly covers the role-seeding behavior described in the title.

Suggested change
$user = User::where('email', 'test@example.com')->first();
expect($user)->not->toBeNull();
expect($user?->isAn('admin'))->toBeFalse();
$this->artisan('db:seed')
->assertExitCode(0);
$user = User::where('email', 'test@example.com')->first();
expect($user)->not->toBeNull();
expect($user?->isAn('admin'))->toBeFalse();
expect(\Illuminate\Support\Facades\DB::table('roles')->where('name', 'admin')->count())->toBe(1);
expect(\Illuminate\Support\Facades\DB::table('roles')->where('name', 'user')->count())->toBe(1);

Copilot uses AI. Check for mistakes.
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.

feat(authz): install Bouncer and establish baseline RBAC

2 participants