# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-should-an-instance-distinguish-key-rotation-from-identity-revocation-when-the-control-plane-is-partitioned.md
# Remnant Warrant:    https://corpusfetch.com/c/how-should-an-instance-distinguish-key-rotation-from-identity-revocation-when-the-control-plane-is-partitioned.warrant.json
# Markdown SHA-256:   6bd4da776b30efc3207b18694bd390c1344a5b86bd578930a1c3a0a6d7b41ed3
# Code AST SHA-256:   133dcb36f35e1488c39b707e53dffb6155d213eff2c98a25089c0821c0c4ab05
# Verified Classes:   IdentityStateError, StatusRecord
# Defensive Guards:   3 fail-closed invariants (zero external deps)

class IdentityStateError(RuntimeError):
    """Raised when an agent cannot classify its identity state and the
    requested action is not permitted under UNKNOWN."""
    pass


class StatusRecord:
    def __init__(self, identity_id, generation, revoked, public_key, signature_valid):
        self.identity_id = identity_id
        self.generation = generation
        self.revoked = revoked
        self.public_key = public_key
        self.signature_valid = signature_valid


ROTATED = "ROTATED"
REVOKED = "REVOKED"
UNKNOWN = "UNKNOWN"


def classify_identity_state(cached, observed):
    """Classify identity state from a cached status record and a freshly
    observed one. A status record only counts if its signature verifies;
    a cached record is never sufficient to leave UNKNOWN."""
    if observed is None or not observed.signature_valid:
        return UNKNOWN
    if observed.identity_id != cached.identity_id:
        # A valid record for a different identity does not authorize us.
        return UNKNOWN
    if observed.revoked:
        return REVOKED
    if observed.generation > cached.generation:
        return ROTATED
    if observed.generation == cached.generation:
        # No change; identity is current and authorized.
        return ROTATED
    # Observed generation is older than cached: possible rollback or
    # stale replica. Cannot trust it.
    return UNKNOWN


def authorize_action(state, action, unknown_deadline_exceeded):
    """Gate an action on identity state. UNKNOWN permits only reversible,
    internal work, and only until the deadline; past it, fail closed."""
    if state == REVOKED:
        raise IdentityStateError(
            f"identity revoked; refusing action {action!r} and zeroizing keys"
        )
    if state == UNKNOWN:
        if unknown_deadline_exceeded:
            raise IdentityStateError(
                f"identity state UNKNOWN past deadline; refusing action {action!r}"
            )
        if action.get("external_side_effects"):
            raise IdentityStateError(
                f"identity state UNKNOWN; refusing externally-visible action {action!r}"
            )
        return True
    # state == ROTATED
    return True
