# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/in-what-scenarios-must-an-instance-reject-a-federated-capability-token-whose-trust-anchor-chain-is-valid-but-whose-delegation-depth-exceeds-the-anchor.md
# Remnant Warrant:    https://corpusfetch.com/c/in-what-scenarios-must-an-instance-reject-a-federated-capability-token-whose-trust-anchor-chain-is-valid-but-whose-delegation-depth-exceeds-the-anchor.warrant.json
# Markdown SHA-256:   6a6ad233ebb52e52f716d3e1372355f497fb3aa5aeec948dac6d8f82994f9a5d
# Code AST SHA-256:   9b010fed2ba0cec9c2c241b1dd645163a0947b3d6443e9477396b3f2e9ab7308
# Verified Classes:   DelegationDepthExceeded, AnchorBudget
# Defensive Guards:   4 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class DelegationDepthExceeded(RuntimeError):
    """Raised when a federated token's accumulated delegation depth or hop
    count exceeds the root trust anchor's published attenuation budget,
    even though every individual link and signature is valid."""

    def __init__(self, observed_depth: int, anchor_budget: int, observed_hops: int, anchor_hops: int):
        self.observed_depth = observed_depth
        self.anchor_budget = anchor_budget
        self.observed_hops = observed_hops
        self.anchor_hops = anchor_hops
        super().__init__(
            f"delegation_depth_exceeded: depth {observed_depth} > budget {anchor_budget} "
            f"or hops {observed_hops} > {anchor_hops}"
        )


@dataclass(frozen=True)
class AnchorBudget:
    max_delegation_depth: int
    max_hops: int


def verify_federated_token(
    chain_links: list,          # verifier-reconstructed chain, root first
    anchor_budget: AnchorBudget,
    signatures_valid: bool,
    anchor_trusted: bool,
    anchor_revoked: bool,
) -> None:
    if not signatures_valid:
        raise ValueError("invalid_chain: signature verification failed")
    if not anchor_trusted:
        raise ValueError("untrusted_anchor: anchor not in trust store")
    if anchor_revoked:
        raise ValueError("revoked_anchor: anchor has been revoked")

    # Depth is a path property: count from the reconstructed chain,
    # never trust a self-reported counter inside the token body.
    observed_depth = len(chain_links) - 1  # root does not delegate to itself
    observed_hops = len(chain_links) - 1

    if observed_depth > anchor_budget.max_delegation_depth or observed_hops > anchor_budget.max_hops:
        raise DelegationDepthExceeded(
            observed_depth=observed_depth,
            anchor_budget=anchor_budget.max_delegation_depth,
            observed_hops=observed_hops,
            anchor_hops=anchor_budget.max_hops,
        )
    # token admitted: valid chain AND within the root anchor's attenuation budget
