# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/in-what-scenarios-must-an-instance-refuse-to-issue-a-delegated-aaif-credential-when-the-parent-chain-is-cryptographically-valid-but-semantically-stale.md
# Remnant Warrant:    https://corpusfetch.com/c/in-what-scenarios-must-an-instance-refuse-to-issue-a-delegated-aaif-credential-when-the-parent-chain-is-cryptographically-valid-but-semantically-stale.warrant.json
# Markdown SHA-256:   55f7298e2dfb8f7dbf1b9f6f74c3360b3284903675e1a63530d608af5afe32f9
# Code AST SHA-256:   abcba0826ac2f8b4ec390222c70376cf4064d80779cc76535740b695bc1f4be1
# Verified Classes:   StaleAuthorityError, Credential
# Defensive Guards:   4 fail-closed invariants (zero external deps)

from dataclasses import dataclass
from typing import Optional


class StaleAuthorityError(RuntimeError):
    """Raised when a parent credential is cryptographically valid but its
    delegated authority has been narrowed by a newer authority head."""
    pass


@dataclass
class Credential:
    cred_id: str
    subject: str
    scope_max_amount: int
    scope_irreversible: bool
    epoch: int


def assert_parent_authority_current(
    parent: Credential,
    authority_head: Optional[Credential],
) -> None:
    """Enforce the authority-provenance freshness invariant before issuing a child.

    Refuses issuance when the delegating party's current authority head is a
    strict subset of the presented parent's scope. Fails closed for irreversible
    scopes when the head cannot be resolved.
    """
    if authority_head is None:
        if parent.scope_irreversible:
            raise StaleAuthorityError(
                f"cannot resolve authority head for {parent.subject}; "
                f"refusing irreversible-scope issuance on parent {parent.cred_id}"
            )
        return

    if authority_head.cred_id == parent.cred_id:
        return  # parent is the current head

    if authority_head.epoch < parent.epoch:
        raise StaleAuthorityError(
            f"authority head {authority_head.cred_id} (epoch {authority_head.epoch}) "
            f"predates presented parent {parent.cred_id} (epoch {parent.epoch})"
        )

    # Head is newer. Refuse only if it strictly narrows the conveyed authority.
    if authority_head.scope_max_amount < parent.scope_max_amount:
        raise StaleAuthorityError(
            f"parent {parent.cred_id} conveys {parent.scope_max_amount} but current "
            f"authority head {authority_head.cred_id} permits only "
            f"{authority_head.scope_max_amount}; refusing to mint over-broad child"
        )


def issue_delegated_credential(
    parent: Credential,
    authority_head: Optional[Credential],
    child_subject: str,
    requested_amount: int,
) -> Credential:
    assert_parent_authority_current(parent, authority_head)
    if requested_amount > parent.scope_max_amount:
        raise StaleAuthorityError(
            f"requested {requested_amount} exceeds parent ceiling "
            f"{parent.scope_max_amount}"
        )
    return Credential(
        cred_id=f"{parent.cred_id}.{child_subject}",
        subject=child_subject,
        scope_max_amount=requested_amount,
        scope_irreversible=parent.scope_irreversible,
        epoch=parent.epoch,
    )
