# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-happens-when-an-instance-delegates-a-capability-across-an-organizational-trust-boundary-without-re-negotiating-the-delegation-chain.md
# Remnant Warrant:    https://corpusfetch.com/c/what-happens-when-an-instance-delegates-a-capability-across-an-organizational-trust-boundary-without-re-negotiating-the-delegation-chain.warrant.json
# Markdown SHA-256:   2770365b139e28a9e7614ecc7fcc04b2c80b222f3713dc3def17b44ba8bc0a84
# Code AST SHA-256:   d9444ab70ded0656135962dc7a79f6be9c9dd860e389ca5a77b6caac6edc35c6
# Verified Classes:   TransitiveAuthorityError, Capability
# Defensive Guards:   5 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class TransitiveAuthorityError(RuntimeError):
    """Raised when a delegation chain exercises authority from an issuer
    that the verifier has not negotiated trust with for the resource class."""
    pass


@dataclass(frozen=True)
class Capability:
    issuer: str            # principal that signed this link
    subject: str           # principal receiving authority
    resource_class: str
    expires_at: float
    chain_root: str        # issuer of the original capability (chain of custody)
    issuer_set: frozenset  # every issuer appearing in the chain, root included


def authorize(chain: list[Capability], resource_class: str,
              negotiated: dict[str, set[str]], now: float) -> None:
    """
    negotiated: map of resource_class -> set of issuers the verifier has
    performed trust negotiation with for that class.
    """
    if not chain:
        raise TransitiveAuthorityError("empty delegation chain")

    terminal = chain[-1]
    if terminal.resource_class != resource_class:
        raise TransitiveAuthorityError(
            f"resource class mismatch: token={terminal.resource_class!r} "
            f"request={resource_class!r}"
        )

    if terminal.expires_at <= now:
        raise TransitiveAuthorityError("capability expired")

    # Monotonic attenuation: each link's issuer_set must be a subset of the
    # previous link's issuer_set plus the link's own issuer. Re-rooting that
    # drops a prior issuer is detected here.
    for prev, cur in zip(chain, chain[1:]):
        expected = prev.issuer_set | {cur.issuer}
        if cur.issuer_set != expected:
            raise TransitiveAuthorityError(
                f"issuer set discontinuity between {prev.issuer} and "
                f"{cur.issuer}: expected {sorted(expected)}, "
                f"got {sorted(cur.issuer_set)}"
            )

    # The core invariant: every principal whose authority is exercised
    # (the full issuer set, not just the root) must be in the negotiation set.
    trusted = negotiated.get(resource_class, set())
    unnegotiated = terminal.issuer_set - trusted
    if unnegotiated:
        raise TransitiveAuthorityError(
            f"transitive authority from unnegotiated issuers "
            f"{sorted(unnegotiated)} for resource class {resource_class!r}; "
            f"negotiated set is {sorted(trusted)}"
        )
