Locality
Locality is the core context management mechanism in Retail API. It identifies the current request’s organization, advisor, and household, then restricts data access accordingly.
Purpose
Section titled “Purpose”- Identify current context - Determine which organization/advisor/household the request operates on
- Reduce permission resolution overhead - Avoid recalculating accessible IDs for every operation
Locality Hierarchy
Section titled “Locality Hierarchy”Federation └── Organization └── Advisor └── HouseholdLocality Types
Section titled “Locality Types”| Type | Inheritance | Purpose |
|---|---|---|
UserLocality | Locality | Default when no route parameters present |
AdvisorLocality | Locality | Advisor context, no impersonation support |
ImpersonatableAdvisorLocality | AdvisorLocality | Supports team collaboration impersonation |
HouseholdLocality | ImpersonatableAdvisorLocality | Household context |
OrganizationLocality | Locality | Organization context, cannot get advisor |
FederationLocality | Locality | Federation context |
Code location: retail-api/app/Locality/
Context Initialization
Section titled “Context Initialization”Context is initialized from route parameters via InitializeLocality middleware. See Locality Middleware for details.
Resolution priority in LocalityManager::initializeLocalityFromRoute():
federationparameter →FederationLocalityadvisor+householdparameters →HouseholdLocalityadvisorparameter →ImpersonatableAdvisorLocalityorganizationparameter →OrganizationLocality- No parameters →
UserLocality
Route parameters use encrypted IDs:
// retail-api/app/Locality/Services/LocalityManager.php:323$id = Crypt::decryptId($encrypted_id);Access Restrictions
Section titled “Access Restrictions”Models under Household
Section titled “Models under Household”| Operation | Restricted to |
|---|---|
| Read | context organization/advisor/household |
| Write | context household only |
Models under Advisor (excluding Household sub-models)
Section titled “Models under Advisor (excluding Household sub-models)”| Operation | Restricted to |
|---|---|
| Read | context organization/advisor |
| Write | context advisor only |
Models under Organization
Section titled “Models under Organization”Access restricted to context organization.
Key Methods
Section titled “Key Methods”LocalityManager
Section titled “LocalityManager”// Get current contextLocalityManager::getAdvisor();LocalityManager::getHousehold();LocalityManager::getOrganization();
// Temporarily switch householdLocalityManager::switchHousehold($household, function() { // Uses new household context within this closure});
// Temporarily switch entire localityLocalityManager::switchLocality($locality, function() { // ...});
// Ignore license status checkLocalityManager::switchIgnoreLicenseStatus(true, function() { // ...});Code location: retail-api/app/Locality/Services/LocalityManager.php
Team Collaboration (Impersonation)
Section titled “Team Collaboration (Impersonation)”Advisors can impersonate other advisors on the same team:
// retail-api/app/Locality/ImpersonatableAdvisorLocality.php:130-135match ($login_user->type) { UserType::ADVISOR => ( $login_user->id === $advisor->id || in_array($advisor->id, AdvisorPolicy::getReadableIdsForDependent(), true) ) || throw new AccessDeniedHttpException(...),};Permission is checked via AdvisorPolicy::getReadableIdsForDependent().
Important Notes
Section titled “Important Notes”Context Advisor ≠ Login Advisor
Section titled “Context Advisor ≠ Login Advisor”The advisor parameter in the route may be an impersonated advisor, not necessarily the logged-in user.
Context Source
Section titled “Context Source”Context comes entirely from route parameters. If the route has no organization/household parameter, calling getHousehold() will throw LogicException.
OrganizationLocality Limitations
Section titled “OrganizationLocality Limitations”OrganizationLocality cannot retrieve an Advisor. Calling getAdvisor() throws an exception.
Sources
Section titled “Sources”- Notion: LocalityManager
retail-api/app/Locality/Services/LocalityManager.phpretail-api/app/Locality/*.php