# Task ID: 3

**Title:** Implement Pydantic Models for Configuration

**Status:** pending

**Dependencies:** 1, 2

**Priority:** high

**Description:** Create Pydantic models for tenant profiles, configuration schema, and authentication tokens used by ConfigManager.

**Details:**

Create `src/teams_phone/models/tenant.py`:
```python
from pydantic import BaseModel, ConfigDict, Field
from enum import Enum
from typing import Optional
from uuid import UUID

class AuthMethod(str, Enum):
    CERTIFICATE = "certificate"
    CLIENT_SECRET = "client-secret"

class TenantProfile(BaseModel):
    model_config = ConfigDict(extra="forbid")
    name: str
    tenant_id: UUID
    client_id: UUID
    display_name: str
    auth_method: AuthMethod
    cert_path: Optional[str] = None
    default_location: Optional[str] = None
```

Create `src/teams_phone/models/config.py` with Config model containing defaults, cache settings, and tenant dict.

Create `src/teams_phone/models/auth.py` with CachedToken, AuthStatus models.

**Test Strategy:**

Unit tests validating model creation, extra field rejection (strict mode), serialization/deserialization, and validation errors for invalid data.

---

## Implementation Notes

### Session: 2026-01-28 20:45 - Agent: claude-opus-4-5-20251101

**Status:** Implemented

#### What Was Done
- Created `src/teams_phone/models/tenant.py` with:
  - `AuthMethod(str, Enum)` - certificate and client-secret values
  - `TenantProfile(BaseModel)` - full configuration with UUID fields, strict mode
- Created `src/teams_phone/models/auth.py` with:
  - `AuthStatusType(str, Enum)` - authenticated, unauthenticated, expired states
  - `CachedToken(BaseModel)` - token storage with expiration check method
  - `AuthStatus(BaseModel)` - authentication state tracking
- Created `src/teams_phone/models/config.py` with:
  - `CacheSettings(BaseModel)` - cache configuration with defaults from constants
  - `NetworkSettings(BaseModel)` - HTTP client settings with defaults
  - `Config(BaseModel)` - root configuration model with tenant dict
- Updated `src/teams_phone/models/__init__.py` with all re-exports
- Created `tests/unit/test_models.py` with 34 comprehensive unit tests covering:
  - Enum value validation
  - Model creation (minimal and full)
  - UUID string coercion
  - Extra field rejection (strict mode)
  - Invalid input rejection
  - Serialization (model_dump and model_dump_json)
  - Token expiration logic
  - Default value behavior

#### Key Decisions Made
- **Added CacheSettings and NetworkSettings models**: Split out nested settings for better organization rather than inline dicts
- **Used timezone.utc instead of UTC**: Python 3.11+ has UTC alias but older versions need timezone.utc for broader compatibility
- **CachedToken.is_expired() handles both naive and aware datetimes**: Ensures robust comparison regardless of how expires_at is set
- **AuthStatusType enum added**: Not in original spec but needed for type-safe status field in AuthStatus model

#### Patterns Discovered
- `(str, Enum)` base class pattern makes enums directly usable as strings while preserving type safety
- `ConfigDict(extra="forbid")` essential for all models per coding standards
- `Field(default_factory=...)` for mutable defaults (dict, list, nested models)

#### Open Items for Next Agent
- [ ] Config model may need `populate_by_name=True` if TOML uses different casing
- [ ] Consider adding validation for cert_path existence when auth_method is CERTIFICATE

#### Gotchas and Warnings
- mypy strict mode doesn't allow direct enum-to-string comparison (use `.value` instead)
- datetime.utcnow() is deprecated in Python 3.12+; use datetime.now(timezone.utc)

---
