from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional


@dataclass
class Envelope:
    """Frozen cross-source envelope — the only schema contract locked in upfront.

    Additive: new fields may be added but existing ones must not be removed or renamed.
    All fields mirror the `envelope` table in kb-postgres (init/001_envelope.sql).
    """

    id: str
    source: str                              # fastmail | gmail | …
    ts: datetime                             # message date, must be UTC-aware
    raw_ref: str                             # relative path to .eml in archive
    geo: Optional[dict] = None              # null for mails; filled by layer-3 enrich
    entities: list = field(default_factory=list)

    def __post_init__(self) -> None:
        if self.ts.tzinfo is None:
            raise ValueError("Envelope.ts must be timezone-aware (UTC)")
