# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-a-federation-gateway-refuse-to-honor-a-peer-s-trust-anchor-after-policy-renegotiation.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-a-federation-gateway-refuse-to-honor-a-peer-s-trust-anchor-after-policy-renegotiation.warrant.json
# Markdown SHA-256:   7fc27b75b7fd6bf5965d5a94d469d6f48a49efeb56693aa29f9a0540534fed92
# Code AST SHA-256:   3c90df25bd6225205247033aa73bad898a8ce397a6f2e532d37c257dddfcf560
# Verified Classes:   StalePolicyBindingError, TrustAnchor, ActivePolicy
# Defensive Guards:   2 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class StalePolicyBindingError(RuntimeError):
    """Raised when a trust anchor is valid but bound to a superseded policy
    for a capability the active policy now constrains."""


@dataclass(frozen=True)
class TrustAnchor:
    peer_id: str
    policy_epoch: int
    signature_valid: bool


@dataclass(frozen=True)
class ActivePolicy:
    epoch: int
    constrained_capabilities: frozenset


def authorize(anchor: TrustAnchor, policy: ActivePolicy, capability: str) -> bool:
    if not anchor.signature_valid:
        raise StalePolicyBindingError(
            f"anchor for {anchor.peer_id} failed signature verification"
        )
    if anchor.policy_epoch >= policy.epoch:
        return True
    # Anchor predates active policy. Safe only if capability is unconstrained.
    if capability in policy.constrained_capabilities:
        raise StalePolicyBindingError(
            f"anchor epoch {anchor.policy_epoch} < active epoch {policy.epoch} "
            f"for constrained capability {capability!r}; force renegotiation"
        )
    return True
