@webex/contact-center 3.12.0-next.149 → 3.12.0-next.150

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/.sdd/manifest.json +1 -1
  2. package/ai-docs/CONTRACTS.md +1 -0
  3. package/dist/cc.js +4 -4
  4. package/dist/cc.js.map +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/services/config/Util.js +38 -45
  7. package/dist/services/config/Util.js.map +1 -1
  8. package/dist/services/config/constants.js +15 -71
  9. package/dist/services/config/constants.js.map +1 -1
  10. package/dist/services/config/index.js +49 -226
  11. package/dist/services/config/index.js.map +1 -1
  12. package/dist/services/config/types.js +33 -11
  13. package/dist/services/config/types.js.map +1 -1
  14. package/dist/types/cc.d.ts +3 -3
  15. package/dist/types/index.d.ts +16 -8
  16. package/dist/types/services/config/Util.d.ts +4 -8
  17. package/dist/types/services/config/constants.d.ts +15 -71
  18. package/dist/types/services/config/index.d.ts +16 -64
  19. package/dist/types/services/config/types.d.ts +97 -160
  20. package/dist/webex.js +1 -1
  21. package/package.json +1 -1
  22. package/src/cc.ts +4 -4
  23. package/src/index.ts +16 -8
  24. package/src/services/agent/ai-docs/AGENTS.md +1 -1
  25. package/src/services/config/Util.ts +43 -82
  26. package/src/services/config/ai-docs/AGENTS.md +34 -39
  27. package/src/services/config/ai-docs/ARCHITECTURE.md +88 -101
  28. package/src/services/config/ai-docs/config-spec.md +115 -132
  29. package/src/services/config/constants.ts +18 -80
  30. package/src/services/config/index.ts +52 -278
  31. package/src/services/config/types.ts +101 -185
  32. package/test/unit/spec/index.ts +6 -2
  33. package/test/unit/spec/services/config/Util.ts +442 -70
  34. package/test/unit/spec/services/config/index.ts +246 -544
  35. package/typedoc.md +1 -1
  36. package/umd/contact-center.min.js +2 -2
  37. package/umd/contact-center.min.js.map +1 -1
@@ -11,7 +11,7 @@
11
11
  | Doc kind | Module spec |
12
12
  | Coverage score | Partial (manifest-authoritative); 15/15 required document fields present |
13
13
  | Generated from | `module-spec` @ SDLC template library `0.2.1` |
14
- | generated_by / approved_by / updated_at | Codex generator / developer-approved Agent Wellness Break delta / 2026-09-02 |
14
+ | generated_by / approved_by / updated_at | Codex generator / developer-approved desktop-login aggregate migration delta / 2026-10-05 |
15
15
  | Validation status | Agent Wellness Break v0.4 delta independently validated by claude-code on 2026-09-07; coverage remains Partial until the remaining baseline promotion criteria are satisfied |
16
16
 
17
17
  ## Evidence Rules
@@ -27,21 +27,21 @@ Config is one of nine confirmed Contact Center SDK modules. Own retrieval and ag
27
27
 
28
28
  The Config Service is an **internal service** that builds the comprehensive AgentProfile (`Profile` type) by:
29
29
 
30
- 1. Fetching user data
30
+ 1. Fetching the user desktop-login aggregate (agent identity plus `agentProfile`)
31
31
 
32
- 2. Fetching desktop profile
32
+ 2. Fetching the organization desktop-login aggregate (org info, org settings, tenant configuration, URL mappings, AI feature, Microsoft/Webex config)
33
33
 
34
34
  3. Fetching teams
35
35
 
36
36
  4. Fetching aux codes (idle/wrapup codes)
37
37
 
38
- 5. Fetching organization settings
38
+ 5. Fetching site and, when the agent profile enables it, dial-plan data
39
39
 
40
40
  6. Aggregating all data into a single AgentProfile
41
41
 
42
42
  The AgentProfile is the central configuration object required for an agent to operate within the contact center. It is built during the registration flow (`cc.register()`) and contains all the data an agent needs: identity, team assignments, dial plans, aux codes, login options, and feature flags. Once constructed, the AgentProfile is stored on the `ContactCenter` plugin instance as `this.agentConfig` and is used by other services (Agent, Task) throughout the session.
43
43
 
44
- - **AgentProfile Aggregation**: Combines data from 8+ API endpoints
44
+ - **AgentProfile Aggregation**: Combines data from 6 API endpoints (5 when the agent profile disables dial plans)
45
45
 
46
46
  - **Aux Codes Fetching**: Gets all idle and wrapup codes with pagination
47
47
 
@@ -53,7 +53,7 @@ The AgentProfile is the central configuration object required for an agent to op
53
53
 
54
54
  - **Multimedia Profile**: Fetches channel capacity and blending config (standalone, not yet publicly exposed)
55
55
 
56
- - **Paginated Data Access**: `getListOfTeams` and `getListOfAuxCodes` support custom pagination independent of profile building
56
+ - **Paginated Data Access**: `getListOfTeams` and `getListOfAuxCodes` support custom pagination independent of profile building. `getListOfTeams` takes a `userDbId` — the `user.dbId` carried by the user desktop-login aggregate, not the CI user id — rather than a list of team ids
57
57
 
58
58
  ## Purpose / Responsibility
59
59
  Own retrieval and aggregation of remote organization, agent, team, profile, auxiliary-code, dial-plan, and feature configuration.
@@ -94,8 +94,9 @@ services/config/
94
94
  |---|---|---|
95
95
  | `getAgentConfig(orgId, agentId)` | staged, all-or-nothing `Promise<Profile>` aggregation | `src/services/config/index.ts` |
96
96
  | User/profile/site/team/aux-code fetches | typed REST methods including pagination helpers | `src/services/config/index.ts`, `src/services/config/types.ts` |
97
- | `getAIFeatureFlags(orgId)` | `AIFeatureFlagsResponse` from `organization/{orgId}/v2/ai-feature?page=0&pageSize=100` | `src/services/config/index.ts`, `src/services/config/constants.ts` |
98
- | `Profile.aiFeature` | optional first AI-feature row mapped by `parseAgentConfigs` | `src/services/config/Util.ts`, `src/services/config/types.ts` |
97
+ | `getOrgDesktopLoginConfig(orgId)` | `OrgDesktopLoginResponse` from `organization/{orgId}/desktop-login` | `src/services/config/index.ts`, `src/services/config/constants.ts` |
98
+ | `getUserDesktopLoginConfig(orgId, ciUserId)` | `UserDesktopLoginResponse` from `organization/{orgId}/v2/user/by-ci-user-id/{ciUserId}/desktop-login` | `src/services/config/index.ts`, `src/services/config/constants.ts` |
99
+ | `Profile.aiFeature` | optional `aiFeature` section of the organization aggregate, mapped by `parseAgentConfigs` | `src/services/config/Util.ts`, `src/services/config/types.ts` |
99
100
  | Multimedia profile | `MultimediaProfileResponse` | `src/services/config/types.ts` |
100
101
  | Organization masking | `OrgSettings.maskSensitiveData` | `src/services/config/types.ts`, `src/services/config/Util.ts` |
101
102
  | Auxiliary-code list URL | includes `desktopProfileFilter=true` | `src/services/config/constants.ts` |
@@ -113,8 +114,8 @@ The service has no `TeamList.channelMap` contract. Exact package exports are ind
113
114
  ## Requirements
114
115
  | ID | WHAT | WHY | Source Evidence | Test / Example Evidence | Assumptions / Gaps | Confidence |
115
116
  |---|---|---|---|---|---|---|
116
- | CONFIG-R-001 | Fetch user config first, then aggregate ten dependent promises including AI feature flags, auxiliary codes, profile/site/team/dial-plan, organization, tenant, and URL data. | Dependent IDs and all-or-nothing consistency require staged orchestration. | `src/services/config/index.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
117
- | CONFIG-R-002 | Include `getAIFeatureFlags` response in `parseAgentConfigs` so `Profile.aiFeature` reflects `/v2/ai-feature`. | ApiAIAssistant behavior is gated by the remote organization feature contract. | `src/services/config/index.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
117
+ | CONFIG-R-001 | Fetch the user desktop-login aggregate first, then aggregate five dependent promises: the organization desktop-login aggregate, auxiliary codes, teams, site, and the conditional dial plan. | Dependent IDs and all-or-nothing consistency require staged orchestration. | `src/services/config/index.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
118
+ | CONFIG-R-002 | Include the organization aggregate's `aiFeature` section in `parseAgentConfigs` so `Profile.aiFeature` reflects the organization feature contract. | ApiAIAssistant behavior is gated by the remote organization feature contract. | `src/services/config/index.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
118
119
  | CONFIG-R-003 | Paginate teams and auxiliary codes until completion and include `desktopProfileFilter=true` for auxiliary-code requests. | A partial or unfiltered set yields invalid profile/team/auxiliary choices. | `src/services/config/constants.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
119
120
  | CONFIG-R-004 | Expose current response/field names: `MultimediaProfileResponse`, `OrgSettings.maskSensitiveData`, and real TeamList fields only. | Type-name drift causes invalid consumer code and incorrect privacy behavior. | `src/services/config/types.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
120
121
  | CONFIG-R-005 | Reject the entire profile aggregation when any required dependent request fails. | Consumers must never receive an internally inconsistent partial Profile. | `src/services/config/index.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
@@ -168,32 +169,22 @@ The AgentProfile is defined as the [`Profile`](../types.ts) type. This is not an
168
169
  | `accessBuddyTeam` | `'ALL' \| 'SPECIFIC' \| 'NONE'` | Collaboration tab buddy-team access scope from Desktop Profile |
169
170
  | `isWellnessBreakEnabled` | boolean | Effective wellness gate derived from backend enablement/reminder configuration and positive AI Assistant license quantity |
170
171
 
171
- `parseAgentConfigs()` maps the three `access*` fields from `DesktopProfileResponse` onto the public `Profile` returned by `cc.register()`.
172
+ `parseAgentConfigs()` maps the three `access*` fields from the user aggregate's `AgentProfile` section onto the public `Profile` returned by `cc.register()`.
172
173
 
173
- The following diagram shows how `getAgentConfig` orchestrates multiple API calls and combines their results into the AgentProfile via `parseAgentConfigs()`:
174
+ The following diagram shows how `getAgentConfig` orchestrates six API calls and combines their results into the AgentProfile via `parseAgentConfigs()`:
174
175
 
175
176
  ```text
176
- getUserUsingCI ────────────┐
177
- │
178
- getOrgInfo ────────────────┤
179
- │
180
- getOrganizationSetting ────┤
181
- │
182
- getTenantData ─────────────┤
183
- │
184
- getURLMapping ─────────────┼──► parseAgentConfigs() ──► AgentProfile
185
- │
186
- getAIFeatureFlags ─────────┤ (maps the first row to Profile.aiFeature)
187
- │
188
- getAllAuxCodes ─────────────┤
189
- │
190
- getDesktopProfileById ─────┤
191
- │
192
- getSiteInfo ───────────────┤ (computes multimediaProfileId)
193
- │
194
- getAllTeams ────────────────┤
195
- │
196
- getDialPlanData ───────────┘
177
+ getUserDesktopLoginConfig ──┐ (awaited first; supplies dbId, siteId, dialPlanEnabled)
178
+ │
179
+ getOrgDesktopLoginConfig ───┤ (org info, org settings, tenant config, urlMappings,
180
+ │ aiFeature, microsoftConfig, webexConfig)
181
+ getAllAuxCodes ─────────────┼──► parseAgentConfigs() ──► AgentProfile
182
+ │
183
+ getAllTeams ────────────────┤ (filtered by userId == user.dbId)
184
+ │
185
+ getSiteInfo ────────────────┤ (team → site fallback for multimediaProfileId)
186
+ │
187
+ getDialPlanData ────────────┘ (only when agentProfile.dialPlanEnabled)
197
188
  ```
198
189
 
199
190
  Types used by the config service, all defined in [`types.ts`](../types.ts):
@@ -201,23 +192,26 @@ Types used by the config service, all defined in [`types.ts`](../types.ts):
201
192
  | Type | Description |
202
193
  |---|---|
203
194
  | `Profile` | Final aggregated agent config returned by `getAgentConfig()` |
204
- | `AgentResponse` | Raw response from `getUserUsingCI()` — agent metadata, teamIds, siteId, agentProfileId |
205
- | `DesktopProfileResponse` | Desktop profile settings — layout, dial plan, login options |
195
+ | `OrgDesktopLoginResponse` | Response from `getOrgDesktopLoginConfig()` — `organization`, `organizationSetting`, `tenantConfiguration`, `urlMappings`, `aiFeature`, `microsoftConfig`, `webexConfig` |
196
+ | `UserDesktopLoginResponse` | Response from `getUserDesktopLoginConfig()` — `user` and `agentProfile` sections |
197
+ | `AgentResponse` | `user` section of the user aggregate — agent metadata, `dbId`, `siteId`, `agentProfileId` |
198
+ | `AgentProfile` | `agentProfile` section of the user aggregate — layout, dial-plan enablement, login options |
206
199
  | `TeamList` | Team record from API — `id`, `name`, `teamType`, `siteId`, `multiMediaProfileId` |
207
200
  | `ListTeamsResponse` | Paginated wrapper around `TeamList[]` with `meta` for pagination |
208
201
  | `OrgInfo` | Organization info — `tenantId`, timezone |
209
202
  | `OrgSettings` | Org feature flags — `webRtcEnabled`, `maskSensitiveData` |
210
203
  | `TenantData` | Tenant-level config — inactivity timeout, `forceDefaultDn`, `outdialEnabled` |
211
204
  | `SiteInfo` | Site config — `id`, `name`, `multimediaProfileId` |
212
- | `URLMapping` | External URL mapping — `id`, `name`, `url` |
205
+ | `OrgUrlMappings` | Keyed external URL mappings — `ACQUEON_API_URL`, `ACQUEON_CONSOLE_URL` |
206
+ | `MicrosoftConfig` | Org-level Microsoft presence config — `showUserDetails`, `stateSynchronization` |
207
+ | `WebexConfig` | Org-level Webex presence config — `showUserDetails`, `stateSynchronization` |
213
208
  | `MultimediaProfileResponse` | Multimedia profile — channel capacities and settings |
214
209
  | `AuxCode` | Auxiliary code record — `id`, `name`, `description`, `workTypeCode` |
215
210
  | `ListAuxCodesResponse` | Paginated wrapper around `AuxCode[]` with `meta` |
216
- | `DialPlanEntity` | Dial plan rule — regex pattern, prefix, strip digits |
211
+ | `DialPlanEntity` | Dial plan rule — regex pattern, prefix, strip digits, `active` |
217
212
  | `Entity` | Basic entity info — `isSystem`, `name`, `id`, `description` |
218
213
  | `WrapupData` | Wrap-up config — auto-wrapup settings, available wrapup codes |
219
214
  | `OutdialAniParams` | Parameters for `getOutdialAniEntries()` — ANI ID, pagination, filtering |
220
- | `Team` | Simplified team shape in `Profile` — `teamId`, `teamName`, `desktopLayoutId` |
221
215
 
222
216
  ```typescript
223
217
  // In register() -> connectWebsocket()
@@ -233,19 +227,19 @@ For endpoints with pagination (teams, aux codes):
233
227
  ```typescript
234
228
  import {DEFAULT_PAGE} from './constants'; // DEFAULT_PAGE = 0
235
229
 
236
- public async getAllTeams(orgId, pageSize, filter): Promise<TeamList[]> {
230
+ public async getAllTeams(orgId, pageSize, userDbId): Promise<TeamList[]> {
237
231
  let allTeams: TeamList[] = [];
238
232
  let page = DEFAULT_PAGE;
239
233
 
240
234
  // First request to get totalPages
241
- const firstResponse = await this.getListOfTeams(orgId, page, pageSize, filter);
235
+ const firstResponse = await this.getListOfTeams(orgId, page, pageSize, userDbId);
242
236
  allTeams = allTeams.concat(firstResponse.data);
243
237
  const totalPages = firstResponse.meta.totalPages;
244
238
 
245
239
  // Parallel requests for remaining pages
246
240
  const requests = [];
247
241
  for (page = DEFAULT_PAGE + 1; page < totalPages; page += 1) {
248
- requests.push(this.getListOfTeams(orgId, page, pageSize, filter));
242
+ requests.push(this.getListOfTeams(orgId, page, pageSize, userDbId));
249
243
  }
250
244
 
251
245
  const responses = await Promise.all(requests);
@@ -263,50 +257,44 @@ The service fetches data from multiple APIs with these response structures:
263
257
 
264
258
  | API Method | Response Type | Key Fields | Usage |
265
259
  |---|---|---|---|
266
- | `getUserUsingCI` | `AgentResponse` | `ciUserId`, `id`, `firstName`, `lastName`, `email`, `teamIds`, `agentProfileId`, `siteId` | Primary agent identity and profile references |
267
- | `getDesktopProfileById` | `DesktopProfileResponse` | `dialPlanEnabled`, `autoAnswer`, `accessWrapUpCode`, `wrapUpCodes`, `accessIdleCode`, `idleCodes`, `loginVoiceOptions` | Agent desktop settings and feature enablement |
260
+ | `getUserDesktopLoginConfig` | `UserDesktopLoginResponse` | `user`: `ciUserId`, `id`, `dbId`, `firstName`, `lastName`, `email`, `agentProfileId`, `siteId`. `agentProfile`: `dialPlanEnabled`, `accessWrapUpCode`, `accessIdleCode`, `loginVoiceOptions`, `viewableStatistics` | Agent identity, team-filter id, site reference, and desktop settings in one call |
261
+ | `getOrgDesktopLoginConfig` | `OrgDesktopLoginResponse` | `organization`: `tenantId`, `timezone`. `organizationSetting`: `webRtcEnabled`, `maskSensitiveData`, `campaignManagerEnabled`, `aiAssistantQuantity`. `tenantConfiguration`: `outdialEnabled`, `forceDefaultDn`, `privacyShieldVisible`, `timeoutDesktopInactivityEnabled`. Optional `urlMappings`, `aiFeature`, `microsoftConfig`, `webexConfig` | All organization-, tenant- and feature-scoped configuration in one call |
268
262
  | `getAllTeams` | `TeamList[]` | real `TeamList` fields from `src/services/config/types.ts` | Team identity, name, type, and site assignment; channel capacities belong to `MultimediaProfileResponse` |
269
- | `getTenantData` | `TenantData` | `outdialEnabled`, `forceDefaultDn`, `privacyShieldVisible`, `timeoutDesktopInactivityEnabled` | Tenant-level feature flags |
270
- | `getOrgInfo` | `OrgInfo` | `tenantId`, `timezone` | Organization metadata |
271
263
  | `getAllAuxCodes` | `AuxCode[]` | `id`, `name`, `workTypeCode`, `active`, `isSystemCode`, `defaultCode` | Auxiliary codes for idle/wrap-up states |
272
- | `getOrganizationSetting` | `OrgSettings` | `webRtcEnabled`, `maskSensitiveData`, `campaignManagerEnabled`, `aiAssistantQuantity` | Organization-level feature flags and AI Assistant license quantity |
273
- | `getDialPlanData` | `DialPlanEntity[]` | `id`, `name`, `regularExpression`, `prefix`, `strippedChars` | Dial plan rules for outbound calling |
274
- | `getURLMapping` | `URLMapping[]` | `name`, `url` | External service URL mappings |
275
- | `getSiteInfo` | `SiteInfo` | Site-specific configuration | Site details |
264
+ | `getDialPlanData` | `DialPlanEntity[]` | `id`, `name`, `regularExpression`, `prefix`, `strippedChars`, `active` | Dial plan rules for outbound calling |
265
+ | `getSiteInfo` | `SiteInfo` | Site-specific configuration | Site details, including the `multimediaProfileId` fallback |
276
266
 
277
267
  These responses are parsed and aggregated into a single `Profile` object by the `parseAgentConfigs` function.
278
268
 
279
269
  ```typescript
280
270
  // See full implementation in Util.ts
281
271
  function parseAgentConfigs(profileData: {
282
- userData: AgentResponse; // See types.ts:AgentResponse
283
- teamData: Team[]; // NOTE: Declared as Team[] (teamId, teamName) but receives TeamList[] (id, name, + 12 more fields) at runtime
284
- tenantData: TenantData; // See types.ts:TenantData
285
- orgInfoData: OrgInfo; // See types.ts:OrgInfo
286
- auxCodes: AuxCode[]; // See types.ts:AuxCode
287
- orgSettingsData: OrgSettings; // See types.ts:OrgSettings
288
- agentProfileData: DesktopProfileResponse; // See types.ts:DesktopProfileResponse
289
- dialPlanData: DialPlanEntity[]; // See types.ts:DialPlanEntity
290
- urlMapping: URLMapping[]; // See types.ts:URLMapping
272
+ orgConfig: OrgDesktopLoginResponse; // See types.ts:OrgDesktopLoginResponse
273
+ userData: AgentResponse; // `user` section; see types.ts:AgentResponse
274
+ agentProfileData: AgentProfile; // `agentProfile` section; see types.ts:AgentProfile
275
+ teamData: TeamList[]; // See types.ts:TeamList
276
+ auxCodes: AuxCode[]; // See types.ts:AuxCode
277
+ dialPlanData: DialPlanEntity[]; // See types.ts:DialPlanEntity
291
278
  multimediaProfileId: string;
292
- aiFeatureFlags: AIFeatureFlagsResponse;
293
- }): Profile { // See types.ts:Profile
294
- const { userData, teamData, tenantData, orgInfoData, auxCodes,
295
- orgSettingsData, agentProfileData, dialPlanData, urlMapping,
296
- aiFeatureFlags } = profileData;
297
-
298
- const aiFeature = aiFeatureFlags?.data?.length > 0
299
- ? aiFeatureFlags.data[0]
300
- : undefined;
279
+ }): Profile { // See types.ts:Profile
280
+ const { orgConfig, userData, agentProfileData, teamData, auxCodes,
281
+ dialPlanData } = profileData;
282
+ const {
283
+ organization: orgInfoData,
284
+ organizationSetting: orgSettingsData,
285
+ tenantConfiguration: tenantData,
286
+ urlMappings,
287
+ aiFeature,
288
+ microsoftConfig,
289
+ webexConfig,
290
+ } = orgConfig;
301
291
 
302
292
  // Aux code filtering via getFilterAuxCodes():
303
- // - checks auxCode.active
304
- // - checks specificCodes access level (ALL → no filter, SPECIFIC → include list)
293
+ // - checks auxCode.workTypeCode and auxCode.active
294
+ // - the aggregate returns the full org pool, so no per-agent restriction is applied
305
295
  // - maps to Entity {id, name, isSystem, isDefault}
306
- const wrapupCodes = getFilterAuxCodes(auxCodes, WRAP_UP_CODE,
307
- agentProfileData.accessWrapUpCode === 'ALL' ? [] : agentProfileData.wrapUpCodes);
308
- const idleCodes = getFilterAuxCodes(auxCodes, IDLE_CODE,
309
- agentProfileData.accessIdleCode === 'ALL' ? [] : agentProfileData.idleCodes);
296
+ const wrapupCodes = getFilterAuxCodes(auxCodes, WRAP_UP_CODE);
297
+ const idleCodes = getFilterAuxCodes(auxCodes, IDLE_CODE);
310
298
 
311
299
  // Hardcoded "Available" state always appended to idle codes
312
300
  idleCodes.push({ id: '0', name: 'Available', isSystem: false, isDefault: false });
@@ -315,7 +303,7 @@ function parseAgentConfigs(profileData: {
315
303
  agentId: userData.ciUserId, // NOTE: uses ciUserId for agent identification
316
304
  analyserUserId: userData.id, // NOTE: userData.id is used for analytics/reporting
317
305
  agentName: `${userData.firstName} ${userData.lastName}`,
318
- teams: teamData, // NOTE: Raw TeamList[] passed directly without mapping
306
+ teams: teamData, // TeamList[] straight from the team API; Profile.teams is TeamList[]
319
307
  idleCodes, // NOTE: Filtered via getFilterAuxCodes() + hardcoded "Available" state
320
308
  wrapupCodes, // NOTE: Filtered via getFilterAuxCodes()
321
309
  webRtcEnabled: orgSettingsData.webRtcEnabled,
@@ -332,31 +320,22 @@ function parseAgentConfigs(profileData: {
332
320
  ## Data Flow
333
321
  ```mermaid
334
322
  flowchart TD
335
- Start[getAgentConfig orgId + agentId] --> User[getUserUsingCI awaited first]
336
- Start --> Org[getOrgInfo]
337
- Start --> OrgSettings[getOrganizationSetting]
338
- Start --> Tenant[getTenantData]
339
- Start --> URL[getURLMapping]
340
- Start --> AI[getAIFeatureFlags]
323
+ Start[getAgentConfig orgId + agentId] --> User[getUserDesktopLoginConfig awaited first]
324
+ Start --> Org[getOrgDesktopLoginConfig]
341
325
  Start --> Aux[getAllAuxCodes]
342
- User --> Profile[getDesktopProfileById]
343
- User --> Site[getSiteInfo]
344
- User --> Teams[getAllTeams or empty]
345
- Profile --> Dial{dialPlanEnabled?}
326
+ User --> Site[getSiteInfo siteId]
327
+ User --> Teams[getAllTeams filtered by dbId]
328
+ User --> Dial{agentProfile.dialPlanEnabled?}
346
329
  Dial -->|yes| DialPlan[getDialPlanData]
347
330
  Dial -->|no| Empty[empty dial plan]
348
- Profile --> All[Promise.all of ten result promises]
349
- Site --> All
331
+ Site --> All[Promise.all of five result promises]
350
332
  Teams --> All
351
333
  DialPlan --> All
352
334
  Empty --> All
353
335
  Org --> All
354
- OrgSettings --> All
355
- Tenant --> All
356
- URL --> All
357
- AI --> All
358
336
  Aux --> All
359
- All --> Parse[parseAgentConfigs including aiFeatureFlags]
337
+ All --> Mm[multimediaProfileId: team value else site value]
338
+ Mm --> Parse[parseAgentConfigs with orgConfig + userData + agentProfileData]
360
339
  Parse --> Result[Profile with aiFeature + maskSensitiveData]
361
340
  ```
362
341
 
@@ -380,19 +359,19 @@ sequenceDiagram
380
359
  participant Util as parseAgentConfigs
381
360
  CC->>Cfg: getAgentConfig(orgId, agentId)
382
361
  par requests started before user data resolves
383
- Cfg->>API: getUserUsingCI
384
- Cfg->>API: org info + org settings + tenant + URL mapping
385
- Cfg->>API: ai-feature flags + all aux codes
362
+ Cfg->>API: getUserDesktopLoginConfig
363
+ Cfg->>API: getOrgDesktopLoginConfig
364
+ Cfg->>API: getAllAuxCodes
386
365
  end
387
- API-->>Cfg: user IDs/profile/site/team IDs
366
+ API-->>Cfg: user.dbId / user.siteId / agentProfile.dialPlanEnabled
388
367
  par user-dependent requests
389
- Cfg->>API: desktop profile + site + teams
390
- Cfg->>API: conditional dial plan chained from desktop profile
368
+ Cfg->>API: getSiteInfo + getAllTeams(filter userId==dbId)
369
+ Cfg->>API: conditional dial plan gated on agentProfile.dialPlanEnabled
391
370
  end
392
- Note over Cfg,API: Promise.all awaits 10 result promises in total
371
+ Note over Cfg,API: Promise.all awaits 5 result promises after the user aggregate
393
372
  alt all succeed
394
- API-->>Cfg: ten results
395
- Cfg->>Util: parseAgentConfigs(..., aiFeatureFlags)
373
+ API-->>Cfg: five results
374
+ Cfg->>Util: parseAgentConfigs(orgConfig, userData, agentProfileData, ...)
396
375
  Util-->>CC: Profile including aiFeature
397
376
  else any fails
398
377
  Cfg-->>CC: throw; no partial Profile
@@ -407,7 +386,7 @@ sequenceDiagram
407
386
  participant Cfg as AgentConfigService
408
387
  participant WR as WebexRequest
409
388
  participant API as WCC API
410
- Caller->>Cfg: getAllTeams/getAllAuxCodes(orgId, pageSize, filters)
389
+ Caller->>Cfg: getAllTeams(orgId, pageSize, userDbId) / getAllAuxCodes(orgId, pageSize, filters)
411
390
  Cfg->>WR: request page 0
412
391
  WR->>API: authenticated GET
413
392
  alt first page succeeds
@@ -437,7 +416,7 @@ classDiagram
437
416
  class parseAgentConfigs
438
417
  class Profile
439
418
  ContactCenter --> AgentConfigService : getAgentConfig
440
- AgentConfigService --> WebexRequest : ten dependent requests
419
+ AgentConfigService --> WebexRequest : six dependent requests
441
420
  AgentConfigService --> parseAgentConfigs : aggregate results
442
421
  parseAgentConfigs --> Profile : aiFeature + maskSensitiveData
443
422
  ```
@@ -450,9 +429,9 @@ classDiagram
450
429
  | `types` | `config/types.ts` | Types, events, interfaces |
451
430
 
452
431
  ## Use Cases
453
- - **UC-1 Two-wave profile aggregation:** retrieve the user first, run ten dependent promises including AI feature flags, then parse one complete Profile or reject the whole operation. Evidence: `src/services/config/index.ts`, `src/services/config/Util.ts`, `test/unit/spec/services/config/index.ts`.
432
+ - **UC-1 Two-wave profile aggregation:** retrieve the user desktop-login aggregate first, run five dependent promises including the organization aggregate, then parse one complete Profile or reject the whole operation. Evidence: `src/services/config/index.ts`, `src/services/config/Util.ts`, `test/unit/spec/services/config/index.ts`.
454
433
  - **UC-2 Paginated teams/aux codes:** follow backend page metadata to completion; auxiliary-code requests include `desktopProfileFilter=true`. Evidence: `src/services/config/index.ts`, `test/unit/spec/services/config/index.ts`.
455
- - **UC-3 Dial plan and URL mapping:** request dial-plan data only when the desktop profile enables it while always including URL mapping in profile aggregation. Evidence: `src/services/config/index.ts`, `test/unit/spec/services/config/index.ts`.
434
+ - **UC-3 Dial plan and URL mappings:** request dial-plan data only when the agent profile enables it, keep only `active` plans, and map the organization aggregate's `urlMappings` into the profile. Evidence: `src/services/config/index.ts`, `src/services/config/Util.ts`, `test/unit/spec/services/config/index.ts`.
456
435
  - **UC-4 Outdial ANI retrieval:** return the organization-scoped ANI list through authenticated WebexRequest and propagate failures without a partial substitute. Evidence: `src/services/config/index.ts`, `test/unit/spec/services/config/index.ts`.
457
436
  - **UC-5 Wellness configuration:** produce one fail-closed effective profile flag and retrieve the exact system wellness idle code across pages. Evidence: `src/services/config/Util.ts`, `src/services/config/index.ts`, `test/unit/spec/services/config/Util.ts`, `test/unit/spec/services/config/index.ts`.
458
437
 
@@ -464,18 +443,20 @@ classDiagram
464
443
  - The system wellness code lookup is separate from profile auxiliary-code aggregation and uses `desktopProfileFilter=false`.
465
444
 
466
445
  ## Concurrency & Reactive Flow
467
- - The initial user lookup supplies identifiers for a ten-promise `Promise.all`; pagination loops await pages in order and stop from returned metadata.
446
+ - The initial user desktop-login lookup supplies identifiers for a five-promise `Promise.all`; pagination loops await pages in order and stop from returned metadata.
468
447
 
469
448
  ## Protocol / Wire Format
470
449
  All Config operations are authenticated REST calls through WebexRequest. Important current routes include:
471
450
 
472
451
  | Operation | Resource shape |
473
452
  |---|---|
474
- | AI feature flags | `organization/{orgId}/v2/ai-feature?page=0&pageSize=100` |
453
+ | Organization desktop-login aggregate | `organization/{orgId}/desktop-login` |
454
+ | User desktop-login aggregate | `organization/{orgId}/v2/user/by-ci-user-id/{ciUserId}/desktop-login` |
455
+ | Teams | `organization/{orgId}/v2/team?page={page}&pageSize={pageSize}&agentView=true&filter=userId=={userDbId}` — the wire field is `userId` but the value is the user's database id; filter value unquoted, no `attributes=` projection |
475
456
  | Auxiliary codes | pagination/filter/attributes plus `desktopProfileFilter=true` |
476
457
  | Wellness system idle code | `organization/{orgId}/v2/auxiliary-code?page={page}&pageSize={pageSize}&workType=IDLE_CODE&customFilter=isSystemCode==true&desktopProfileFilter=false` |
477
458
  | Multimedia profile | organization-scoped multimedia-profile resource |
478
- | Dial plan | organization-scoped dial-plan resource when desktop profile enables it |
459
+ | Dial plan | organization-scoped dial-plan resource when the agent profile enables it |
479
460
 
480
461
  Exact resources live in `src/services/config/constants.ts`; response/profile fields live in `src/services/config/types.ts`.
481
462
 
@@ -485,7 +466,7 @@ Exact resources live in `src/services/config/constants.ts`; response/profile fie
485
466
  | Dependency rejection | Typed/rethrown error or failure event | Inspect structured details, preserve tracking id, and retry only when the operation is safe. |
486
467
  | Timeout or missing async completion | Timeout/recovery state | Follow the module-specific recovery path; never synthesize success. |
487
468
 
488
- All API methods within the config service throw errors on failure. After `getUserUsingCI`, `getAgentConfig` awaits ten dependent requests via `Promise.all`: desktop profile, site, teams, conditional dial plan, organization info, organization settings, tenant data, URL mapping, AI feature flags, and all auxiliary codes. A failure in any required request, including `getAIFeatureFlags`, causes the entire AgentProfile fetch to fail. There is no partial profile — either all data is successfully fetched and aggregated, or the operation throws.
469
+ All API methods within the config service throw errors on failure. After `getUserDesktopLoginConfig`, `getAgentConfig` awaits five dependent requests via `Promise.all`: site, conditional dial plan, teams, the organization desktop-login aggregate, and all auxiliary codes. A failure in any required request, including `getOrgDesktopLoginConfig`, causes the entire AgentProfile fetch to fail. There is no partial profile — either all data is successfully fetched and aggregated, or the operation throws.
489
470
 
490
471
  ```typescript
491
472
  try {
@@ -502,14 +483,17 @@ try {
502
483
  Each method follows consistent error handling:
503
484
 
504
485
  ```typescript
505
- public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentResponse> {
506
- LoggerProxy.info('Fetching user data using CI', {
486
+ public async getUserDesktopLoginConfig(
487
+ orgId: string,
488
+ ciUserId: string
489
+ ): Promise<UserDesktopLoginResponse> {
490
+ LoggerProxy.info('Fetching user desktop-login configuration', {
507
491
  module: CONFIG_FILE_NAME,
508
- method: METHODS.GET_USER_USING_CI,
492
+ method: METHODS.GET_USER_DESKTOP_LOGIN_CONFIG,
509
493
  });
510
494
 
511
495
  try {
512
- const resource = endPointMap.userByCI(orgId, agentId);
496
+ const resource = endPointMap.userDesktopLogin(orgId, ciUserId);
513
497
  const response = await this.webexReq.request({
514
498
  service: WCC_API_GATEWAY,
515
499
  resource,
@@ -520,16 +504,16 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
520
504
  throw new Error(`API call failed with ${response.statusCode}`);
521
505
  }
522
506
 
523
- LoggerProxy.log('getUserUsingCI api success.', {
507
+ LoggerProxy.log('getUserDesktopLoginConfig api success.', {
524
508
  module: CONFIG_FILE_NAME,
525
- method: METHODS.GET_USER_USING_CI,
509
+ method: METHODS.GET_USER_DESKTOP_LOGIN_CONFIG,
526
510
  });
527
511
 
528
512
  return Promise.resolve(response.body);
529
513
  } catch (error) {
530
- LoggerProxy.error(`getUserUsingCI API call failed with ${error}`, {
514
+ LoggerProxy.error(`getUserDesktopLoginConfig API call failed with ${error}`, {
531
515
  module: CONFIG_FILE_NAME,
532
- method: METHODS.GET_USER_USING_CI,
516
+ method: METHODS.GET_USER_DESKTOP_LOGIN_CONFIG,
533
517
  });
534
518
  throw error;
535
519
  }
@@ -546,8 +530,8 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
546
530
  "module": "config/index.ts", "method": "getAgentConfig"
547
531
 
548
532
  // Specific API method failures
549
- "getUserUsingCI API call failed"
550
- "getDesktopProfileById API call failed"
533
+ "getUserDesktopLoginConfig API call failed"
534
+ "getOrgDesktopLoginConfig API call failed"
551
535
  "getAllTeams API call failed"
552
536
  "getAllAuxCodes API call failed"
553
537
 
@@ -583,7 +567,7 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
583
567
 
584
568
  1. Check `totalPages` in first response
585
569
 
586
- 2. Verify filter array contains valid team/aux code IDs
570
+ 2. Verify the team filter carries a valid `userDbId` (`user.dbId`, not the CI user id) and that aux-code filters contain valid IDs
587
571
 
588
572
  3. Check if pageSize is appropriate (default: 100)
589
573
 
@@ -594,8 +578,8 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
594
578
  **Log patterns:**
595
579
 
596
580
  ```typescript
597
- "getOrganizationSetting api success"
598
- "getTenantData api success"
581
+ "getOrgDesktopLoginConfig api success."
582
+ "getUserDesktopLoginConfig api success."
599
583
  ```
600
584
 
601
585
  **Solution**:
@@ -618,7 +602,7 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
618
602
 
619
603
  3. Note: dial plan fetch only happens if `dialPlanEnabled === true`
620
604
 
621
- **Cause**: Access level set to 'SPECIFIC' but missing code IDs
605
+ **Cause**: Expected auxiliary codes missing from the returned pool
622
606
 
623
607
  **Log patterns:**
624
608
 
@@ -628,23 +612,22 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
628
612
 
629
613
  **Solution**:
630
614
 
631
- 1. Check `agentProfileData.accessWrapUpCode` (should be 'ALL' or 'SPECIFIC')
632
-
633
- 2. Check `agentProfileData.accessIdleCode`
615
+ 1. `getFilterAuxCodes` no longer applies a per-agent restriction list — the full organization pool is returned for every agent
634
616
 
635
- 3. If 'SPECIFIC', verify `wrapUpCodes` and `idleCodes` arrays contain valid IDs
617
+ 2. `Profile.idleCodesAccess` / `wrapupCodesAccess` still report `ALL` or `SPECIFIC` from `agentProfileData`
636
618
 
637
- 4. Ensure aux codes have `active: true` status
619
+ 3. Ensure aux codes have `active: true` status and the expected `workTypeCode`
638
620
 
639
- 5. Note: "Available" state is always appended to idle codes
621
+ 4. Note: "Available" state is always appended to idle codes
640
622
 
641
623
  ## Pitfalls
642
- - `getUserUsingCI` must complete before profile/site/team-dependent requests are constructed, while the ten dependent promises remain all-or-nothing.
643
- - AI feature flags are part of the ten-result aggregation and must be passed into `parseAgentConfigs`; omitting them silently removes `Profile.aiFeature`.
624
+ - `getUserDesktopLoginConfig` must complete before site/team/dial-plan requests are constructed, while the five dependent promises remain all-or-nothing.
625
+ - The `aiFeature` section is part of the organization aggregate and must be passed into `parseAgentConfigs`; omitting it silently removes `Profile.aiFeature`.
626
+ - The team filter value must stay unquoted (`filter=userId=={dbId}`) — the quoted form returns HTTP 400 — and must not carry an `attributes=` projection, which would strip `multiMediaProfileId`, `teamType` and `siteName`.
644
627
  - Team responses do not own channel configuration, and auxiliary-code requests require `desktopProfileFilter=true` during profile construction.
645
628
 
646
629
  ## Module Do's / Don'ts
647
- - DO preserve the user-first dependency boundary and the exact ten-promise result order.
630
+ - DO preserve the user-first dependency boundary and the exact five-promise result order.
648
631
  - DO paginate team and auxiliary-code endpoints until their metadata indicates completion.
649
632
  - DON'T return a partially assembled Profile after any required dependency fails.
650
633
  - DON'T invent TeamList fields such as `channelMap` or omit `maskSensitiveData`/`aiFeature` mappings.
@@ -653,7 +636,7 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
653
636
  - Profile creation is all-or-nothing across dependent API calls so consumers never receive internally inconsistent partial configuration.
654
637
 
655
638
  ## Test-Case Strategy (module)
656
- `test/unit/spec/services/config/index.ts` must cover staged user-first orchestration, ten-promise aggregation, AI-feature mapping, conditional dial plan, pagination, auxiliary-code URL filtering, real response field names, and whole-profile rejection on any required failure.
639
+ `test/unit/spec/services/config/index.ts` must cover staged user-first orchestration, five-promise aggregation, AI-feature mapping, conditional dial plan, the `userDbId` team filter, pagination, auxiliary-code URL filtering, real response field names, and whole-profile rejection on any required failure.
657
640
 
658
641
  | Behavior / Requirement | Existing test evidence | Gap |
659
642
  |---|---|---|