# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-structural-signals-indicate-the-attestation-freshness-paradox-in-cross-organization-agent-trust-bootstrapping-where-revocation-propagation-lags-n.md
# Remnant Warrant:    https://corpusfetch.com/c/what-structural-signals-indicate-the-attestation-freshness-paradox-in-cross-organization-agent-trust-bootstrapping-where-revocation-propagation-lags-n.warrant.json
# Markdown SHA-256:   1fba386b30b8cdd424fa088d869674f606324285876ae6e234aebb02229d325d
# Code AST SHA-256:   de79d16436ac4a693cf0f6e9de08631414d2c78ff27569ae3c59b258e8448c2c
# Verified Classes:   AttestationFreshnessError, Attestation, RevocationSnapshot
# Defensive Guards:   4 fail-closed invariants (zero external deps)

import time
from dataclasses import dataclass


class AttestationFreshnessError(RuntimeError):
    """Raised when a cross-org attestation cannot be soundly evaluated
    against revocation state at bootstrap (the freshness paradox)."""
    pass


@dataclass
class Attestation:
    issuer: str
    issued_at: float          # epoch seconds
    revocation_epoch: int     # issuer's monotonic revocation epoch at mint
    ttl: float                # attestation validity period


@dataclass
class RevocationSnapshot:
    issuer: str
    this_update: float        # when this snapshot was published
    next_update: float        # issuer-promised next publication
    epoch: int                # monotonic revocation epoch covered


def evaluate_bootstrap_trust(
    att: Attestation,
    snap: RevocationSnapshot,
    now: float,
    max_staleness: float,
) -> str:
    """Return a trust level for a first-contact (bootstrap) attestation.

    Returns 'trusted' only when the revocation snapshot provably covers
    the attestation and is fresh. Otherwise returns 'probationary' with
    a re-check deadline, or raises on structurally unsound input.
    """
    if att.issuer != snap.issuer:
        raise AttestationFreshnessError(
            f"issuer mismatch: attestation={att.issuer} snapshot={snap.issuer}"
        )

    # Invariant 1: the snapshot must have been published after the
    # attestation was minted, otherwise it cannot cover it.
    if snap.this_update < att.issued_at:
        raise AttestationFreshnessError(
            "revocation snapshot predates attestation issuance; "
            f"this_update={snap.this_update} < issued_at={att.issued_at}"
        )

    # Invariant 2: monotonic epoch must cover the attestation's epoch.
    if snap.epoch < att.revocation_epoch:
        raise AttestationFreshnessError(
            "revocation epoch behind attestation epoch; "
            f"snapshot={snap.epoch} < attestation={att.revocation_epoch}"
        )

    # Invariant 3: snapshot must be within the staleness bound.
    age = now - snap.this_update
    if age > max_staleness:
        # Not unsound, but not trusted: downgrade to probationary with a
        # hard deadline derived from the issuer's own next_update promise.
        return "probationary"

    # Attestation TTL must not outlive the propagation bound, else the
    # window reopens before expiry can heal it.
    if att.ttl > (snap.next_update - snap.this_update):
        raise AttestationFreshnessError(
            "attestation TTL exceeds issuer revocation propagation bound; "
            "staleness cannot self-heal via expiry"
        )

    return "trusted"


def bootstrap_handshake(
    att: Attestation,
    snap: RevocationSnapshot,
    now: float,
    max_staleness: float,
) -> dict:
    level = evaluate_bootstrap_trust(att, snap, now, max_staleness)
    if level == "probationary":
        # Enforce re-check at the issuer's promised next_update, not now+TTL.
        return {"trust": level, "recheck_at": snap.next_update}
    return {"trust": level, "recheck_at": None}
