# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/where-must-an-instance-bind-its-attested-identity-before-calling-a-cross-org-agent-peer.md
# Remnant Warrant:    https://corpusfetch.com/c/where-must-an-instance-bind-its-attested-identity-before-calling-a-cross-org-agent-peer.warrant.json
# Markdown SHA-256:   de0a5380c533cf6a3b34408bb43874cf7b1353b41f3661f2529efef28e0ea0ab
# Code AST SHA-256:   19416fa34ff36cc539786e10778d8af01c809e7906dbf590ee2c1452e3db5d92
# Verified Classes:   AgentIdentityBindingError, Svid, AgentIdentity
# Defensive Guards:   5 fail-closed invariants (zero external deps)

import time
from dataclasses import dataclass
from typing import Optional


class AgentIdentityBindingError(RuntimeError):
    """Raised when an SVID does not attest to the agent originating a cross-org call."""


@dataclass(frozen=True)
class Svid:
    spiffe_id: str
    selectors: frozenset[str]   # e.g. {"sa:reconciler", "ns:agents", "pod-uid:abc"}
    not_after: float            # unix seconds
    trust_domains: frozenset[str]


@dataclass(frozen=True)
class AgentIdentity:
    agent_name: str
    required_selector: str      # the selector that MUST appear in the SVID
    trust_domain: str


def bind_for_cross_org_call(
    agent: AgentIdentity,
    svid: Optional[Svid],
    peer_trust_domains: frozenset[str],
    rotation_grace_s: float = 90.0,
    peer_clock_skew_s: float = 60.0,
    now: Optional[float] = None,
) -> Svid:
    now = time.time() if now is None else now

    if svid is None:
        raise AgentIdentityBindingError(
            f"agent {agent.agent_name!r} has no SVID; refusing cross-org call"
        )

    # 1. The SVID must attest to *this agent*, not merely to a host workload.
    if agent.required_selector not in svid.selectors:
        raise AgentIdentityBindingError(
            f"SVID {svid.spiffe_id!r} selectors {sorted(svid.selectors)} do not "
            f"include agent selector {agent.required_selector!r}; "
            f"identity is bound to transport, not agent {agent.agent_name!r}"
        )

    # 2. Trust domain must be mutually federated.
    if agent.trust_domain not in peer_trust_domains:
        raise AgentIdentityBindingError(
            f"trust domain {agent.trust_domain!r} not in peer bundle "
            f"{sorted(peer_trust_domains)}; federation is not transitive"
        )
    if not svid.spiffe_id.startswith(f"spiffe://{agent.trust_domain}/"):
        raise AgentIdentityBindingError(
            f"SVID {svid.spiffe_id!r} is outside agent trust domain "
            f"{agent.trust_domain!r}"
        )

    # 3. Eager rotation: refuse if within grace window of expiry, regardless of rate.
    remaining = svid.not_after - now
    if remaining <= rotation_grace_s + peer_clock_skew_s:
        raise AgentIdentityBindingError(
            f"SVID {svid.spiffe_id!r} expires in {remaining:.1f}s "
            f"(grace {rotation_grace_s}s + skew {peer_clock_skew_s}s); "
            f"force refresh before cross-org call"
        )

    return svid
