# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-an-instance-refuse-a-delegated-token-that-is-syntactically-valid-but-semantically-orphaned.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-an-instance-refuse-a-delegated-token-that-is-syntactically-valid-but-semantically-orphaned.warrant.json
# Markdown SHA-256:   6af04299fc4d9627867efec53c8126ee4551b342582d24fabf612679abaf4a31
# Code AST SHA-256:   887347571b3773d902b20a3c343c26b264114edb0d052707d2bf420c223af932
# Verified Classes:   OrphanedDelegationError
# Defensive Guards:   4 fail-closed invariants (zero external deps)

class OrphanedDelegationError(RuntimeError):
    """Raised when a delegated token's actor is no longer live under a non-grace anchor."""
    pass


def authorize_delegated_token(token, registry, active_anchors, grace_anchors):
    # Signature and scope checks are assumed to have passed upstream.
    act_sub = token.claims.get("act", {}).get("sub")
    issuer = token.claims["iss"]
    anchor_id = token.claims["anchor_id"]

    actor_live = registry.is_registered(act_sub)

    if anchor_id in active_anchors:
        # Active anchor: actor liveness is the only remaining gate.
        if not actor_live:
            raise OrphanedDelegationError(
                f"actor {act_sub!r} from issuer {issuer!r} is deregistered; "
                f"token is valid but delegation is orphaned"
            )
        return True

    if anchor_id in grace_anchors:
        # Grace period exists to drain LIVE delegations only.
        if not actor_live:
            raise OrphanedDelegationError(
                f"actor {act_sub!r} is deregistered and its anchor {anchor_id!r} "
                f"is in grace; grace does not extend orphaned delegations"
            )
        return True

    # Anchor unknown or fully retired: fail closed.
    raise OrphanedDelegationError(
        f"anchor {anchor_id!r} for issuer {issuer!r} is neither active nor in grace"
    )


def authorize_with_registry_outage(token, registry_available):
    if not registry_available and _is_cross_issuer_delegated(token):
        # Fail closed: we cannot prove the actor is live.
        raise OrphanedDelegationError(
            "instance registry unreachable; cannot validate act.sub liveness "
            "for cross-issuer delegated token"
        )
    return True


def _is_cross_issuer_delegated(token):
    return "act" in token.claims and token.claims.get("iss") != token.local_issuer
