# 5. Components

### 5.1 CLI Layer

#### Command Groups (Typer)

**Responsibility:** Parse command-line arguments, validate input, invoke services, format output.

**Key Interfaces:**
- `users` - User management commands (list, show, search)
- `numbers` - Phone number commands (list, show, search, assign, unassign, bulk-assign)
- `policies` - Policy commands (list, show, assign)
- `locations` - Location commands (list, show, search)
- `tenants` - Tenant profile commands (list, add, remove, switch, test)
- `auth` - Authentication commands (login, logout, status, refresh)
- `api-check` - Contract validation command

**Dependencies:** All Service layer components, OutputFormatter

**Technology Stack:** Typer, Rich (for output)

### 5.2 Service Layer

#### 5.2.1 UserService

**Responsibility:** Manage user voice configurations - list, search, and retrieve user details.

**Key Interfaces:**
- `list_users(filters, page_size, skip)` → list[UserConfiguration]
- `get_user(user_id)` → UserConfiguration
- `search_users(query)` → list[UserConfiguration]
- `resolve_user(identifier)` → UserConfiguration (by UPN, name, or ID)

**Dependencies:** GraphClient, CacheManager

#### 5.2.2 NumberService

**Responsibility:** Manage phone number inventory - list, search, assign, unassign, update.

**Key Interfaces:**
- `list_numbers(filters, page_size)` → list[NumberAssignment]
- `get_number(phone_number)` → NumberAssignment
- `search_numbers(pattern, status, type)` → list[NumberAssignment]
- `assign_number(user_id, phone_number, number_type, location_id)` → AsyncOperation
- `unassign_number(phone_number, number_type)` → AsyncOperation
- `update_number(phone_number, location_id, network_site_id)` → None
- `poll_operation(operation_id, timeout)` → AsyncOperation

**Dependencies:** GraphClient, LocationService (for validation), CacheManager

#### 5.2.3 PolicyService

**Responsibility:** Manage policy assignments - list available policies, show user policies, assign policies.

**Key Interfaces:**
- `list_policies(policy_type)` → list[Policy] (from CSV)
- `get_user_policies(user_id)` → list[PolicyAssignment] (via UserService)
- `assign_policy(user_id, policy_type, policy_id)` → None
- `validate_policy(policy_type, policy_name)` → bool

**Dependencies:** GraphClient, CacheManager (CSV reading)

#### 5.2.4 LocationService

**Responsibility:** Manage emergency locations from CSV cache - list, search, validate.

**Key Interfaces:**
- `list_locations()` → list[EmergencyLocation]
- `get_location(location_id)` → EmergencyLocation
- `search_locations(query)` → list[EmergencyLocation]
- `validate_location(location_id)` → bool
- `get_cache_age()` → timedelta
- `is_cache_stale()` → bool

**Dependencies:** CacheManager (CSV reading)

#### 5.2.5 TenantService

**Responsibility:** Manage tenant profiles - CRUD operations, switching active tenant.

**Key Interfaces:**
- `list_tenants()` → list[TenantProfile]
- `get_current_tenant()` → TenantProfile
- `switch_tenant(name)` → TenantProfile
- `add_tenant(profile)` → TenantProfile
- `remove_tenant(name)` → None
- `test_connection(name)` → ConnectionTestResult

**Dependencies:** ConfigManager, AuthService

#### 5.2.6 AuthService

**Responsibility:** Handle Microsoft Entra ID authentication - login, token management, refresh.

**Key Interfaces:**
- `login(tenant_profile, force)` → AuthToken
- `logout(tenant_name, all)` → None
- `get_token(tenant_name)` → str (access token)
- `get_status()` → AuthStatus
- `refresh_token(tenant_name)` → AuthToken
- `is_authenticated(tenant_name)` → bool

**Dependencies:** ConfigManager (for tenant config), CacheManager (token storage)

**Technology Stack:** MSAL, certificate/secret handling

### 5.3 Infrastructure Layer

#### 5.3.1 GraphClient

**Responsibility:** HTTP client for Microsoft Graph API with retry, throttling, and error handling.

**Key Interfaces:**
- `get(endpoint, params)` → dict
- `post(endpoint, body)` → dict | AsyncOperation
- `batch(requests)` → list[BatchResponse]
- `get_with_pagination(endpoint, params, max_items)` → AsyncIterator[dict]

**Dependencies:** AuthService (for tokens), CacheManager (response caching)

**Technology Stack:** httpx, exponential backoff, rate limit handling

**Key Behaviors:**
- Automatic retry on 429 (throttled) and 503 (service unavailable)
- Exponential backoff: 3 retries with 1s, 2s, 4s delays
- Request timeout: 30 seconds default
- Automatic token refresh on 401
- Beta API base URL: `https://graph.microsoft.com/beta`

#### 5.3.2 CacheManager

**Responsibility:** Manage all cached data - tokens, API responses, CSV files.

**Key Interfaces:**
- `get_token(tenant_name)` → CachedToken
- `save_token(tenant_name, token)` → None
- `clear_tokens(tenant_name)` → None
- `read_csv(filename)` → list[dict]
- `get_csv_metadata()` → CacheMetadata
- `get_cached_response(key)` → dict | None
- `save_cached_response(key, data, ttl)` → None

**Dependencies:** None (lowest level)

**Technology Stack:** File I/O, JSON, CSV, optional encryption for tokens

**Cache Locations:**
- Config: `~/.teams-phone/config.toml`
- Tokens: `~/.teams-phone/tokens/` (encrypted)
- CSV Cache: `~/.teams-phone/cache/`

#### 5.3.3 ConfigManager

**Responsibility:** Read/write TOML configuration file and tenant profiles.

**Key Interfaces:**
- `load_config()` → Config
- `save_config(config)` → None
- `get_tenant(name)` → TenantProfile
- `set_tenant(name, profile)` → None
- `get_default_tenant()` → str
- `set_default_tenant(name)` → None

**Dependencies:** None (lowest level)

**Technology Stack:** tomli/tomllib, Pydantic models

#### 5.3.4 OutputFormatter

**Responsibility:** Format command output - tables, JSON, progress bars, errors.

**Key Interfaces:**
- `table(data, columns, title)` → None (prints)
- `json(data)` → None (prints)
- `success(message)` → None
- `error(message, remediation)` → None
- `warning(message)` → None
- `progress_bar(total, description)` → ProgressContext

**Dependencies:** None

**Technology Stack:** Rich (tables, progress, colors)

### 5.4 Component Diagram

```mermaid
graph TB
    subgraph "CLI Layer"
        CMD[Typer Commands<br/>users/numbers/policies/locations/tenants/auth]
    end

    subgraph "Service Layer"
        US[UserService]
        NS[NumberService]
        PS[PolicyService]
        LS[LocationService]
        TS[TenantService]
        AS[AuthService]
    end

    subgraph "Infrastructure Layer"
        GC[GraphClient]
        CM[CacheManager]
        CFG[ConfigManager]
        OF[OutputFormatter]
    end

    CMD --> US & NS & PS & LS & TS & AS
    CMD --> OF

    US --> GC & CM
    NS --> GC & CM & LS
    PS --> GC & CM
    LS --> CM
    TS --> CFG & AS
    AS --> CFG & CM

    GC --> AS
    GC --> CM
```

---

