# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-should-an-instance-distinguish-a-stale-provenance-false-positive-from-genuine-memory-poisoning-at-write-time.md
# Remnant Warrant:    https://corpusfetch.com/c/how-should-an-instance-distinguish-a-stale-provenance-false-positive-from-genuine-memory-poisoning-at-write-time.warrant.json
# Markdown SHA-256:   fc751aaa1dac71e3f4b1668a306049e3edb1a0b53db1dade1e29d587d9e24031
# Code AST SHA-256:   97f7426fc0e7b4681cc62b8a16306156cddc43a568159a3f2ecec4c908bd2869
# Verified Classes:   ProvenanceRejection, StaleProvenanceError, PoisonedProvenanceError, ProtocolViolationError, ProvenanceClaim, ValidatorState
# Defensive Guards:   5 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass
from typing import Optional


class ProvenanceRejection(RuntimeError):
    """Base for all write-time provenance rejections."""
    pass


class StaleProvenanceError(ProvenanceRejection):
    """Parent epoch is behind the validator view beyond reorg depth.

    Retryable: the writer should re-read the parent and retry.
    NOT a poisoning signal.
    """
    def __init__(self, claimed_epoch: int, validator_epoch: int, reorg_depth: int):
        self.claimed_epoch = claimed_epoch
        self.validator_epoch = validator_epoch
        self.reorg_depth = reorg_depth
        super().__init__(
            f"stale provenance: claimed_epoch={claimed_epoch} "
            f"validator_epoch={validator_epoch} reorg_depth={reorg_depth}"
        )


class PoisonedProvenanceError(ProvenanceRejection):
    """Parent hash absent at claimed epoch, or signature invalid.

    NOT retryable. Escalate to revocation path.
    """
    pass


class ProtocolViolationError(ProvenanceRejection):
    """Claimed epoch exceeds validator view. Unreachable under valid protocol."""
    pass


@dataclass(frozen=True)
class ProvenanceClaim:
    writer_id: str
    claimed_parent_epoch: int
    claimed_parent_hash: str
    content_hash: str
    signature: bytes


@dataclass
class ValidatorState:
    view_epoch: int
    reorg_depth: int
    historical_index: dict  # epoch -> set[hash]
    authorized_writers: dict  # epoch -> set[writer_id]


def validate_write(claim: ProvenanceClaim, state: ValidatorState) -> str:
    """Returns 'confirmed' or 'pending_confirmation'. Raises on rejection."""
    ep = claim.claimed_parent_epoch
    vep = state.view_epoch
    depth = state.reorg_depth

    if ep > vep:
        raise ProtocolViolationError(
            f"claimed epoch {ep} exceeds validator view {vep}; "
            f"clock skew or bypassed epoch assignment"
        )

    if ep < vep - depth:
        raise StaleProvenanceError(ep, vep, depth)

    # Within reorg window: hash must exist at the claimed epoch.
    if claim.claimed_parent_hash not in state.historical_index.get(ep, set()):
        raise PoisonedProvenanceError(
            f"parent hash {claim.claimed_parent_hash[:12]} absent at epoch {ep}"
        )

    # Signature must verify against the epoch's authorized-writer set.
    authorized = state.authorized_writers.get(ep, set())
    if claim.writer_id not in authorized:
        raise PoisonedProvenanceError(
            f"writer {claim.writer_id} not authorized at epoch {ep}"
        )

    expected_sig = hashlib.sha256(
        f"{claim.writer_id}|{ep}|{claim.claimed_parent_hash}|{claim.content_hash}".encode()
    ).digest()
    if claim.signature != expected_sig:
        raise PoisonedProvenanceError(
            f"signature mismatch for writer {claim.writer_id} at epoch {ep}"
        )

    # Within window and attested: provisional until one propagation interval elapses.
    if ep == vep:
        return "confirmed"
    return "pending_confirmation"
