# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-an-instance-reject-a-hardware-backed-aaif-credential-chain-that-verifies-correctly.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-an-instance-reject-a-hardware-backed-aaif-credential-chain-that-verifies-correctly.warrant.json
# Markdown SHA-256:   690bc8a28da3c7a5790d1be8b6ad935c8cc0eff0132a5dcc9cf11276229cffc3
# Code AST SHA-256:   45dc3eec54106ce6fc1eb4796536d7d45fbc08917b10f2a2b22c145e93e1a836
# Verified Classes:   AAIFBindingError
# Defensive Guards:   4 fail-closed invariants (zero external deps)

class AAIFBindingError(RuntimeError):
    """Raised when an AAIF chain verifies cryptographically but fails instance binding."""
    pass


def admit_aaif_chain(chain, live_handshake, expected_nonce, revocation_epoch):
    """
    chain: parsed AAIF credential chain (leaf subject, quote, EK cert)
    live_handshake: dict with 'ephemeral_pubkey' and 'nonce' from the current channel
    expected_nonce: nonce this handler issued and has not yet accepted
    revocation_epoch: latest known EK revocation epoch (unix seconds)
    """
    if not chain.signatures_valid():
        raise AAIFBindingError("chain signature invalid; reject before binding checks")

    # 1. single-use nonce bound to THIS channel
    if live_handshake["nonce"] != expected_nonce:
        raise AAIFBindingError(
            f"nonce mismatch: channel={live_handshake['nonce']!r} expected={expected_nonce!r}"
        )

    # 2. proof-of-possession: leaf subject key must sign the live handshake
    if chain.leaf_subject_key != live_handshake["ephemeral_pubkey"]:
        raise AAIFBindingError(
            "leaf subject key does not match live channel key; chain attests image, not instance"
        )

    # 3. revocation freshness
    if revocation_epoch < chain.quote_timestamp:
        raise AAIFBindingError(
            f"stale revocation epoch {revocation_epoch} < quote {chain.quote_timestamp}"
        )

    return chain.leaf_subject  # safe: bound to exactly one live instance
