# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-taint-tracking-fail-open-when-a-tool-invocation-is-re-entered-after-a-sandbox-denial.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-taint-tracking-fail-open-when-a-tool-invocation-is-re-entered-after-a-sandbox-denial.warrant.json
# Markdown SHA-256:   a8734d3c093e208c39a4e1c7d9721d4311635738e9d612db106508c11464b807
# Code AST SHA-256:   cac4c4be49ac706529ba35b83481acf13f652bf83eb593c0fe67b19eeedec3ae
# Verified Classes:   TaintViolation, RetryableToolError, ProvenanceTable
# Defensive Guards:   3 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass, field
from typing import Any


class TaintViolation(RuntimeError):
    """Raised when tainted data reaches a sensitive sink.

    Deliberately NOT a subclass of RetryableToolError so that retry
    classifiers cannot match it by accident.
    """
    pass


class RetryableToolError(RuntimeError):
    """Transient tool fault; safe to retry."""
    pass


@dataclass
class ProvenanceTable:
    """Session-scoped taint store keyed by value hash, not by frame."""
    tainted: dict[str, str] = field(default_factory=dict)

    @staticmethod
    def _key(value: Any) -> str:
        return hashlib.sha256(repr(value).encode("utf-8")).hexdigest()

    def mark(self, value: Any, origin: str) -> None:
        self.tainted[self._key(value)] = origin

    def origin_of(self, value: Any) -> str | None:
        return self.tainted.get(self._key(value))

    def derive(self, source: Any, derived: Any) -> Any:
        """Taint-preserving transform: derived value inherits source taint."""
        origin = self.origin_of(source)
        if origin is not None:
            self.tainted[self._key(derived)] = origin
        return derived


SENSITIVE_TOOLS = {"send_email", "http_post", "execute_sql", "write_file"}


def dispatch(tool: str, args: dict[str, Any], prov: ProvenanceTable) -> None:
    if tool in SENSITIVE_TOOLS:
        for name, value in args.items():
            origin = prov.origin_of(value)
            if origin is not None:
                raise TaintViolation(
                    f"sensitive tool {tool!r} arg {name!r} derived from "
                    f"untrusted origin {origin!r}"
                )
    # ... actual dispatch ...


def retry_loop(tool: str, args: dict[str, Any], prov: ProvenanceTable,
               attempts: int = 3) -> None:
    last: Exception | None = None
    for _ in range(attempts):
        try:
            dispatch(tool, args, prov)
            return
        except TaintViolation:
            # Terminal: never reformulate and retry a taint denial.
            raise
        except RetryableToolError as e:
            last = e
            continue
    if last is not None:
        raise last
