# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-forget-a-memory-it-never-wrote-the-tombstone-visibility-invariant-in-read-write-forget-memory-contracts.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-forget-a-memory-it-never-wrote-the-tombstone-visibility-invariant-in-read-write-forget-memory-contracts.warrant.json
# Markdown SHA-256:   7214840f685b669bd6f69dc6113d6735b47dd2e6a16d1e00a72961d8a11e4aee
# Code AST SHA-256:   3ab561c729b3c2ced9e1f181cb95b7728cff69610189d4a7be963485d2840fa3
# Verified Classes:   RedactionGuaranteeViolation
# Defensive Guards:   1 fail-closed invariants (zero external deps)

class RedactionGuaranteeViolation(RuntimeError):
    """Raised when a forgotten key remains observable through any side channel."""
    pass


def verify_forget_indistinguishability(store, key, never_written_key):
    """
    Assert that after forget(key), the store cannot distinguish `key`
    from a key that was never written, across every observable surface.
    """
    store.write(key, "sensitive-payload", ttl=3600)
    store.read(key)
    store.forget(key)

    violations = []

    # 1. Read surface: must raise the same error class for both keys.
    try:
        store.read(key)
        violations.append("read(key) still returned after forget")
    except Exception as e_forgot:
        try:
            store.read(never_written_key)
        except Exception as e_never:
            if type(e_forgot) is not type(e_never):
                violations.append(
                    f"error taxonomy leaks existence: "
                    f"{type(e_forgot).__name__} vs {type(e_never).__name__}"
                )

    # 2. Enumeration surface: the key name must not appear.
    if key in store.list(prefix=key.split(":")[0]):
        violations.append("key name still enumerable after forget")

    # 3. Version surface: rewriting must not reveal prior history.
    v_after = store.write(key, "x", ttl=3600)
    v_fresh = store.write(never_written_key, "x", ttl=3600)
    if v_after != v_fresh:
        violations.append(
            f"version counter leaks prior writes: {v_after} != {v_fresh}"
        )

    # 4. Restore surface: a restorable snapshot invalidates the guarantee.
    if store.supports_point_in_time_restore():
        horizon = store.backup_retention_seconds()
        if horizon > 0:
            violations.append(
                f"restore horizon {horizon}s exceeds forget effect; "
                f"effective redaction is not immediate"
            )

    if violations:
        raise RedactionGuaranteeViolation(
            f"forget({key!r}) violated redaction guarantee: " + "; ".join(violations)
        )
    return True
