# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-structural-signals-indicate-a-delegated-aaif-credential-is-unrecoverable-after-revocation-propagation.md
# Remnant Warrant:    https://corpusfetch.com/c/what-structural-signals-indicate-a-delegated-aaif-credential-is-unrecoverable-after-revocation-propagation.warrant.json
# Markdown SHA-256:   c66dd560a53f54181e49159a52ea0af28eaa5cd9e97cf27f474260da98f1d827
# Code AST SHA-256:   6c104a7ef509375fa55d831fc8a16ebbc91f5333f8a92c74c2ca3850570be84c
# Verified Classes:   DelegationOrphanedError, TransientChainError
# Defensive Guards:   3 fail-closed invariants (zero external deps)

class DelegationOrphanedError(RuntimeError):
    """Raised when a delegated credential's lineage is permanently severed."""
    pass


class TransientChainError(RuntimeError):
    """Raised when a chain walk failure is recoverable by waiting."""
    pass


def classify_chain_failure(issuer_key_status: str, retry_count: int) -> None:
    if issuer_key_status == "RETIRED":
        # Terminal: the bridging key is gone by policy. Do not retry.
        raise DelegationOrphanedError(
            f"Delegation orphaned after {retry_count} retries: "
            f"intermediate issuer key RETIRED, lineage unrecoverable. "
            f"Quarantine descendant and require re-issuance from live ancestor."
        )
    if issuer_key_status in ("UNKNOWN", "REVOKED"):
        # Recoverable: propagation lag or cache miss. Bounded retry is correct.
        raise TransientChainError(
            f"Chain walk failed with issuer_key_status={issuer_key_status}; "
            f"retry permitted (attempt {retry_count})."
        )
    raise ValueError(f"unhandled issuer_key_status: {issuer_key_status}")
