Talent Pool — technical guide
This guide is for implementation and support teams tracing the redesigned Talent Pool module, its shared group infrastructure and People Review integration. Functional covers usage; configuration separates customer administration from platform prerequisites.
Implementation claims below are Verified in code in the local repositories inspected on 16 October 2026. They do not establish deployment, runtime availability or effective tenant authorization. Paths are repository-relative and grouped by repository in the evidence map.
Architecture and responsibilities
| Component | Responsibility |
|---|---|
| Legacy navigation definition / Twig extension | Exposes the admin feature when the integration prerequisites are met. It does not implement a second pool editor. |
| Vue TalentPoolModule | List/detail screens, localized information, candidate selection, permissions and feedback. |
| Pinia stores / composables | Search, sorting, pagination, selected candidates and current pool state. |
talentPool.api.ts | V2 requests, response validation and frontend mapping. |
| Routing YAML | Resource controllers, operation permissions, filters and relation actions. |
TalentPool / TalentPoolUser | Pool configuration and membership data. |
| Shared group listener / rule service | Read-only enforcement, dynamic-member removal guard, rule-change publication and rule evaluation. |
| Pool manager / listener | Membership events and linked campaign synchronization. |
No AIHub request or talent-ranking model was identified in this traced flow. AIHub was searched for the feature name; the absence of a direct reference does not establish that every external integration has been audited. Do not conflate this module with job-offer candidate pools in AIHub.
Navigation and coexistence
Frontend src/constants/app-route.ts defines TALENT_POOL as /:space(admin)/modules/talent-pool; src/router/private-routes.ts maps the authenticated list route and its /:id detail route.
Legacy app/config/neobrain/company/definitions.yml defines smr_talent_pool with hybrid switch enable_new_neobrain_hybrid_platform, legacy right smr_talent_pool_access and SMR scope read-talent-pool. src/Twig/Company/CompanyNavigationExtension.php::getSmrTalentPoolFeature returns the redesigned destination when the admin space is displayable. src/Enum/V2/AdminFeaturesEnum.php identifies the same destination.
A legacy shell and a nextgen module can therefore coexist. No standalone legacy Talent Pool controller/entity equivalent was identified by the scoped feature searches. A migration, independent legacy dataset or synchronization between two pool databases was not established.
API contracts
The frontend uses the /api/v2 prefix. Backend paths below are declared in src/Http/Api/Routing/V2/talent_pool.yaml and talent_pool_user.yaml.
| Method / path | Operation | Required permission |
|---|---|---|
GET /api/v2/talent-pool | List pools | read-talent-pool |
POST /api/v2/talent-pool | Create | create-talent-pool |
GET /api/v2/talent-pool/{id} | Detail | read-talent-pool |
PUT, PATCH /api/v2/talent-pool/{id} | Update | update-talent-pool |
DELETE /api/v2/talent-pool/{id} | Soft-delete resource | delete-talent-pool |
GET /api/v2/talent-pool/{id}/user | Membership list | read-talent-pool |
GET /api/v2/talent-pool/{id}/user/{userId} | Membership detail | read-talent-pool |
POST /api/v2/talent-pool/{id}/user | Attach users | add-user-to-talent-pool |
DELETE /api/v2/talent-pool/{id}/user | Detach users | remove-user-from-talent-pool |
IDs are constrained to digits in routing. Attach/detach use addUserToTalentPool / removeUserFromTalentPool bulk actions with target users resolved through findUsers. Their validators extend DefaultAttachValidator and use MissingUserValidatorTrait. This routing/validation inspection does not establish every response status or bulk execution timing.
Illustrative payload shapes from the frontend caller, with synthetic content only:
{
"titles": {"en-US": "Example pool"},
"descriptions": {"en-US": "Illustrative population for an approved workflow"}
}
Use an actual supported company locale rather than assuming en-US is enabled. Membership mutation uses this body, including a body on DELETE:
{"resources": [101, 102]}
The numbers are illustrative IDs, not existing people. Do not send these examples to production unchanged.
List queries and response handling
The pool caller defaults to page=1&per_page=50 and sends title search as filters[title][contain]. Sorting maps pool-name to title, members to number_of_members, Owner to created_by, and creation date to created_at; frontend dsc becomes API desc. The backend default sorting is title ASC, id ASC.
The routing definition additionally allows title equal/contain/start/end, owner equal, status equal, and numeric/date comparisons on member count/creation date. These API filters are not all exposed as list controls. Their availability does not establish an advanced filter panel.
Member search uses filters[username][contain], with page/per_page and ordering. Routing also exposes first/last-name filters and creation_type equality. Default member sorting is firstname ASC, lastname ASC, created_at ASC. The frontend displays Added via as sortable but its API mapping does not explicitly translate creationType; runtime compatibility for this option needs verification.
getTalentPoolList validates the DTO, maps it and validates the frontend model. On validation failure it logs and tries mapping without schema enforcement, then throws if mapping fails. Detail/create/update map responses through mapToTalentPool. Members use their DTO response schema and consume results, item_count and pages. The list fallback can hide contract drift; a rendered table alone is not proof of schema compliance.
Data model and validation
| Model / property | Checked behavior |
|---|---|
TalentPool extends Group | Maps talent_pool; inherits company, code, read-only, member count, rules, timestamps, creator and soft-delete support. |
| Company | Shared Group links to current Setting; a unique constraint covers code + company. |
| Translations | TalentPoolTranslation and translatable group behavior hold localized content. GroupDTO requires titles and validates translations. |
| Name / description | Backend title max 255, description max 1,000 with HTML sanitization. UI creation uses name max 250 and textarea description max 500 from constants/form-rules.ts. |
| Code | Optional DTO value with uniqueness, restricted-code, text-sanitization and 1–255 length validation when applicable. Not exposed in the checked creation form. |
| Status | TalentPoolStatus: ACTIVE=1, ARCHIVED=2; entity/DTO initial status Active. No full UI status transition was verified. |
| Owner | Entity uses a required owner relation attributed on creation. DTO exposes owner ID/object read-only. UI information uses createdBy, not this separate owner object. |
TalentPoolUser | Composite identity of talent pool + user in talent_pool_user; records timestamps, blameable user, creation type and membership type. |
| Membership defaults | CreationType::API and MembershipType::Static are entity defaults; dynamic processing supplies dynamic membership. |
| Campaign association | PeopleReviewCampaignTalentPool links pools with People Review campaigns. Pool collections cascade persistence/removal and use orphan removal. |
TalentPool::addUser checks existing user IDs before adding to its collection. This protects that method from duplicate collection additions; it does not establish every bulk response behavior.
TalentPoolUserRepository::findTalentPoolUsers joins the pool/user, constrains pool ID and current company, and adds translations. Exact row-level visibility for all operations also depends on shared authorization and target-user lookup. It was not exhaustively audited; pool ownership must not be presented as an independently verified authorization boundary.
Request and membership lifecycle
- The list fetches pools with search, pagination and optional sorting. Opening a row navigates to its detail route.
- Detail fetches the pool and a separate member list. Member search is debounced by 300 ms and resets page/removal selection.
- Manual selection calls the shared user list with search, status and manager IDs. It excludes IDs present in the currently loaded members store locally, not every member across every page. Candidate counts are inherited from the upstream user list.
useAddMembersWithRulesvalidates the modal, posts selected manual IDs, then separately PATCHes rules if marked for saving. It refreshes pool/member state after success.TalentPoolListenerinherits resource guards and publishes rule changes through the shared group listener. Attachment/detachment hooks refresh member counts.
Manual additions and the rule PATCH are sequential independent requests. If the rule update fails after manual additions succeed, the UI shows an error but no compensating rollback is implemented in this composable. Refresh before retrying.
Dynamic rules
TalentPoolAddMembers.vue exposes the dynamic tab with update permission, passes context="talent_pool", and tracks whether that tab was visited. useAddMembersWithRules uses shouldSaveRules, so a visited dynamic tab can cause a rule save even after returning to manual selection. The checked component resets rule state on unmount; rule state is also reset when opening/closing the modal.
The active save path uses useSimpleRulesConverter, not the older converter in the same file. It emits {rules: [...]}, preserves typed expression groups, converts integer/existence values and filters out empty values. GroupDTO documents root expressions as AND and applies the USER-domain rule validator. Do not copy an unconditional “sections are OR” statement from general group documentation.
AbstractGroupListener::postUpdate compares previous/new rules and publishes when they differ. GroupRuleChangedConsumerCommand::execute restores user context and calls GroupRuleService::ruleGroupChanged. The service resolves the pool manager, evaluates matched users and updates rule-based membership. Empty rules remove memberships identified as rule-created; nonempty rules add matches and remove nonmatching rule-created links. updateGroups(User) also evaluates a user's membership across pools with rules.
The service contains a special empty-rule count path that supplies zero to updateNumberOfMembers; the relationship between that count and retained manual memberships needs runtime verification. Do not assume every displayed count is a full recount after rule clearing.
Linked People Review campaigns
TalentPoolManager::addUsersToGroup and removal methods dispatch pool membership events. TalentPoolListener::onTalentPoolUsersAdded/Removed calls CampaignTalentPoolSyncService::syncUsersWithCampaigns. That service finds linked campaign IDs and publishes attachment/detachment messages, using TALENT_POOL as the attachment source. Separate consumers also handle attaching/detaching a whole pool to/from a campaign.
The admin People Review route is /admin/modules/people-review. Its campaign Review assignment step exposes Manual, Groups and Talent Pool sources. The Talent Pool table displays the pool name and member count; selection remains in the assignment state until the campaign is saved. useSaveReviewees posts selected pool IDs to /api/v2/people-review-campaign/{campaignId}/talent-pool; reopening an assignment loads the linked pool IDs separately. Changes to pool membership synchronize asynchronously with linked campaigns, so campaign owners should review participants after a pool change.
The event path is asynchronous. Propagation timing and every campaign-phase effect depend on the deployed workers and campaign state.
Permissions, privacy and failure modes
The frontend independently checks read/create/update/delete/add/remove permissions as appropriate; routing enforces operation permissions. AbstractGroupListener rejects update/delete or attach/detach for read-only groups. Its preDeleteUsers rejects direct removal of dynamic users. Hiding a row action is therefore supplementary to server checks; bulk selection can still contain a dynamic member and fail.
Membership lists expose employee identity and talent-management population. Restrict access through approved roles and validate effective visibility with representative accounts. A pool is not a visibility group or a role grant. Keep request bodies, membership exports and screenshots out of public diagnostics.
| Failure / diagnostic point | Code evidence and practical implication |
|---|---|
| Invalid/missing translation | GroupDTO translation constraints and required title; UI and API length limits differ. |
| Missing relation users | Attach/detach validators use shared missing-user validation. |
| Read-only or dynamic removal | Shared group listener throws a bad-request exception before the operation. |
| Fetch/mutation error | API helpers log; frontend mutation/member fetch paths show translated error toasts. No complete HTTP error catalogue was verified. |
| Contract drift | Pool list schema fallback may still render; inspect response validation logs and payload shape. |
| Rule processing failure | Consumer dispatches a CRITICAL CatchEvent and returns message rejection on Throwable. Broker requeue/dead-letter policy was not inspected. |
| Partial update | Manual-add request can succeed before rule PATCH fails. No cross-request atomicity. |
| Stale member/campaign state | Inspect rule-change publication/consumption and campaign membership messages independently. |
Operational logs must be handled as potentially sensitive: the rule consumer includes the message body in its failure context. This guide intentionally omits infrastructure endpoints, credentials and production execution commands.
Runtime dependencies and extension points
The design depends on authenticated nextgen HTTP access, Symfony resource routing/controllers, Doctrine entities/repositories, locale-aware serialization, the shared rule/query infrastructure and functioning message consumers. Queue topology and service health are deployment responsibilities.
To extend pool information, trace DTO validation, entity/translation mapping and frontend schemas together. To add rule fields, follow the USER-domain rule definitions and builder support rather than inventing arbitrary JSON field IDs. Membership changes must preserve pool events, count handling and campaign synchronization. A new permission needs matching API enforcement and UI behavior.
Evidence and limitations
Key implementation files:
| Repository | Source map |
|---|---|
| nextgen-front | src/constants/app-route.ts, src/router/private-routes.ts, src/constants/form-rules.ts; src/modules/ModuleConfig/TalentPoolModule/ API, list/create/detail components, permissions, stores and add-members composables; src/modules/ConditionalRules/conditionalRules.composables.ts and useAddMembersWithRules.ts. |
| nextgen-back | src/Http/Api/Routing/V2/talent_pool.yaml, talent_pool_user.yaml; src/Domain/V2/Group/DTO/GroupDTO.php; src/Domain/V2/TalentPool/DTO/TalentPoolDTO.php, Enum/TalentPoolStatus.php; src/Infrastructure/Persistence/Entity/Group/Group.php, Entity/TalentPool/TalentPool.php, TalentPoolUser.php; Repository/TalentPool/TalentPoolUserRepository.php; Validator/TalentPool/; Service/TalentPool/TalentPoolManager.php; Listener/Group/AbstractGroupListener.php, Listener/TalentPool/TalentPoolListener.php; src/Infrastructure/Service/Rule/Group/GroupRuleService.php, Service/PeopleReview/CampaignTalentPoolSyncService.php; src/Command/Consumer/Rule/Group/GroupRuleChangedConsumerCommand.php. |
| legacy | app/config/neobrain/company/definitions.yml; src/Twig/Company/CompanyNavigationExtension.php; src/Enum/V2/AdminFeaturesEnum.php; scoped Talent Pool/vivier reference search. |
| aihub | Feature-name search found no direct Talent Pool Python implementation reference. No AI implementation claim is inferred from other candidate-pool features. |
Documented in Confluence: SmartMobility Redesign playbook, PS, v3, 24 September 2026. It supplies deployment intent and campaign assignment context; implementation claims remain anchored to code above. The supplied PS methodology/onboarding pages were read, and the FAQ reference resolved to a folder. None supplied a Talent Pool API contract.
Deployment-specific behavior includes release revision, effective shared visibility rules, candidate-filter combinations, rule-editor state hydration, member-count handling after clearing rules, message retries, campaign-phase effects and restoration. Confirm these contracts with the platform owner before relying on them operationally.
Product-guide scope
The functional guide explains pool lookup, manual and dynamic membership, editing and People Review assignment. The configuration guide covers roles, activation dependencies and population management. Employee-facing Talent Pool administration is not part of this module; the redesigned pool routes are in the admin workspace.
Last updated on 3 November 2026