Overview
Company business data is isolated at company or organization level, as described below. IAM also supports clients under an organization. Each selected company or client has aniam_scopes row, used as Spatie’s team ID. Authentication and
profile switching can run before a scope has been selected.
Clients do not automatically gain access to company business packages. Their
guards are client-api and client-agent, with an explicit permission catalog.
IAM roles and permission pivots use scope_id; company business tables keep
company_id. Profiles and assignments have exactly one company or client owner.
See IAM overview for the shared access model.
Hierarchy
- An Organization groups multiple companies under one umbrella (e.g., a holding company)
- A Company is the core business unit. It can be a main company (parent) or a branch (child)
- Some data (like the product catalog and assets) is shared at the organization level — all companies in the same organization see the same products
- Other data (like orders, customers, stock) is scoped to the company level — each branch has its own
How tenancy is enforced
1. JWT Token carries the context
After a company human selects a profile, the JWT token encodes:2. Middleware resolves the tenant
Theexowpee.teams middleware (registered by the IAM package) runs on every protected route and:
- Reads the JWT token
- Resolves the selected
company_idorclient_idandorganization_id - Sets the tenant context for the request
- Configures Spatie’s permission team system using the matching IAM scope
exowpee.company or exowpee.client.
3. Queries are automatically scoped
Models use the resolved tenant context to scope queries:4. Policies check ownership
Authorization policies verify that the requested resource belongs to the user’s current organization/company:Data scoping by level
Why organization-level sharing?
For businesses with multiple branches, the product catalog should be the same everywhere. A “Samsung Galaxy A54” in the Cotonou branch is the same product in the Porto-Novo branch. But each branch manages its own stock levels, orders, and customers independently.Switching companies
A user can belong to multiple companies through different UserProfiles. To switch context:company_id and organization_id.
Helper functions
Exowpee provides global helpers to access the current tenant context anywhere in the code:packages/shared/src/Helpers/helpers.php and app/Helpers/helpers.php.
For developers
When writing new code:- Always scope queries by
company_idororganization_id - Always check ownership in policies
- Never assume a single company — the system is multi-tenant
- Use the
company()andgetTeamOrganization()helpers instead of hardcoding IDs - Write migrations with
company_idororganization_idcolumns on any tenant-specific table