# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/which-invariants-prevent-cross-org-agent-federation-from-accepting-a-did-document-whose-controller-chain-was-re-anchored-mid-resolution.md
# Remnant Warrant:    https://corpusfetch.com/c/which-invariants-prevent-cross-org-agent-federation-from-accepting-a-did-document-whose-controller-chain-was-re-anchored-mid-resolution.warrant.json
# Markdown SHA-256:   996ffb218b6081745f700ccc5f39644a572bdf56c8fded5e13ea7c95eca42dff
# Code AST SHA-256:   2f49fd5abcef927782767be4be9b4ad7080e58e30ad9f78c1d661c7a27c66ae2
# Verified Classes:   AnchorDivergenceError, AnchorRecord
# Defensive Guards:   7 fail-closed invariants (zero external deps)

from __future__ import annotations

import dataclasses
from typing import Optional


class AnchorDivergenceError(RuntimeError):
    """Raised when a credential cannot be bound to a single, versioned trust anchor."""


@dataclasses.dataclass(frozen=True)
class AnchorRecord:
    did: str
    version: int
    effective_from: float          # epoch seconds
    effective_to: Optional[float]  # None == open-ended
    controller_chain: tuple[str, ...]
    deactivated: bool = False


def validate_credential_against_anchor(
    *,
    credential_issued_at: float,
    document_anchor: AnchorRecord,
    chain_anchor: AnchorRecord,
) -> None:
    # Invariant 1: document and controller chain must describe the same world.
    if document_anchor.version != chain_anchor.version:
        raise AnchorDivergenceError(
            f"anchor split: document v{document_anchor.version} vs "
            f"chain v{chain_anchor.version} for {document_anchor.did}"
        )

    anchor = document_anchor

    # Invariant 3: deactivation is terminal and must not be read as "no authority".
    if anchor.deactivated:
        raise AnchorDivergenceError(
            f"anchor {anchor.did} v{anchor.version} is deactivated; "
            "credential cannot be validated against a dead anchor"
        )

    # Invariant 2: credential issuance must fall inside the anchor's effective interval.
    if credential_issued_at < anchor.effective_from:
        raise AnchorDivergenceError(
            f"credential issued at {credential_issued_at} precedes anchor "
            f"{anchor.did} v{anchor.version} effective_from {anchor.effective_from}"
        )
    if anchor.effective_to is not None and credential_issued_at >= anchor.effective_to:
        raise AnchorDivergenceError(
            f"credential issued at {credential_issued_at} is outside anchor "
            f"{anchor.did} v{anchor.version} interval ending {anchor.effective_to}"
        )


def validate_with_fallback(
    *,
    credential_issued_at: float,
    resolved: list[AnchorRecord],
    method_exposes_versioning: bool,
) -> AnchorRecord:
    if not method_exposes_versioning:
        # Decision boundary: refuse rather than cache across the chain boundary.
        raise AnchorDivergenceError(
            "DID method does not expose version/effective-interval metadata; "
            "federation must be refused or resolved atomically per validation"
        )

    if not resolved:
        raise AnchorDivergenceError("no anchor records resolved")

    # Invariant 4: monotonic version ordering; any regression is a hard error.
    versions = [r.version for r in resolved]
    if versions != sorted(versions):
        raise AnchorDivergenceError(
            f"non-monotonic anchor versions observed: {versions}"
        )

    anchor = resolved[-1]
    validate_credential_against_anchor(
        credential_issued_at=credential_issued_at,
        document_anchor=anchor,
        chain_anchor=anchor,
    )
    return anchor
