# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-an-instance-refuse-to-attenuate-a-delegated-aaif-capability-token-before-the-delegation-chain-is-re-verified.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-an-instance-refuse-to-attenuate-a-delegated-aaif-capability-token-before-the-delegation-chain-is-re-verified.warrant.json
# Markdown SHA-256:   bcb3dc17be99974ad636df05a570e0ea84c3474f0192c787d3f48fa7acbee51e
# Code AST SHA-256:   3010f7b7009600ef1e8f15ec760506771bf279d80cca74efdc045e3aac8b7ab3
# Verified Classes:   UnentailedAttenuationError, ChainFreshness
# Defensive Guards:   2 fail-closed invariants (zero external deps)

class UnentailedAttenuationError(RuntimeError):
    """Raised when an instance attempts to attenuate a delegated AAIF token
    from a parent whose live scope entailment cannot be established."""


class ChainFreshness:
    def __init__(self, attested_scope, ttl_seconds, issued_at):
        self.attested_scope = attested_scope
        self.ttl_seconds = ttl_seconds
        self.issued_at = issued_at

    def is_fresh(self, now, max_staleness):
        return (now - self.issued_at) <= min(self.ttl_seconds, max_staleness)


def attenuate(parent_token, child_scope, freshness, now, max_staleness):
    """Attenuate parent_token to child_scope only if child_scope is entailed
    by the live parent scope. Refuses otherwise."""
    if freshness is None or not freshness.is_fresh(now, max_staleness):
        # No fresh chain attestation: we cannot prove live entailment.
        # Do NOT fall back to syntactic narrowing against parent_token.scope.
        raise UnentailedAttenuationError(
            f"cannot attenuate token {parent_token.id!r}: no fresh chain "
            f"attestation within staleness window {max_staleness}s; "
            f"syntactic narrowing against cached scope is unsound"
        )

    live_scope = freshness.attested_scope
    if not live_scope.entails(child_scope):
        raise UnentailedAttenuationError(
            f"cannot attenuate token {parent_token.id!r}: requested child "
            f"scope {child_scope!r} is not entailed by live parent scope "
            f"{live_scope!r} (possible ancestor narrowing or revocation)"
        )

    return parent_token.issue_child(child_scope)
