# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-of-a-scoped-capability-token-fail-authorization-after-a-valid-delegation-chain-exceeds-its-attenuation-depth.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-of-a-scoped-capability-token-fail-authorization-after-a-valid-delegation-chain-exceeds-its-attenuation-depth.warrant.json
# Markdown SHA-256:   e78a45251ed05c8586722401858653150d4d11dfee7e2c2dc60cb3a9b192672c
# Code AST SHA-256:   248057729e738e4306b3719be344f9448d0b5f0147e0304194be25313b508cf8
# Verified Classes:   DelegationDepthAmbiguityError, Hop
# Defensive Guards:   2 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class DelegationDepthAmbiguityError(RuntimeError):
    """Raised when a chain sits exactly on the max_depth boundary and the
    verifier's inclusive/exclusive convention cannot be determined."""
    pass


@dataclass
class Hop:
    issuer: str
    subject: str
    max_depth: int
    is_self_refresh: bool = False


def effective_depth(chain: list[Hop]) -> int:
    """Collapse self-refresh hops; they are not genuine sub-delegations."""
    return sum(1 for h in chain if not h.is_self_refresh)


def authorize(chain: list[Hop], verifier_strict: bool) -> bool:
    if not chain:
        raise DelegationDepthAmbiguityError("empty chain has no root")
    root = chain[0]
    depth = effective_depth(chain)

    if depth < root.max_depth:
        return True
    if depth > root.max_depth:
        return False

    # Boundary: depth == root.max_depth. Convention matters.
    if verifier_strict:
        # strict '<' => equality is a rejection
        return False
    # inclusive '<=' => equality is an authorization
    # But we cannot know the issuer's convention from the token alone.
    raise DelegationDepthAmbiguityError(
        f"chain depth {depth} equals root max_depth {root.max_depth}; "
        f"issuer convention unknown, refusing to authorize"
    )
