// src/services/voiceDiag/checks/executiveAssistant.js // // Info-only check for the Executive / Executive Assistant feature. // This isn't something a store line would normally be configured // for; when the type is anything other than 'UNASSIGNED', calls can // be filtered/screened through an assistant relationship in ways // that look like "the store phone isn't behaving right". We surface // the current type so an operator can decide whether to unassign it // in Control Hub. No remediation button — this is intentional // executive configuration, we don't auto-flip it. // // Endpoint: GET /v1/people/{personId}/features/executiveAssistant // Scope: spark-admin:people_read // Response shape: { type: 'UNASSIGNED' | 'EXECUTIVE' | 'EXECUTIVE_ASSISTANT' } // // NOTE: Webex has announced a path migration for this endpoint (see // developer.webex.com changelog — /v1/telephony/config/people/{id}/executive // is the new path). When that ships and starts returning 404 on the // legacy path, swap the ENDPOINT constant. Do NOT eagerly switch // before Cisco's cutover window closes — until then only the legacy // path is live. const ENDPOINT = (personId) => `people/${personId}/features/executiveAssistant`; export const executiveAssistantCheck = { id: 'executiveAssistant', label: 'Executive / Assistant', requires: ['personId'], scope: 'spark-admin:people_read', async run(ctx) { const data = await ctx.webex.request('GET', ENDPOINT(ctx.personId)); const type = data?.type || 'UNASSIGNED'; if (type === 'UNASSIGNED') { return { status: 'ok', message: 'No executive / assistant relationship (normal for a store line).', details: { type }, remediation: null, }; } return { status: 'warn', message: `This line is configured as **${type}** in the executive/assistant feature. ` + `Verify this is intentional — otherwise calls may be routed through an ` + `assistant relationship.`, details: { type }, remediation: null, }; }, };