# Task ID: 28

**Title:** Implement API-Check Contract Validation Command

**Status:** pending

**Dependencies:** 7, 9, 11

**Priority:** medium

**Description:** Create the api-check command for validating Pydantic models against live Graph API responses.

**Details:**

Create `src/teams_phone/cli/api_check.py`:
```python
from teams_phone.models import UserConfiguration, NumberAssignment, AsyncOperation

@app.command("api-check")
def api_check(
    ctx: typer.Context,
    endpoint: Optional[str] = typer.Option(None, help="Check specific endpoint"),
    verbose: bool = typer.Option(False, "--verbose"),
):
    """Validate API contracts against live responses."""
    checks = [
        ("userConfigurations", "/admin/teams/userConfigurations?$top=1", UserConfiguration),
        ("numberAssignments", "/admin/teams/telephoneNumberManagement/numberAssignments?$top=1", NumberAssignment),
    ]
    
    results = []
    for name, endpoint, model in checks:
        try:
            response = await graph_client.get(endpoint)
            items = response.get("value", [response])
            for item in items:
                model.model_validate(item)  # Strict validation
            results.append((name, "PASS", None))
        except ValidationError as e:
            results.append((name, "FAIL", str(e)))
    
    # Display results table
    # Exit with code 8 if any failures
```

This catches API contract drift (new fields added, fields renamed/removed).

**Test Strategy:**

Unit tests with mock responses: pass for matching schema, fail for extra fields (strict mode), fail for missing required fields, proper exit codes.

---

## Implementation Notes

### Session: 2026-01-30 00:15 - Agent: claude-sonnet-4-5-20250929

**Status:** Implemented

#### What Was Done
- Created `src/teams_phone/cli/api_check.py` with the api-check command
- Registered api-check as a standalone command in `src/teams_phone/cli/main.py`
- Created comprehensive unit tests in `tests/unit/test_cli_api_check.py` (12 tests)

#### Key Decisions Made
- **Standalone command vs Typer group**: Implemented as a standalone command registered via `app.command("api-check")(api_check)` since it's a single utility command, not a group of related commands
- **OData stripping**: Duplicated `_strip_odata_metadata()` helper in api_check.py rather than importing from user_service.py to maintain module independence and clearer intent
- **Two endpoints only**: Validated only `userConfigurations` and `numberAssignments` as specified in the task. AsyncOperation model was mentioned in imports but not in the validation list, so it was not included
- **Empty data handling**: Returns PASS with "No data available" message when endpoint has no data (can't fail validation on nothing)

#### Patterns Discovered
- **Enum values use camelCase**: Graph API enum values like `accountType`, `numberType`, etc. use camelCase (`user`, `callingPlan`, `activated`) not TitleCase
- **Command registration pattern**: For standalone commands, use `app.command("name")(function)` instead of `@app.command()` decorator when the function is defined in a separate module

#### Files Created/Modified
- Created: `src/teams_phone/cli/api_check.py` - Main command implementation
- Modified: `src/teams_phone/cli/main.py` - Added import and command registration
- Created: `tests/unit/test_cli_api_check.py` - Unit tests (12 tests)

#### Test Coverage
- `test_api_check_shows_in_help` - Command appears in main help
- `test_api_check_has_own_help` - Has own help text with options
- `test_api_check_pass_all_endpoints` - Happy path for all endpoints
- `test_api_check_fail_extra_field` - Detects extra fields (strict mode)
- `test_api_check_fail_missing_required_field` - Detects missing required fields
- `test_api_check_specific_endpoint` - --endpoint filter works
- `test_api_check_invalid_endpoint` - Rejects invalid endpoint names
- `test_api_check_verbose_shows_details` - --verbose shows error details
- `test_api_check_json_output` - --json outputs structured JSON
- `test_api_check_empty_endpoint_data` - Handles empty data gracefully
- `test_api_check_auth_error` - Handles auth errors appropriately
- `test_api_check_strips_odata_metadata` - Properly strips @odata fields

#### Open Items for Next Agent
- None - task is complete

#### Gotchas and Warnings
- **AuthService signature**: AuthService takes only 2 parameters (config_manager, cache_manager), NOT 3. Tenant resolution is handled internally via config_manager
- **Pydantic enum validation**: Test data must use exact enum values from the model (e.g., `"user"` not `"User"`, `"callingPlan"` not `"CallingPlan"`)

---
