Customer Admin Component¶
Overview¶
The customer_admin component is a component that manages everything related to company administrators (admins) at
Alan. It provides a centralized, country-agnostic interface for handling admin user management across Alan's
multi-country platform (France π«π·, Belgium π§πͺ, Spain πͺπΈ and Canada π¨π¦/global).
Purpose¶
This component was created to:
- Centralize admin management logic - Consolidate scattered admin-related code into a single, dedicated component
- Provide a unified interface - Abstract away country-specific implementations behind a common API
- Support multi-entity hierarchies - Handle complex relationships between accounts, companies, and operational scopes
- Manage admin permissions - Track admin responsibilities and access rights across different entities
Core Concepts¶
Admin Types¶
Admins are categorized by their level of access:
- Account Admin - Has access to all companies within an account
- Company Admin - Has access to specific companies only
- Operational Scope Admin - Has access to specific operational scopes within companies
π Operational scope admin have further access restrictions: they cannot access pro dashboard pages like the admin management, contracts or invoices pages.
This corresponds to the three types of entities:
- Account - Top-level organization unit - defines the Alan x customer relationship
- Company - Mid-level unit (belongs to an account) - mostly defined by the contractual setup mostly (= contracts' are tied to a company)
- Operational Scope - Lowest level unit (belongs to a company) - not all customers use this level, it's used to accommodate customers' more complex needs
π Most of the component API is designed to operate in a specific account context to best match users mental model (both customers and Alaners).
AdminedEntitiesForest¶
A hierarchical tree structure representing all entities an admin has access to:
- Contains both direct admin relationships and transitive relationships
- Account admins automatically have access to all companies in their account
- Efficient querying of admin permissions across entity hierarchies
Note: Forest wording is used to flag that an admin might be admin in several accounts which translated to several indepdendant trees.
This data structure contains 2 kind of nodes:
- context_account: regroups all entities of a given account as children = under a single tree
- entity: corresponds to a specific entity the user is admin of (either directly or transitively)
Admin Responsibilities¶
Note
β οΈ This is FR specific for now and should be replaced at some point with a finer grained access control model. Admins can have different responsibilities for different entities and these only impact the emails received (= all admins get full admin dashboard access, except scope admins): - The plan is to not fully support responsibilities in the global code for now, and directly go for the finer grained access control model, to then migrate FR to that. Rationale: existing responsibilities are confusing admins as they expect responsibilities to limit access to the different part of the pro dashboard.
contract_manager- Manages contractspeople_manager- Manages people/employeespayroll_manager- Manages payrollinvoice_manager- Manages invoiceswellbeing_referent- Wellbeing responsibilities
AccountOrgTreeQueryApi¶
This is a global API that abstract away the country-specific data model of the accounts entity setup = which company is
linked
to which account and which operational scope is linked to which company.
This allows customer_admin component to avoid directly relying on each country Account, Company and OperationalScope
models by instead relying on the dependency inversion pattern (CustomerAdminDependency interface implemented in each
country)
The main data structure returned by this API is AccountOrgTree which is a tree structure of all the entities in a
given account. This is particularly useful for admin rights business logic as admin rights are transitive (ex: an
account admin is also admin of all the companies in that account)
Architecture¶
Current state¶
Warning
π§ The component is an ongoing work. As of Jan 2026:
- Different patterns and some legacy data models are still used. The most up to date code is the one based on the global
CustomerAdmindata model. - The admin invitation is fully global + Canada use the global admin management stack end to end (data model + business logic). Other countries are yet to be migrated to global stack.
High level recap table
| Aspect | France π«π· | Belgium π§πͺ | Spain πͺπΈ | Global/Canada π¨π¦ |
|---|---|---|---|---|
| Global admin invite stack | β | β | β | β |
| Global admin stack | β | β | β | β |
| Data models | Local FrCompanyAdmin |
Local BeAccountAdmin, BeCompanyAdmin |
Local EsAccountAdmin, EsCompanyAdmin |
Global CustomerAdmin, CustomerAdminToEntity |
| Responsibilities avaiable | Yes | No | No | No |
| Operational Scopes | β | β | β | Not yet |
Public API¶
CustomerAdminReadServiceis the public entrypoint to query admin data. It's a higher level API that abstracts away country-specific data model and exposes a unified interface.- For the write part, we use plain functions stored in public/actions.py
Global data Model¶
CustomerAdmin¶
The core model representing an admin user and denormalize some profile data:
class CustomerAdmin:
profile_id: UUID # Links to global profile
first_name: str # First name (encrypted), mainly for display and search purpose
last_name: str # Last name (encrypted), mainly for display and search purpose
customer_admin_to_entities # Relationship to entities
CustomerAdminToEntity¶
Represents the relationship between an admin and an entity they manage:
class CustomerAdminToEntity(Historizable):
customer_admin_id: UUID # Reference to CustomerAdmin
entity_id: str # ID of the managed entity
entity_type: EntityType # account/company/operational_scope
parent_account_id: str # Context account
start_date: date # When admin role began
end_date: date # When admin role ended
user_id: str # Country-specific user ID
# other fields for specific use case exists but are omitted for clarity
Key features:
- Historizable - Tracks start/end dates for admin relationships
- Multi-entity support - An admin can manage multiple entities
Interaction with other components¶
Depends on:
- the
onboardingcomponent for the admin invite flow - some countries components (
fr,be,es) to bridge with country-specific data models and logic. This is a transition state only global_profileto get aprofile_idfrom a localuser_id+ react to profile merge and name update events.
Used by:
ca(Canada) for customer authorization logiccontracting- work in progress - the direction is to centralize admin management from contracting into customer admin (ex: acccount hub should be powered by this component API long term)global_customer_dashboardto display admins in the customer dashboard
Design Pattern for backward compatibility¶
The component uses a delegation pattern to handle country-specific logic and bridge with local data models when needed:
- Public API methods receive requests
- Determine the current application context (FR/BE/ES)
- Delegate to country-specific implementations using
match/casestatements - Return standardized entities from the public API
Info
π§ This pattern is being phased out in favor of a repository based pattern to reduce dependencies on local code and data model.
The component also makes uses of dependency inversion pattern β§ to call country-specific code from the global component.
How It Works¶
Permission Checking¶
Authorization is checked separately before the following logic:
- Component builds
AdminedEntitiesForestfor the user - Tree includes direct relationships + transitive relationships
- Controllers check if requested entity is in the admin's tree
For pro dashboard use cases, read the following documentation β§
Admin Invitation Flow¶
High level overview of how the global stack works
flowchart TD
subgraph dash [Pro dashboard]
A[Admin invite new admin]
end
A -->|global_customer_dashboard API calls| B
subgraph onb [Onboarding component]
B[Invitation created + email is sent]
B -->|Invited user click on invite link| C
subgraph invited [Invited user]
C[Deep link in Alan web app is opened]
C --> E[Invitee signs up]
end
end
E -->|admin onboarding completed handler called| F
subgraph customer_admin [Customer_adminΒ component]
F[Admin rights created]
end
- Admin rights created = rows in
CustomerAdminandCustomerAdminToEntityDB tables are created and user gets access to the pro dashboard as a result. - There's an alternative flow that allows directly creating admin rights for an existing employee (add admin by the user name instead of invite email in the invite form). Keyword in the code: "promote admin"
Admin lifecycle¶
- Admin rights are automatically ended when the admin is also an employee and they leave the company.
- Aside from that case, admin management is manual and is done by other admins who add, update and remove admins from the pro dashboard.
Frontend Integration¶
The component works with the customer-admin-management frontend module, which handles:
- Displaying admins in the customer dashboard
- Admin invitation UI
- Admin removal and rights update workflows
Component Tags: Customer Admin, Authorization, Multi-Country, Admin Management