Database
Laravel Access creates four tables.
access_permissions
Stores permission definitions.
id
name
label
description
created_at
updated_ataccess_roles
Stores reusable role definitions.
id
name
label
description
is_global
created_at
updated_ataccess_role_permissions
Connects roles to permissions.
role_id
permission_idaccess_assignments
Assigns a role or direct permission to an actor, globally or in a scope.
id
actor_type
actor_id
role_id
permission_id
scope_type
scope_id
created_at
updated_atExactly one of role_id or permission_id should be present.
Unique Assignments
The assignments table has separate unique indexes for role assignments and direct permission assignments:
actor_type, actor_id, role_id, scope_type, scope_id
actor_type, actor_id, permission_id, scope_type, scope_idThis prevents duplicate assignments for the same actor and scope.
Global Rows
Global rows have no scope:
scope_type = null
scope_id = nullScoped rows store both scope columns:
scope_type = App\Models\Company
scope_id = 1Scope Scaffold Tables
The optional access:scope command generates additional application tables such as:
companies
company_members
company_invitations
users.current_company_idThose tables are not Laravel Access authorization tables. They represent membership, invitations, and current scope state for your app.
Laravel Access still stores permissions, roles, and assignments in the access_* tables. A common company setup writes to both systems:
$company->users()->attach($user, ['role' => CompanyRole::Admin->value]);
$user->in($company)->assignRole(CompanyRole::Admin);The membership row says the user belongs to the company. The access assignment says the user has the Admin authorization role inside that company.