wxcli 1.2.0__py3-none-any.whl
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.
- wxcli/__init__.py +4 -0
- wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
- wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
- wxcli/_playbook/.claude/rules/cleanup.md +29 -0
- wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
- wxcli/_playbook/.claude/rules/org-health.md +14 -0
- wxcli/_playbook/.claude/settings.json +8 -0
- wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
- wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
- wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
- wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
- wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
- wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
- wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
- wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
- wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
- wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
- wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
- wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
- wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
- wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
- wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
- wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
- wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
- wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
- wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
- wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
- wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
- wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
- wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
- wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
- wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
- wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
- wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
- wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
- wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
- wxcli/_playbook/CLAUDE.md +373 -0
- wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
- wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
- wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
- wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
- wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
- wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
- wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
- wxcli/_playbook/docs/reference/admin-partner.md +357 -0
- wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
- wxcli/_playbook/docs/reference/authentication.md +965 -0
- wxcli/_playbook/docs/reference/call-control.md +1205 -0
- wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
- wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
- wxcli/_playbook/docs/reference/call-routing.md +2304 -0
- wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
- wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
- wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
- wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
- wxcli/_playbook/docs/reference/devices-core.md +1869 -0
- wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
- wxcli/_playbook/docs/reference/devices-platform.md +467 -0
- wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
- wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
- wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
- wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
- wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
- wxcli/_playbook/docs/reference/meetings-content.md +473 -0
- wxcli/_playbook/docs/reference/meetings-core.md +903 -0
- wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
- wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
- wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
- wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
- wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
- wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
- wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
- wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
- wxcli/_playbook/docs/reference/provisioning.md +1366 -0
- wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
- wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
- wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
- wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
- wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
- wxcli/_version.py +24 -0
- wxcli/auth.py +137 -0
- wxcli/commands/__init__.py +0 -0
- wxcli/commands/_registry.py +181 -0
- wxcli/commands/activation_email.py +103 -0
- wxcli/commands/admin_recordings.py +585 -0
- wxcli/commands/analytics.py +105 -0
- wxcli/commands/announcement_playlists.py +219 -0
- wxcli/commands/announcements.py +519 -0
- wxcli/commands/archive_users.py +36 -0
- wxcli/commands/attachment_actions.py +60 -0
- wxcli/commands/audit_events.py +83 -0
- wxcli/commands/authorizations.py +113 -0
- wxcli/commands/auto_attendant.py +642 -0
- wxcli/commands/broadworks_billing_reports.py +126 -0
- wxcli/commands/broadworks_enterprises.py +160 -0
- wxcli/commands/broadworks_subscribers.py +319 -0
- wxcli/commands/broadworks_workspaces.py +108 -0
- wxcli/commands/call_controls.py +1304 -0
- wxcli/commands/call_park.py +494 -0
- wxcli/commands/call_pickup.py +229 -0
- wxcli/commands/call_queue.py +1878 -0
- wxcli/commands/call_recording.py +707 -0
- wxcli/commands/call_routing.py +1610 -0
- wxcli/commands/call_settings_for_me_phase_5.py +212 -0
- wxcli/commands/caller_reputation.py +169 -0
- wxcli/commands/calling_service.py +305 -0
- wxcli/commands/cc_address_book.py +770 -0
- wxcli/commands/cc_agent_greetings.py +242 -0
- wxcli/commands/cc_agent_summaries.py +39 -0
- wxcli/commands/cc_agent_wellbeing.py +216 -0
- wxcli/commands/cc_agents.py +425 -0
- wxcli/commands/cc_ai_assistant.py +55 -0
- wxcli/commands/cc_ai_feature.py +294 -0
- wxcli/commands/cc_audio_files.py +149 -0
- wxcli/commands/cc_auto_csat.py +311 -0
- wxcli/commands/cc_aux_code.py +458 -0
- wxcli/commands/cc_business_hour.py +353 -0
- wxcli/commands/cc_call_monitoring.py +228 -0
- wxcli/commands/cc_callbacks.py +194 -0
- wxcli/commands/cc_campaign.py +212 -0
- wxcli/commands/cc_captures.py +39 -0
- wxcli/commands/cc_contact_list.py +169 -0
- wxcli/commands/cc_contact_number.py +295 -0
- wxcli/commands/cc_data_sources.py +235 -0
- wxcli/commands/cc_desktop_layout.py +380 -0
- wxcli/commands/cc_desktop_profile.py +322 -0
- wxcli/commands/cc_dial_number.py +511 -0
- wxcli/commands/cc_dial_plan.py +347 -0
- wxcli/commands/cc_dnc.py +101 -0
- wxcli/commands/cc_entry_point.py +545 -0
- wxcli/commands/cc_ewt.py +51 -0
- wxcli/commands/cc_flow.py +477 -0
- wxcli/commands/cc_global_vars.py +430 -0
- wxcli/commands/cc_holiday_list.py +335 -0
- wxcli/commands/cc_journey.py +1261 -0
- wxcli/commands/cc_legacy_flows.py +49 -0
- wxcli/commands/cc_multimedia_profile.py +436 -0
- wxcli/commands/cc_notification.py +51 -0
- wxcli/commands/cc_outdial_ani.py +604 -0
- wxcli/commands/cc_overrides.py +341 -0
- wxcli/commands/cc_queue.py +1083 -0
- wxcli/commands/cc_queue_stats.py +55 -0
- wxcli/commands/cc_realtime.py +51 -0
- wxcli/commands/cc_resource_collection.py +312 -0
- wxcli/commands/cc_search.py +46 -0
- wxcli/commands/cc_site.py +400 -0
- wxcli/commands/cc_skill.py +350 -0
- wxcli/commands/cc_skill_profile.py +289 -0
- wxcli/commands/cc_subscriptions.py +426 -0
- wxcli/commands/cc_summaries.py +130 -0
- wxcli/commands/cc_tasks.py +844 -0
- wxcli/commands/cc_team.py +325 -0
- wxcli/commands/cc_user_profiles.py +349 -0
- wxcli/commands/cc_users.py +701 -0
- wxcli/commands/cc_work_types.py +363 -0
- wxcli/commands/cdr.py +89 -0
- wxcli/commands/classifications.py +38 -0
- wxcli/commands/cleanup.py +1427 -0
- wxcli/commands/client_settings.py +72 -0
- wxcli/commands/conference.py +328 -0
- wxcli/commands/configure.py +72 -0
- wxcli/commands/converged_recordings.py +347 -0
- wxcli/commands/converged_recordings_export.py +310 -0
- wxcli/commands/cq_playlists.py +42 -0
- wxcli/commands/cucm.py +2794 -0
- wxcli/commands/cucm_config.py +129 -0
- wxcli/commands/customer_assist.py +373 -0
- wxcli/commands/data_sources.py +227 -0
- wxcli/commands/dect_devices.py +787 -0
- wxcli/commands/device_configurations.py +77 -0
- wxcli/commands/device_dynamic_settings.py +320 -0
- wxcli/commands/device_settings.py +1489 -0
- wxcli/commands/devices.py +280 -0
- wxcli/commands/domains.py +142 -0
- wxcli/commands/ecm.py +178 -0
- wxcli/commands/emergency_services.py +827 -0
- wxcli/commands/events.py +83 -0
- wxcli/commands/external_voicemail.py +52 -0
- wxcli/commands/groups.py +206 -0
- wxcli/commands/guest_management.py +76 -0
- wxcli/commands/hds.py +340 -0
- wxcli/commands/hot_desk.py +67 -0
- wxcli/commands/hot_desking_members.py +118 -0
- wxcli/commands/hot_desking_portal.py +124 -0
- wxcli/commands/hunt_group.py +577 -0
- wxcli/commands/hybrid_clusters.py +71 -0
- wxcli/commands/hybrid_connectors.py +67 -0
- wxcli/commands/identity_org.py +159 -0
- wxcli/commands/init_playbook.py +155 -0
- wxcli/commands/licenses.py +106 -0
- wxcli/commands/live_monitoring.py +40 -0
- wxcli/commands/location_call_handling.py +577 -0
- wxcli/commands/location_schedules.py +341 -0
- wxcli/commands/location_settings.py +1297 -0
- wxcli/commands/location_voicemail.py +494 -0
- wxcli/commands/locations.py +336 -0
- wxcli/commands/meeting_captions.py +110 -0
- wxcli/commands/meeting_chats.py +63 -0
- wxcli/commands/meeting_invitees.py +234 -0
- wxcli/commands/meeting_messages.py +28 -0
- wxcli/commands/meeting_participants.py +278 -0
- wxcli/commands/meeting_polls.py +111 -0
- wxcli/commands/meeting_preferences.py +515 -0
- wxcli/commands/meeting_qa.py +78 -0
- wxcli/commands/meeting_qualities.py +43 -0
- wxcli/commands/meeting_reports.py +101 -0
- wxcli/commands/meeting_session_types.py +105 -0
- wxcli/commands/meeting_site.py +57 -0
- wxcli/commands/meeting_slido.py +44 -0
- wxcli/commands/meeting_summaries.py +92 -0
- wxcli/commands/meeting_tracking_codes.py +233 -0
- wxcli/commands/meeting_transcripts.py +230 -0
- wxcli/commands/meetings.py +1997 -0
- wxcli/commands/memberships.py +164 -0
- wxcli/commands/messages.py +213 -0
- wxcli/commands/mode_management.py +244 -0
- wxcli/commands/my_call_settings.py +3577 -0
- wxcli/commands/numbers.py +405 -0
- wxcli/commands/operating_modes.py +410 -0
- wxcli/commands/org_contacts.py +284 -0
- wxcli/commands/org_health_cli.py +55 -0
- wxcli/commands/org_settings.py +71 -0
- wxcli/commands/organizations.py +83 -0
- wxcli/commands/paging_group.py +257 -0
- wxcli/commands/partner_admins.py +141 -0
- wxcli/commands/partner_reports.py +188 -0
- wxcli/commands/partner_tags.py +216 -0
- wxcli/commands/people.py +279 -0
- wxcli/commands/person_call_settings.py +71 -0
- wxcli/commands/pstn.py +280 -0
- wxcli/commands/recording_report.py +154 -0
- wxcli/commands/report_templates.py +38 -0
- wxcli/commands/reports.py +144 -0
- wxcli/commands/resource_group_memberships.py +160 -0
- wxcli/commands/resource_groups.py +67 -0
- wxcli/commands/roles.py +63 -0
- wxcli/commands/room_tabs.py +160 -0
- wxcli/commands/rooms.py +225 -0
- wxcli/commands/scim_bulk.py +46 -0
- wxcli/commands/scim_groups.py +246 -0
- wxcli/commands/scim_schemas.py +82 -0
- wxcli/commands/scim_users.py +283 -0
- wxcli/commands/security_audit.py +54 -0
- wxcli/commands/service_apps.py +51 -0
- wxcli/commands/single_number_reach.py +209 -0
- wxcli/commands/team_memberships.py +155 -0
- wxcli/commands/teams.py +153 -0
- wxcli/commands/ucm_profile.py +42 -0
- wxcli/commands/update.py +219 -0
- wxcli/commands/user_settings.py +5116 -0
- wxcli/commands/video_mesh.py +1090 -0
- wxcli/commands/virtual_extensions.py +502 -0
- wxcli/commands/virtual_line_settings.py +2072 -0
- wxcli/commands/webhooks.py +176 -0
- wxcli/commands/wholesale_billing_reports.py +147 -0
- wxcli/commands/wholesale_provisioning.py +523 -0
- wxcli/commands/workspace_locations.py +339 -0
- wxcli/commands/workspace_metrics.py +103 -0
- wxcli/commands/workspace_personalization.py +70 -0
- wxcli/commands/workspace_settings.py +3347 -0
- wxcli/commands/workspaces.py +279 -0
- wxcli/commands/xapi.py +114 -0
- wxcli/config.py +139 -0
- wxcli/errors.py +77 -0
- wxcli/main.py +210 -0
- wxcli/migration/CLAUDE.md +106 -0
- wxcli/migration/__init__.py +1 -0
- wxcli/migration/advisory/CLAUDE.md +196 -0
- wxcli/migration/advisory/__init__.py +46 -0
- wxcli/migration/advisory/advisor.py +107 -0
- wxcli/migration/advisory/advisory_patterns.py +2552 -0
- wxcli/migration/advisory/recommendation_rules.py +835 -0
- wxcli/migration/cucm/CLAUDE.md +74 -0
- wxcli/migration/cucm/__init__.py +5 -0
- wxcli/migration/cucm/connection.py +265 -0
- wxcli/migration/cucm/discovery.py +225 -0
- wxcli/migration/cucm/extractors/__init__.py +1 -0
- wxcli/migration/cucm/extractors/announcements.py +92 -0
- wxcli/migration/cucm/extractors/base.py +90 -0
- wxcli/migration/cucm/extractors/device_profiles.py +98 -0
- wxcli/migration/cucm/extractors/devices.py +193 -0
- wxcli/migration/cucm/extractors/e911.py +103 -0
- wxcli/migration/cucm/extractors/features.py +309 -0
- wxcli/migration/cucm/extractors/helpers.py +73 -0
- wxcli/migration/cucm/extractors/informational.py +295 -0
- wxcli/migration/cucm/extractors/locations.py +221 -0
- wxcli/migration/cucm/extractors/moh.py +100 -0
- wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
- wxcli/migration/cucm/extractors/routing.py +493 -0
- wxcli/migration/cucm/extractors/shared_lines.py +146 -0
- wxcli/migration/cucm/extractors/templates.py +229 -0
- wxcli/migration/cucm/extractors/tier4.py +173 -0
- wxcli/migration/cucm/extractors/users.py +240 -0
- wxcli/migration/cucm/extractors/voicemail.py +243 -0
- wxcli/migration/cucm/extractors/workspaces.py +88 -0
- wxcli/migration/cucm/unity_connection.py +304 -0
- wxcli/migration/execute/CLAUDE.md +372 -0
- wxcli/migration/execute/__init__.py +303 -0
- wxcli/migration/execute/batch.py +277 -0
- wxcli/migration/execute/dependency.py +483 -0
- wxcli/migration/execute/engine.py +964 -0
- wxcli/migration/execute/handlers.py +2232 -0
- wxcli/migration/execute/planner.py +1939 -0
- wxcli/migration/execute/runtime.py +571 -0
- wxcli/migration/export/CLAUDE.md +49 -0
- wxcli/migration/export/__init__.py +8 -0
- wxcli/migration/export/csv_export.py +126 -0
- wxcli/migration/export/deployment_plan.py +479 -0
- wxcli/migration/export/json_export.py +60 -0
- wxcli/migration/models.py +941 -0
- wxcli/migration/phone_models.py +50 -0
- wxcli/migration/preflight/CLAUDE.md +52 -0
- wxcli/migration/preflight/__init__.py +89 -0
- wxcli/migration/preflight/checks.py +911 -0
- wxcli/migration/preflight/runner.py +293 -0
- wxcli/migration/rate_limiter.py +144 -0
- wxcli/migration/report/CLAUDE.md +245 -0
- wxcli/migration/report/__init__.py +7 -0
- wxcli/migration/report/appendix.py +2437 -0
- wxcli/migration/report/assembler.py +183 -0
- wxcli/migration/report/charts.py +263 -0
- wxcli/migration/report/executive.py +776 -0
- wxcli/migration/report/explainer.py +704 -0
- wxcli/migration/report/helpers.py +74 -0
- wxcli/migration/report/ingest.py +152 -0
- wxcli/migration/report/notice_templates.py +192 -0
- wxcli/migration/report/score.py +375 -0
- wxcli/migration/report/styles.py +1052 -0
- wxcli/migration/report/user_diff.py +1052 -0
- wxcli/migration/report/user_notice.py +425 -0
- wxcli/migration/state.py +139 -0
- wxcli/migration/store.py +860 -0
- wxcli/migration/transform/CLAUDE.md +107 -0
- wxcli/migration/transform/__init__.py +12 -0
- wxcli/migration/transform/analysis_pipeline.py +453 -0
- wxcli/migration/transform/analyzers/__init__.py +142 -0
- wxcli/migration/transform/analyzers/css_permission.py +189 -0
- wxcli/migration/transform/analyzers/css_routing.py +335 -0
- wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
- wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
- wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
- wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
- wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
- wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
- wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
- wxcli/migration/transform/analyzers/missing_data.py +300 -0
- wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
- wxcli/migration/transform/analyzers/shared_line.py +170 -0
- wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
- wxcli/migration/transform/analyzers/workspace_license.py +212 -0
- wxcli/migration/transform/cross_reference.py +1136 -0
- wxcli/migration/transform/cucm_pattern.py +246 -0
- wxcli/migration/transform/decisions.py +301 -0
- wxcli/migration/transform/e164.py +145 -0
- wxcli/migration/transform/engine.py +256 -0
- wxcli/migration/transform/mappers/CLAUDE.md +123 -0
- wxcli/migration/transform/mappers/__init__.py +76 -0
- wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
- wxcli/migration/transform/mappers/base.py +190 -0
- wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
- wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
- wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
- wxcli/migration/transform/mappers/css_mapper.py +868 -0
- wxcli/migration/transform/mappers/dect_mapper.py +367 -0
- wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
- wxcli/migration/transform/mappers/device_mapper.py +227 -0
- wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
- wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
- wxcli/migration/transform/mappers/e911_mapper.py +129 -0
- wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
- wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
- wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
- wxcli/migration/transform/mappers/line_mapper.py +310 -0
- wxcli/migration/transform/mappers/location_mapper.py +235 -0
- wxcli/migration/transform/mappers/moh_mapper.py +114 -0
- wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
- wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
- wxcli/migration/transform/mappers/routing_mapper.py +821 -0
- wxcli/migration/transform/mappers/snr_mapper.py +201 -0
- wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
- wxcli/migration/transform/mappers/user_mapper.py +264 -0
- wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
- wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
- wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
- wxcli/migration/transform/normalizers.py +2008 -0
- wxcli/migration/transform/pattern_converter.py +106 -0
- wxcli/migration/transform/pipeline.py +271 -0
- wxcli/migration/transform/rules.py +255 -0
- wxcli/org_health/CLAUDE.md +63 -0
- wxcli/org_health/__init__.py +7 -0
- wxcli/org_health/analyze.py +93 -0
- wxcli/org_health/checks.py +458 -0
- wxcli/org_health/collector.py +62 -0
- wxcli/org_health/models.py +78 -0
- wxcli/org_health/report.py +300 -0
- wxcli/output.py +101 -0
- wxcli-1.2.0.dist-info/METADATA +505 -0
- wxcli-1.2.0.dist-info/RECORD +413 -0
- wxcli-1.2.0.dist-info/WHEEL +5 -0
- wxcli-1.2.0.dist-info/entry_points.txt +2 -0
- wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
- wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
- wxcli-1.2.0.dist-info/scm_version.json +8 -0
- wxcli-1.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: manage-licensing
|
|
3
|
+
description: |
|
|
4
|
+
Audit, assign, and reclaim Webex licenses across the organization.
|
|
5
|
+
Covers license inventory, usage analysis, unused license reports, capacity checks,
|
|
6
|
+
bulk assignment, and license reclamation from inactive users.
|
|
7
|
+
NOT for: initial user provisioning with licenses (use provision-calling) or
|
|
8
|
+
resource deletion (use teardown).
|
|
9
|
+
allowed-tools: Read, Grep, Glob, Bash
|
|
10
|
+
argument-hint: [operation — e.g. "audit usage", "assign licenses", "reclaim unused", "check capacity"]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Manage Licensing Workflow
|
|
14
|
+
|
|
15
|
+
**Checkpoint — do NOT proceed until you can answer these:**
|
|
16
|
+
1. What API method assigns licenses to users? (Answer: PATCH `/licenses/users` — not PUT. The body uses `add`/`remove` operations with license IDs and user IDs.)
|
|
17
|
+
2. What must you include when assigning a Webex Calling license? (Answer: Either an extension or phone number — the PATCH call requires one of these for calling licenses or it will fail.)
|
|
18
|
+
|
|
19
|
+
If you cannot answer both, you skipped reading this skill. Go back and read it.
|
|
20
|
+
|
|
21
|
+
## Step 1: Load references
|
|
22
|
+
|
|
23
|
+
1. Read `docs/reference/admin-licensing.md` for license API patterns, PATCH body schema, and error codes
|
|
24
|
+
2. Read `docs/reference/provisioning.md` § "Licenses API" (and § "Provisioning Workflow" for how license assignment ties to user creation) — it has a Table of Contents with section anchors; load only those sections, not the whole doc
|
|
25
|
+
|
|
26
|
+
**Mandatory --help verification:** Before constructing any wxcli command, run `wxcli <group> --help` to verify the subcommand exists, then `wxcli <group> <subcommand> --help` to verify the exact flags. Do NOT rely on examples in this skill or reference docs — the CLI is auto-generated and flag names may differ from what documentation suggests.
|
|
27
|
+
|
|
28
|
+
## Step 2: Verify auth token is working
|
|
29
|
+
|
|
30
|
+
Before any licensing operation, confirm the token is valid and has the required scopes.
|
|
31
|
+
|
|
32
|
+
### Required scopes by operation
|
|
33
|
+
|
|
34
|
+
| Operation | Scope(s) |
|
|
35
|
+
|-----------|----------|
|
|
36
|
+
| List/view licenses | Admin token (full or read-only admin) |
|
|
37
|
+
| Assign/remove licenses (PATCH) | Admin token (full admin) |
|
|
38
|
+
| List people (for cross-reference) | `spark-admin:people_read` |
|
|
39
|
+
|
|
40
|
+
### Verification sequence
|
|
41
|
+
|
|
42
|
+
**2a. Check token identity:**
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
wxcli whoami
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Inspect the output:
|
|
49
|
+
- Confirm a valid user/admin identity is returned (display name, org ID present).
|
|
50
|
+
- If this fails with 401 — token is expired or missing. Run `wxcli configure` or check `~/.wxcli/config.json`.
|
|
51
|
+
- If this fails with 403 — token exists but lacks permissions. You may have a user-level token instead of an admin token.
|
|
52
|
+
- Personal access tokens last 12 hours. Service app tokens vary by grant type.
|
|
53
|
+
|
|
54
|
+
**2b. Verify admin scope by exercising the license API:**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
wxcli licenses list
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Inspect the output:
|
|
61
|
+
- **Success (license table returned):** Admin read scope confirmed. Proceed.
|
|
62
|
+
- **403 Forbidden:** Token is not an admin token, or the admin role is insufficient. Stop and resolve.
|
|
63
|
+
- **401 Unauthorized:** Token is invalid or expired. Re-run `wxcli configure`.
|
|
64
|
+
- **Empty result (no licenses):** Unusual — confirm org ID is correct via `wxcli whoami` output.
|
|
65
|
+
|
|
66
|
+
**2c. For write operations (assign/remove), verify full admin:**
|
|
67
|
+
|
|
68
|
+
If the user's operation requires assignment or removal, confirm the token is a **full admin** token (not read-only admin). Read-only admins can list licenses but cannot PATCH. The only reliable test is to note the admin role from `wxcli whoami` output, or to attempt the operation and handle a 403.
|
|
69
|
+
|
|
70
|
+
### Gate
|
|
71
|
+
|
|
72
|
+
**Do not proceed until token confirmed valid.** Both `wxcli whoami` and `wxcli licenses list` must succeed before moving to Step 3. If either fails, stop and troubleshoot auth:
|
|
73
|
+
- Token expired — re-run `wxcli configure` with a fresh token
|
|
74
|
+
- Token not configured — run `wxcli configure` or check `~/.wxcli/config.json`
|
|
75
|
+
- Token lacks admin access — read-only admins can list but cannot assign/remove licenses
|
|
76
|
+
- Wrong org — verify the org ID in `wxcli whoami` matches the target organization
|
|
77
|
+
|
|
78
|
+
## Step 3: Determine the operation
|
|
79
|
+
|
|
80
|
+
Ask the user which licensing operation they need. The six supported operations are:
|
|
81
|
+
|
|
82
|
+
| Operation | What It Does | CLI Group |
|
|
83
|
+
|-----------|-------------|-----------|
|
|
84
|
+
| **License inventory** | See all licenses and usage counts | `licenses list` |
|
|
85
|
+
| **License details** | Get details for a specific license | `licenses show` |
|
|
86
|
+
| **Assign licenses** | Add licenses to users | `licenses update` (PATCH with `--json-body`) |
|
|
87
|
+
| **Usage audit** | Find unused/unassigned licenses | `licenses` + `people` (cross-reference) |
|
|
88
|
+
| **Reclaim licenses** | Remove licenses from inactive users | `licenses update` + `people` |
|
|
89
|
+
| **Calling license check** | Quick calling-focused license list | `licenses list -o json` + client-side filter (no --calling-only flag) |
|
|
90
|
+
|
|
91
|
+
> Group naming: `licenses` is the canonical group (generated). `licenses-api` still works as a deprecated alias for one release (renamed 2026-07-02).
|
|
92
|
+
|
|
93
|
+
Confirm with the user before proceeding:
|
|
94
|
+
- **Which operation** from the table above
|
|
95
|
+
- **Target details** (license type, user emails, usage threshold, etc.)
|
|
96
|
+
- **For reclamation**: criteria for "inactive" (days since last login, specific users, etc.)
|
|
97
|
+
|
|
98
|
+
## Step 4: Check prerequisites
|
|
99
|
+
|
|
100
|
+
Run these checks based on the operation. **Stop and report** if any prerequisite fails.
|
|
101
|
+
|
|
102
|
+
### For license inventory or audit:
|
|
103
|
+
```bash
|
|
104
|
+
# List all licenses — verify API access works
|
|
105
|
+
wxcli licenses list
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### For license assignment:
|
|
109
|
+
```bash
|
|
110
|
+
# 1. Find the target license and check capacity
|
|
111
|
+
wxcli licenses list -o json
|
|
112
|
+
# Look for the target license name — confirm consumed < total
|
|
113
|
+
|
|
114
|
+
# 2. Verify the target user exists
|
|
115
|
+
wxcli people list --email user@example.com -o json
|
|
116
|
+
|
|
117
|
+
# 3. For calling licenses: verify location exists
|
|
118
|
+
wxcli locations list --calling-only
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### For license reclamation:
|
|
122
|
+
```bash
|
|
123
|
+
# 1. Identify the license to reclaim
|
|
124
|
+
wxcli licenses list -o json
|
|
125
|
+
|
|
126
|
+
# 2. List users currently assigned to that license
|
|
127
|
+
wxcli licenses show "LICENSE_ID" --include-assigned-to user -o json
|
|
128
|
+
|
|
129
|
+
# 3. Cross-reference user status
|
|
130
|
+
wxcli people list -o json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Step 5: Build plan — [SHOW BEFORE EXECUTING]
|
|
134
|
+
|
|
135
|
+
**Present the plan to the user and wait for approval.** Never execute write operations without confirmation.
|
|
136
|
+
|
|
137
|
+
Format the plan as:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
=== Licensing Plan ===
|
|
141
|
+
|
|
142
|
+
Operation: [Assign License / Reclaim License / Audit Usage / etc.]
|
|
143
|
+
|
|
144
|
+
Target:
|
|
145
|
+
- [specific details — license name, user emails, criteria]
|
|
146
|
+
|
|
147
|
+
Steps:
|
|
148
|
+
1. [First CLI command — what it does]
|
|
149
|
+
2. [Second CLI command — what it does]
|
|
150
|
+
3. Verify: [what we'll check after]
|
|
151
|
+
|
|
152
|
+
Prerequisites verified:
|
|
153
|
+
✓ Auth token valid (authenticated as [name])
|
|
154
|
+
✓ License available: [name] ([consumed]/[total])
|
|
155
|
+
✓ Target user exists: [email] ([person_id])
|
|
156
|
+
✓ [any other checks]
|
|
157
|
+
|
|
158
|
+
Proceed? [wait for user confirmation]
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Step 6: Execute the licensing operation
|
|
162
|
+
|
|
163
|
+
### Operation A: License Inventory
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Quick table view of all licenses
|
|
167
|
+
wxcli licenses list
|
|
168
|
+
|
|
169
|
+
# Calling-only quick view (no --calling-only flag exists — filter client-side)
|
|
170
|
+
wxcli licenses list -o json | python3.11 -c "
|
|
171
|
+
import json, sys
|
|
172
|
+
for lic in json.load(sys.stdin):
|
|
173
|
+
if 'calling' in lic['name'].lower():
|
|
174
|
+
print(f\"{lic['name']}: {lic.get('consumedUnits', 0)}/{lic.get('totalUnits', 0)}\")
|
|
175
|
+
"
|
|
176
|
+
|
|
177
|
+
# Detailed view with availability calculation
|
|
178
|
+
wxcli licenses list -o json | python3.11 -c "
|
|
179
|
+
import json, sys
|
|
180
|
+
data = json.load(sys.stdin)
|
|
181
|
+
for lic in data:
|
|
182
|
+
avail = lic.get('totalUnits', 0) - lic.get('consumedUnits', 0)
|
|
183
|
+
print(f\"{lic['name']}: {lic.get('consumedUnits', 0)}/{lic.get('totalUnits', 0)} (available: {avail})\")
|
|
184
|
+
"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Operation B: License Details
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Basic details
|
|
191
|
+
wxcli licenses show "LICENSE_ID"
|
|
192
|
+
|
|
193
|
+
# With list of assigned users
|
|
194
|
+
wxcli licenses show "LICENSE_ID" --include-assigned-to user -o json
|
|
195
|
+
|
|
196
|
+
# Paginate assigned users (max 300 per page)
|
|
197
|
+
wxcli licenses show "LICENSE_ID" --include-assigned-to user --limit 100
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Operation C: Assign a Non-Calling License
|
|
201
|
+
|
|
202
|
+
For Meetings, Messaging, or other non-calling licenses. No `properties` block needed.
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
wxcli licenses update --email "user@example.com" --json-body '{
|
|
206
|
+
"email": "user@example.com",
|
|
207
|
+
"licenses": [
|
|
208
|
+
{"id": "LICENSE_ID", "operation": "add"}
|
|
209
|
+
]
|
|
210
|
+
}'
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Operation D: Assign a Calling License
|
|
214
|
+
|
|
215
|
+
Calling licenses require `properties` with at least `phoneNumber` or `extension`. If `phoneNumber` is omitted, `locationId` is mandatory.
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# With extension and location (most common)
|
|
219
|
+
wxcli licenses update --email "user@example.com" --json-body '{
|
|
220
|
+
"email": "user@example.com",
|
|
221
|
+
"licenses": [
|
|
222
|
+
{
|
|
223
|
+
"id": "CALLING_PRO_LICENSE_ID",
|
|
224
|
+
"operation": "add",
|
|
225
|
+
"properties": {
|
|
226
|
+
"locationId": "LOCATION_ID",
|
|
227
|
+
"extension": "1001"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
]
|
|
231
|
+
}'
|
|
232
|
+
|
|
233
|
+
# With phone number and extension
|
|
234
|
+
wxcli licenses update --email "user@example.com" --json-body '{
|
|
235
|
+
"email": "user@example.com",
|
|
236
|
+
"licenses": [
|
|
237
|
+
{
|
|
238
|
+
"id": "CALLING_PRO_LICENSE_ID",
|
|
239
|
+
"operation": "add",
|
|
240
|
+
"properties": {
|
|
241
|
+
"locationId": "LOCATION_ID",
|
|
242
|
+
"phoneNumber": "+14085551234",
|
|
243
|
+
"extension": "1001"
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
]
|
|
247
|
+
}'
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Key constraints:**
|
|
251
|
+
- `locationId` is **write-once** — can only be set on initial calling license assignment, cannot be changed after
|
|
252
|
+
- `extension` value must NOT include the location routing prefix
|
|
253
|
+
- Either `phoneNumber` or `extension` is mandatory for calling licenses
|
|
254
|
+
- To move a user to a new location: remove calling license, then re-add with new location (this is destructive)
|
|
255
|
+
|
|
256
|
+
### Operation E: Remove a License
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
wxcli licenses update --email "user@example.com" --json-body '{
|
|
260
|
+
"email": "user@example.com",
|
|
261
|
+
"licenses": [
|
|
262
|
+
{"id": "LICENSE_ID", "operation": "remove"}
|
|
263
|
+
]
|
|
264
|
+
}'
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**WARNING:** Removing a Calling license is destructive. ALL calling configuration is deleted: extension, phone number, call forwarding rules, voicemail settings, monitoring lists, and device associations. There is no undo. Always document the user's settings before removing a calling license.
|
|
268
|
+
|
|
269
|
+
### Operation F: Add and Remove in One Call
|
|
270
|
+
|
|
271
|
+
Swap licenses (e.g., upgrade from Standard to Professional) in a single PATCH:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
wxcli licenses update --email "user@example.com" --json-body '{
|
|
275
|
+
"email": "user@example.com",
|
|
276
|
+
"licenses": [
|
|
277
|
+
{
|
|
278
|
+
"id": "NEW_CALLING_PRO_LICENSE_ID",
|
|
279
|
+
"operation": "add",
|
|
280
|
+
"properties": {
|
|
281
|
+
"locationId": "LOCATION_ID",
|
|
282
|
+
"extension": "1001"
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
{"id": "OLD_CALLING_STD_LICENSE_ID", "operation": "remove"}
|
|
286
|
+
]
|
|
287
|
+
}'
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Operation G: Usage Audit
|
|
291
|
+
|
|
292
|
+
Cross-reference license inventory with user data to find gaps.
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Step 1: Get license inventory
|
|
296
|
+
wxcli licenses list -o json
|
|
297
|
+
|
|
298
|
+
# Step 2: For each calling license, list assigned users
|
|
299
|
+
wxcli licenses show "CALLING_LICENSE_ID" --include-assigned-to user -o json
|
|
300
|
+
|
|
301
|
+
# Step 3: List all people to find unlicensed users
|
|
302
|
+
wxcli people list -o json
|
|
303
|
+
|
|
304
|
+
# Step 4: Compare — users in people list without corresponding license assignment
|
|
305
|
+
# are candidates for license assignment or removal from the org
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Operation H: Reclaim Licenses from Inactive Users
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# Step 1: List users holding the target license
|
|
312
|
+
wxcli licenses show "CALLING_LICENSE_ID" --include-assigned-to user -o json
|
|
313
|
+
|
|
314
|
+
# Step 2: Cross-reference with people list to check login activity
|
|
315
|
+
wxcli people list -o json
|
|
316
|
+
# Look for users with lastActivity > N days ago, or status != "active"
|
|
317
|
+
|
|
318
|
+
# Step 3: Document the user's calling settings BEFORE removal
|
|
319
|
+
wxcli users show PERSON_ID -o json
|
|
320
|
+
|
|
321
|
+
# Step 4: Remove the license (after user approval)
|
|
322
|
+
wxcli licenses update --email "inactive.user@example.com" --json-body '{
|
|
323
|
+
"email": "inactive.user@example.com",
|
|
324
|
+
"licenses": [
|
|
325
|
+
{"id": "CALLING_LICENSE_ID", "operation": "remove"}
|
|
326
|
+
]
|
|
327
|
+
}'
|
|
328
|
+
|
|
329
|
+
# Step 5: Verify license was freed
|
|
330
|
+
wxcli licenses show "CALLING_LICENSE_ID"
|
|
331
|
+
# Confirm consumedUnits decreased by 1
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Operation I: Bulk License Assignment
|
|
335
|
+
|
|
336
|
+
For assigning the same license to multiple users, loop the PATCH command:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
LICENSE_ID="<license_id>"
|
|
340
|
+
LOCATION_ID="<location_id>"
|
|
341
|
+
EXT=200
|
|
342
|
+
|
|
343
|
+
for email in user1@example.com user2@example.com user3@example.com; do
|
|
344
|
+
wxcli licenses update --json-body "{
|
|
345
|
+
\"email\": \"$email\",
|
|
346
|
+
\"licenses\": [
|
|
347
|
+
{
|
|
348
|
+
\"id\": \"$LICENSE_ID\",
|
|
349
|
+
\"operation\": \"add\",
|
|
350
|
+
\"properties\": {
|
|
351
|
+
\"locationId\": \"$LOCATION_ID\",
|
|
352
|
+
\"extension\": \"$EXT\"
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
]
|
|
356
|
+
}"
|
|
357
|
+
echo "Assigned to: $email (ext $EXT)"
|
|
358
|
+
EXT=$((EXT + 1))
|
|
359
|
+
done
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
> **Note:** For large batches (50+ users), use the migration engine's async pattern for better performance with concurrent requests and automatic 429 retry handling. For smaller batches, shell loops with `sleep 1` suffice.
|
|
363
|
+
|
|
364
|
+
## Step 7: Verify results
|
|
365
|
+
|
|
366
|
+
Always read back the modified resources to confirm.
|
|
367
|
+
|
|
368
|
+
### Verify a license assignment:
|
|
369
|
+
```bash
|
|
370
|
+
# Check the license's consumed count changed
|
|
371
|
+
wxcli licenses show "LICENSE_ID"
|
|
372
|
+
|
|
373
|
+
# Verify the user appears in the assigned users list
|
|
374
|
+
wxcli licenses show "LICENSE_ID" --include-assigned-to user -o json
|
|
375
|
+
# Search for the target user's email in the output
|
|
376
|
+
|
|
377
|
+
# Verify the user's own record reflects the license
|
|
378
|
+
wxcli users show PERSON_ID -o json
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Verify a license removal:
|
|
382
|
+
```bash
|
|
383
|
+
# Confirm consumed count decreased
|
|
384
|
+
wxcli licenses show "LICENSE_ID"
|
|
385
|
+
|
|
386
|
+
# Confirm user no longer appears in assigned users
|
|
387
|
+
wxcli licenses show "LICENSE_ID" --include-assigned-to user -o json
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Verify bulk operations:
|
|
391
|
+
```bash
|
|
392
|
+
# Check overall capacity after bulk assignment
|
|
393
|
+
wxcli licenses list -o json | python3.11 -c "
|
|
394
|
+
import json, sys
|
|
395
|
+
data = json.load(sys.stdin)
|
|
396
|
+
for lic in data:
|
|
397
|
+
if 'calling' in lic.get('name', '').lower():
|
|
398
|
+
avail = lic.get('totalUnits', 0) - lic.get('consumedUnits', 0)
|
|
399
|
+
print(f\"{lic['name']}: {lic.get('consumedUnits', 0)}/{lic.get('totalUnits', 0)} (available: {avail})\")
|
|
400
|
+
"
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Step 8: Report results
|
|
404
|
+
|
|
405
|
+
Summarize what was done:
|
|
406
|
+
|
|
407
|
+
```
|
|
408
|
+
=== Licensing Operation Complete ===
|
|
409
|
+
|
|
410
|
+
Operation: [what was done]
|
|
411
|
+
Results:
|
|
412
|
+
- [license]: [action] for [user/count] ([status])
|
|
413
|
+
- Capacity: [consumed]/[total] (was [old_consumed]/[total])
|
|
414
|
+
|
|
415
|
+
Verification:
|
|
416
|
+
✓ [what was confirmed]
|
|
417
|
+
|
|
418
|
+
Next steps:
|
|
419
|
+
- [any follow-up actions needed]
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Critical Rules
|
|
425
|
+
|
|
426
|
+
1. **ALWAYS test auth first** -- Run `wxcli whoami` before any licensing call. Do not proceed on auth failure.
|
|
427
|
+
|
|
428
|
+
2. **ALWAYS show plan before executing** -- Present the licensing plan and wait for user confirmation. Never assign or remove licenses without approval.
|
|
429
|
+
|
|
430
|
+
3. **Removing a Calling license is destructive** -- ALL calling configuration is deleted: extension, phone number, call forwarding rules, voicemail settings, monitoring lists, and device associations. There is no undo. Always document settings before removal.
|
|
431
|
+
|
|
432
|
+
4. **License IDs are org-specific base64 strings** -- Never hardcode them. Always retrieve via `wxcli licenses list` first.
|
|
433
|
+
|
|
434
|
+
5. **Calling licenses require `properties`** -- Unlike Meetings or Messaging licenses, Calling license assignment must include `properties` with at least `phoneNumber` or `extension`. If you omit `phoneNumber`, you must provide `locationId`. Error code 400411 indicates missing properties.
|
|
435
|
+
|
|
436
|
+
6. **`locationId` is write-once on calling licenses** -- Can only be set when first assigning a calling license. Cannot be changed after. To move a user, remove calling license and re-add with new location (destructive).
|
|
437
|
+
|
|
438
|
+
7. **`licenses update` confirms "Updated" even on no-op** -- If the user already has the license, the CLI prints "Updated." without error. Always verify the actual state with `licenses show` after assignment.
|
|
439
|
+
|
|
440
|
+
8. **License conflicts are strictly enforced** -- A user cannot hold both Calling Professional and Calling Standard. The API returns specific error codes for each conflict (400404, 400406, 400407, 400410).
|
|
441
|
+
|
|
442
|
+
9. **Attendant Console has a prerequisite** -- Assign Calling Professional before assigning Attendant Console. Error code 400408 if the prerequisite is missing.
|
|
443
|
+
|
|
444
|
+
10. **206 Partial Content is not an error** -- The PATCH endpoint can return HTTP 206 when some licenses succeeded but others failed. Always compare the returned `licenses` array against what was requested.
|
|
445
|
+
|
|
446
|
+
11. **`licenses` (admin spec) vs `licenses` (calling spec)** -- Use `licenses` for assignment/removal and full inventory. Use `licenses` with `--calling-only` for quick calling-license audits.
|
|
447
|
+
|
|
448
|
+
12. **Log all operations** -- Print what you are about to do before each CLI command, and print the result after. This creates an audit trail for troubleshooting.
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## Error Handling
|
|
453
|
+
|
|
454
|
+
When a wxcli command fails:
|
|
455
|
+
|
|
456
|
+
**A. Fix and retry** -- Missing required field, wrong ID, format issue:
|
|
457
|
+
1. Read the full error message
|
|
458
|
+
2. Run `wxcli licenses update --help` to check required flags
|
|
459
|
+
3. Fix the command and retry
|
|
460
|
+
|
|
461
|
+
**B. Skip and continue** -- License already assigned or already removed:
|
|
462
|
+
1. Verify current state: `wxcli licenses show LICENSE_ID --include-assigned-to user -o json`
|
|
463
|
+
2. If state is correct, skip to next operation
|
|
464
|
+
|
|
465
|
+
**C. Escalate** -- Unclear or persistent error:
|
|
466
|
+
1. Run with `--debug` for raw HTTP details
|
|
467
|
+
2. Invoke `/wxc-calling-debug` for systematic diagnosis
|
|
468
|
+
|
|
469
|
+
Licensing-specific errors:
|
|
470
|
+
- 400 with code 400000: License ID not recognized -- re-run `licenses list` to get correct IDs
|
|
471
|
+
- 400 with code 400411: Missing `properties` on calling license -- add `locationId`, `phoneNumber`, or `extension`
|
|
472
|
+
- 400 with code 400404: Cannot hold both Calling Professional and Standard simultaneously -- remove one first
|
|
473
|
+
- 400 with code 400408: Attendant Console requires Calling Professional prerequisite
|
|
474
|
+
- 400 with code 400112: Cannot downgrade Calling Professional to Standard
|
|
475
|
+
- 206: Partial success -- check which licenses in the array failed
|
|
476
|
+
- 403: Token lacks admin write access -- verify admin role
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## Required Scopes Reference
|
|
481
|
+
|
|
482
|
+
| Operation | Scope(s) |
|
|
483
|
+
|-----------|----------|
|
|
484
|
+
| List/view licenses | Admin token (full or read-only admin) |
|
|
485
|
+
| Assign/remove licenses (PATCH) | Admin token (full admin) |
|
|
486
|
+
| List people (for cross-reference) | `spark-admin:people_read` |
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## Two CLI Groups for Licensing
|
|
491
|
+
|
|
492
|
+
| | `licenses` (admin spec) | `licenses` (calling spec) |
|
|
493
|
+
|---|---|---|
|
|
494
|
+
| **Commands** | list, show, update | list, show |
|
|
495
|
+
| **Best for** | Full lifecycle: inventory, details with assigned users, assign, remove | Quick calling-license audit |
|
|
496
|
+
| **Assignment** | Yes -- via `update` with `--json-body` | No -- read-only |
|
|
497
|
+
| **Filter** | No built-in filter (use JSON output + script) | `--calling-only` flag |
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## License Type Quick Reference
|
|
502
|
+
|
|
503
|
+
| License Name Pattern | Type | Properties Required |
|
|
504
|
+
|----------------------|------|---------------------|
|
|
505
|
+
| Webex Calling - Professional | Calling | locationId + (phoneNumber or extension) |
|
|
506
|
+
| Webex Calling - Standard | Calling | locationId + (phoneNumber or extension) |
|
|
507
|
+
| Webex Calling - Common Area | Calling | locationId + (phoneNumber or extension) |
|
|
508
|
+
| CX Essentials | Calling add-on | Requires Calling Professional first |
|
|
509
|
+
| Webex Attendant Console | Calling add-on | Requires Calling Professional first |
|
|
510
|
+
| Webex Meetings | Non-calling | None (optionally siteUrl) |
|
|
511
|
+
| Webex Messaging | Non-calling | None |
|
|
512
|
+
|
|
513
|
+
Match by substring (e.g., `"calling"` in name), not exact string. License names vary by subscription.
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## Cross-Reference
|
|
518
|
+
|
|
519
|
+
For calling license assignment during user provisioning, see the `provision-calling` skill. The `licenses update` command now provides CLI-native license assignment.
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## Context Compaction Recovery
|
|
524
|
+
|
|
525
|
+
If context compacts mid-execution, recover by:
|
|
526
|
+
1. Read `docs/reference/admin-licensing.md` to recover PATCH body format and error codes
|
|
527
|
+
2. Check current license state: `wxcli licenses list -o json`
|
|
528
|
+
3. Resume from the first incomplete step
|