# Task ID: 12

**Title:** Implement Auth CLI Commands

**Status:** done

**Dependencies:** 6, 8, 11

**Priority:** high

**Description:** Create the auth command group with login, logout, status, and refresh commands.

**Details:**

Create `src/teams_phone/cli/auth.py`:
```python
import typer
from teams_phone.services.auth_service import AuthService

auth_app = typer.Typer(name="auth", help="Authentication commands")

@auth_app.command()
def login(
    ctx: typer.Context,
    method: AuthMethod = typer.Option(AuthMethod.CERTIFICATE, help="Auth method"),
    force: bool = typer.Option(False, "--force", help="Force re-authentication"),
):
    """Authenticate to Microsoft Graph API."""
    ...

@auth_app.command()
def logout(
    ctx: typer.Context,
    all_tenants: bool = typer.Option(False, "--all", help="Clear all tenant tokens"),
):
    """Clear cached authentication tokens."""
    ...

@auth_app.command()
def status(ctx: typer.Context):
    """Show current authentication status."""
    ...

@auth_app.command()
def refresh(ctx: typer.Context):
    """Refresh authentication token."""
    ...
```

**Test Strategy:**

Integration tests: test login flow with mocked MSAL, verify token caching, test status output format (table and JSON), test logout clears tokens.

---

## Implementation Notes

### Session: 2026-01-29 16:00 - Agent: claude-sonnet-4-5-20250929

**Status:** Implemented

#### What Was Done
- Created `src/teams_phone/cli/auth.py` with four commands: `status`, `login`, `logout`, `refresh`
- Modified `src/teams_phone/cli/main.py` to import `auth_app` from the new module (replaced placeholder)
- Created `tests/unit/test_cli_auth.py` with 34 comprehensive unit tests

#### Key Decisions Made
- **Simplified login command**: Did not implement `--method`, `--cert-path`, `--cert-thumbprint`, or `--secret` options from CLI spec. The AuthService already uses the tenant profile's configured auth_method and cert_path, so these CLI options would only be useful for overriding config. This can be added in a future enhancement if needed.
- **refresh without --force checks status**: The refresh command first calls `get_status()` to check if token is still valid (AUTHENTICATED). If valid, it informs user and returns. With `--force`, it always calls `refresh_token()` directly.
- **CacheManager instantiation**: Each command creates its own `CacheManager()` instance. This is acceptable since CacheManager is stateless and lightweight.
- **JSON output format**: Used simple dict format for JSON responses (e.g., `{"status": "authenticated", "tenant_id": "..."}`) rather than full Pydantic model dump for login/logout/refresh to keep output focused.

#### Patterns Discovered
- **Error handling pattern**: `try/except TeamsPhoneError` with `formatter.error(e.message, remediation=e.remediation)` followed by `raise typer.Exit(e.exit_code)` - see `src/teams_phone/cli/auth.py:47-49`
- **Service instantiation pattern**: Get `config_manager` via `cli_ctx.get_config_manager()` (lazy init), create `CacheManager()` fresh, then `AuthService(config_manager, cache_manager)`
- **ANSI color codes in tests**: Rich console adds color codes to numeric strings in output. Use `--no-color` flag in tests or use tenant IDs without numbers (e.g., "test-tenant-id-abc") to avoid assertion failures.

#### Open Items for Next Agent
- [ ] Consider adding `--method`, `--cert-path`, `--cert-thumbprint` options to login command to allow overriding tenant profile config
- [ ] Consider adding integration tests that exercise actual AuthService (with mocked MSAL) once other CLI commands are implemented

#### Gotchas and Warnings
- **AuthService.login() returns CachedToken, not AuthToken**: The recon correctly noted this - use `CachedToken` fields like `tenant_id` and `expires_at`
- **get_status() can raise exceptions**: Unlike `is_authenticated()` which catches all errors, `get_status()` propagates `ConfigurationError` and `NotFoundError` - these must be caught in CLI
- **Import inside function**: The `from teams_phone.models import AuthStatusType` import is inside the `refresh` function to avoid circular imports at module level

---
