# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-identity-claim-survive-token-expiry-in-aaif-scoped-delegation-chains.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-identity-claim-survive-token-expiry-in-aaif-scoped-delegation-chains.warrant.json
# Markdown SHA-256:   46e1e42438c3eb32ad9045794573423613fca858dcb40b46308055e43f33c267
# Code AST SHA-256:   b904c453a2335803c483a670eb96a03e75372df464a00932b6e116f1134b2df7
# Verified Classes:   DelegationChainError, RevokedIntermediateError
# Defensive Guards:   2 fail-closed invariants (zero external deps)

class DelegationChainError(RuntimeError):
    """Raised when an AAIF delegation chain cannot be validly re-minted."""
    pass


class RevokedIntermediateError(DelegationChainError):
    """Intermediate delegator is revoked, but root attestation is still live."""


def remint_scoped_token(act_chain, root_attestation, now, revocation_lookup):
    """
    act_chain: list of actor entries from leaf to root, each with 'id' and 'exp'.
    root_attestation: dict with 'subject', 'exp'.
    revocation_lookup: callable(actor_id) -> bool (True if revoked).
    """
    if now >= root_attestation["exp"]:
        raise DelegationChainError(
            f"root attestation for {root_attestation['subject']} expired at "
            f"{root_attestation['exp']}; cannot re-mint"
        )

    # The non-obvious invariant: every intermediate edge must be live NOW.
    for actor in act_chain:
        if revocation_lookup(actor["id"]):
            raise RevokedIntermediateError(
                f"intermediate delegator {actor['id']} revoked at re-mint time "
                f"(now={now}); root attestation still live, refusing re-mint "
                f"to avoid revocation-bypass window"
            )

    leaf = act_chain[0]
    return {
        "sub": leaf["id"],
        "act": [a["id"] for a in act_chain],
        "exp": min(now + 300, root_attestation["exp"]),
    }
