# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-does-an-instance-detect-a-retention-scope-violation-when-the-forget-api-acknowledges-deletion-but-the-backing-store-retains-a-tombstoned-replica.md
# Remnant Warrant:    https://corpusfetch.com/c/how-does-an-instance-detect-a-retention-scope-violation-when-the-forget-api-acknowledges-deletion-but-the-backing-store-retains-a-tombstoned-replica.warrant.json
# Markdown SHA-256:   89c72e803b6f0f09530b2f2561ee744fd9748d7a1c9d51127d970d1b870e75b6
# Code AST SHA-256:   67158c08def57fd1226f9ca4b1c74f767c16e466e842a971ddd028329a963a9b
# Verified Classes:   RetentionScopeViolation, ResurrectionDetected
# Defensive Guards:   3 fail-closed invariants (zero external deps)

class RetentionScopeViolation(RuntimeError):
    """Raised when a forget acknowledgement is contradicted by a later read
    whose write_epoch precedes the recorded forget_epoch for the same scope."""
    pass


class ResurrectionDetected(RetentionScopeViolation):
    """Specific case: enumeration found a key that should have been forgotten."""
    pass


def verify_forget(scope: str, key: str, forget_epoch: int, store) -> None:
    """
    Enumerate the full replica set for `scope` and assert `key` is absent.
    Must be called after any forget whose retention guarantee is hard.
    """
    replicas = store.replica_set(scope)
    if not replicas:
        raise RetentionScopeViolation(
            f"no replicas resolvable for scope={scope}; cannot verify forget"
        )

    for replica in replicas:
        record = replica.read(scope=scope, key=key, consistent=False)
        if record is None:
            continue
        write_epoch = record.get("write_epoch")
        if write_epoch is None:
            raise RetentionScopeViolation(
                f"replica={replica.id} returned key={key} with no write_epoch; "
                f"cannot order against forget_epoch={forget_epoch}"
            )
        if write_epoch < forget_epoch:
            raise ResurrectionDetected(
                f"replica={replica.id} resurrected key={key} "
                f"(write_epoch={write_epoch} < forget_epoch={forget_epoch}) "
                f"for scope={scope}; retention guarantee violated"
            )
        # write_epoch >= forget_epoch means a legitimate re-write after forget;
        # that is not a violation, but the caller must be told the key exists again.
    # Enumeration across all replicas returned empty or post-forget writes only.
