Audience: admins, support engineers, internal developers Difficulty: intermediate
What this covers
Every Spatie permission on the parent app (50 keys) and every Solabooks permission (261 keys, grouped by namespace), with the middleware, policy, or Blade directive that enforces each.
Parent app — Spatie permissions (guard web)
Defined inline in database/seeders/DatabaseSeeder.php. Permissions are
checked through the standard Spatie pipeline (@can, @hasrole, route
middleware role:/permission:, and policy classes in app/Policies).
Admin-side (24)
| Permission | Enforced by | Notes |
|---|---|---|
create-admin, edit-admin, view-admin, delete-admin |
AdminController, app/Policies/AdminPolicy.php |
Manage User rows with admin role |
create-project, edit-project, view-project, delete-project |
ProjectController, app/Policies/ProjectPolicy.php |
Central projects table |
create-client, edit-client, view-client, delete-client |
ClientController |
Tenant client rows |
create-plan, edit-plan, view-plan, delete-plan |
PlanController |
Bundle plans |
create-project-plan, edit-project-plan, view-project-plan, delete-project-plan |
Admin/AdminProjectPlanController |
Per-project tier CRUD |
create-client-subscription, edit-client-subscription, view-client-subscription, delete-client-subscription |
Admin/AdminSubscriptionController |
Subscription rows |
Client-side (26)
| Permission | Enforced by | Notes |
|---|---|---|
create-organization, edit-organization, view-organization, delete-organization |
Client/ClientOrganizationController, app/Policies/OrganizationPolicy.php |
Workspace orgs |
access-organization, access-all-organizations |
SetClientContext middleware |
Org switcher |
create-team-member, edit-team-member, view-team-member, delete-team-member |
Client/ClientUserController |
Org members |
manage-organization-projects |
Client/Portal/... |
Project enable/disable |
assign-project-users, access-project, access-all-projects |
Client/ClientOrganizationProjectUserController |
Project-level membership |
manage-client-settings |
Client/SubscriptionController etc. |
Tenant-level settings |
assign-roles, manage-user-roles |
RoleController (super-admin), ClientUserPermissionController |
Role assignment |
manage-subscriptions |
Client/SubscriptionController |
Self-serve billing |
view-reports, export-data |
client dashboard, beta-report exports | Coarse |
Roles → permission map (parent)
| Role | Permission set |
|---|---|
super-admin |
every Spatie permission |
admin |
none assigned in seeder; configurable per deployment |
client_owner |
all 26 client-side perms (24 in $clientPermissions, plus manage-subscriptions, manage-client-settings) |
client_manager |
16 of the client perms — no assign-roles, manage-subscriptions, manage-client-settings |
client_member |
5 view-only perms |
The user_organizations.role column is a separate string field used by
SuperAdminProvisioningSeeder and is not the same as the Spatie
client_owner role on the user. Both must be present for full access.
Solabooks app — permission keys (config/finance_permissions.php)
261 keys total, grouped by namespace. Enforcement is done by route
middleware perm:<key> (alias for EnsureFinancePermission),
controller authorize() calls, policies in app/Policies/*, and Blade
@can directives. Most pages also have a feature flag — see
plan-feature-matrix.
org.* (4) — Organizations & membership
| Key | Description | Enforced |
|---|---|---|
org.view |
View organizations and membership | global side-nav |
org.manage |
Create or update organizations | Settings/OrganizationController |
org.select, org.switch |
Select / switch active organization | ResolveActiveOrganization middleware |
setup.* (2) — Setup wizard
| Key | Description |
|---|---|
setup.view |
View finance setup wizard |
setup.edit |
Complete finance setup wizard steps |
settings.* (16) — Settings hub
| Key | Description |
|---|---|
settings.view, settings.manage |
Top-level settings |
settings.currencies.{view,manage} |
Currency table |
settings.exchange_rates.{view,manage} |
FX rates (gated on multi_currency_enabled) |
settings.sequences.{view,manage} |
Document numbering |
settings.pdf_templates.{view,manage} |
PDF templates (gated on pdf_templates_enabled) |
settings.workflow.{view,manage} |
Approval routes (gated on workflow_enabled) |
settings.taxes.{view,manage} |
Tax settings (gated on vat_enabled) |
accounts.* (7) — Chart of accounts
| Key | Description | Policy |
|---|---|---|
accounts.view, accounts.create, accounts.edit, accounts.delete |
CRUD | – |
accounts.change_type, accounts.add_opening_balance, accounts.subtypes.manage |
Restricted ops | – |
journals.* (9) — Journal entries
| Key | Description | Policy |
|---|---|---|
journals.view, journals.create, journals.edit_draft, journals.delete |
CRUD | JournalEntryPolicy |
journals.post, journals.reverse, journals.restore |
Lifecycle | JournalEntryPolicy |
journals.delete_hard, journals.trash |
Hard delete + trash | JournalEntryPolicy |
transactions.* (3) — Generic transaction rules
transactions.create, transactions.edit_draft, transactions.delete_hard.
sales.* (28)
sales.invoices.{view,create,edit_draft,send,delete,post,unpost,void} (8) —
InvoicePolicy.
sales.receipts.{view,create,edit_draft,delete,post,void} (6) —
SalesReceiptPolicy.
sales.credit_notes.{view,create,edit_draft,delete,post,void,apply,unapply} (8) —
CreditNotePolicy.
sales.refunds.{view,create,edit_draft,delete,post} (5) —
RefundReceiptPolicy.
sales.payments.{view,create,post,reverse,delete} (5) — PaymentPolicy.
quotes.* (7), sales_orders.* (7)
Full CRUD + approve + convert + cancel. Policies: QuotePolicy,
SalesOrderPolicy. sales_orders.* requires sales.use_sales_orders
feature.
purchase_orders.* (10), purchases.* (32)
| Group | Keys |
|---|---|
purchase_orders.* (10) |
view, create, edit, delete_draft, approve, send, receive, convert_to_bill, close, cancel |
purchases.bills.* (9) |
full lifecycle + allocate, download |
purchases.bill_payments.* (6) |
full lifecycle |
purchases.debit_notes.* (8) |
full lifecycle + apply, unapply |
purchases.expenses.* (6) |
full lifecycle |
purchases.refunds.* (5) |
full lifecycle |
Policies: PurchaseOrderPolicy, BillPolicy, DebitNotePolicy,
PaymentPolicy.
payments.* (6) — Generic payments
payments.{view,create,post,unpost,repost,delete}. Used by both AR and AP
where the polymorphic payment service is invoked. Policy: PaymentPolicy.
banking.* (15)
| Sub-namespace | Keys |
|---|---|
banking.accounts |
view, manage |
banking.reconciliation |
view, start, finalize, lock, reopen |
banking.import |
view, upload, commit |
banking.templates, banking.rules |
view, manage (each) |
Policies: BankReconciliationPolicy, BankStatementImportPolicy. Most
require bank_reconciliation_enabled feature.
tax.* + vat_returns.* + reports.vat.* (16)
tax.{view,apply,edit_rate,archive}, tax.codes.{view,manage},
tax.rates.{view,manage}, tax.reverse_charge,
vat_returns.{view,create,finalize,post_reporting,settle,carry_forward},
reports.vat.view. Gated on vat_enabled (and reverse_charge_enabled
for tax.reverse_charge).
inventory.* + price_lists.* + customer_groups.* + pricing_rules.* (22)
| Group | Keys |
|---|---|
inventory.units |
view, manage |
inventory.categories |
view, manage |
inventory.items |
view, manage |
price_lists |
view, create, edit, delete, manage_product_prices, override_prices |
customer_groups |
view, create, edit, delete |
pricing_rules |
view, create, edit, delete |
customers.*, vendors.*, suppliers.*, supplier_categories.* (8)
Each has view + manage. vendors and suppliers are aliases of the
same controller.
reports.*, dimensions.* (7)
reports.{view,export}, reports.vat.view,
dimensions.{view,manage,assign,create_value}.
periods.*, recurring.*, tasks.*, users.* (15)
| Group | Keys |
|---|---|
periods |
view, lock, unlock, close, reopen, generate |
recurring |
view, create, edit, pause, runs.view |
tasks |
view, manage |
users |
view, manage, view_audit_log |
fixed_assets.* (13)
view, create, edit, delete, post, reverse, approve,
dispose, transfer, depreciate, categories.{view,manage},
reports.view. Gated on tracker.fixed_assets.
Cross-cutting (mileage.*, landed_costs.*, comments.*, custom_fields.*, custom_views.*, api.*, workflow_rules.*, timesheets.*, fx_adjustments.*) (29)
Each has its own view / create / manage* triplet. See the source
file for the full label text.
Roles → permission set (Solabooks, FinanceRolePermissionSet)
Defined in database/seeders/FinanceRolePermissionSetSeeder.php. Used by
the perm: middleware (which consults FinanceRolePermissionSet, not
the Spatie permissions table on the user).
role_key |
Strategy | Notes |
|---|---|---|
owner |
All 261 perms true |
Tenant owner |
manager |
All true except a deny-list of system/legal/period ops (org.manage, users.manage, settings.manage, setup.edit, tax.edit_rate, tax.archive, accounts.{change_type,delete,archive}, periods.{unlock,reopen}, sales/purchase order approval/cancel, fixed_assets.{delete,reverse}, plus all *delete_permanently*/*delete_hard*) |
Day-to-day administrator |
member (Accountant) |
Default-deny; allow prefixes sales., purchases., payments., journals., banking., vat_returns., reports., suppliers., vendors., customers., supplier_categories., tasks. (excluding hard-deletes); plus a curated memberAllowExact list; minus a memberAlwaysDeny list |
Bookkeeper |
approver |
Default-deny except fixed_assets.{view,approve,reports.view,categories.view} |
Single-purpose approver |
A separate Spatie admin role (one role only) is also seeded by
RolePermissionSeeder and gets every guard_name='web' permission. This
role is what RoleMiddleware:admin checks for the admin/* shell.
Middleware aliases (app/Http/Kernel.php)
| Alias | Class | Purpose |
|---|---|---|
perm |
EnsureFinancePermission |
Per-permission gate; reads FinanceRolePermissionSet |
feature |
EnsureFinanceFeatureEnabled |
Per-feature gate; reads feature_flags table + config/finance_features.php defaults |
finance.owner |
EnsureFinanceOwner |
owner role-key only |
external.api |
EnsureExternalApiAccess |
API scope check on api/v1/* |
parent.role, parent.permission |
EnsureParentRole, EnsureParentPermission |
Used when finance route needs central-app role/perm rather than tenant-DB one |