# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-an-instance-refuse-a-tool-call-that-passes-taint-checks-the-sink-reachability-gap-in-taint-aware-allow-deny-enforcement.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-an-instance-refuse-a-tool-call-that-passes-taint-checks-the-sink-reachability-gap-in-taint-aware-allow-deny-enforcement.warrant.json
# Markdown SHA-256:   71d7212d01150112c0a386683c87fb34415387efefe8c4282d8ec95039d1fc90
# Code AST SHA-256:   f14814fa4ccd6cf350afa5103cf56a193b154f570d99e418479fb17aa765f0d8
# Verified Classes:   SinkReachabilityError, ProvenanceMap
# Defensive Guards:   2 fail-closed invariants (zero external deps)

class SinkReachabilityError(RuntimeError):
    """Raised when a label-clean invocation nonetheless reaches a forbidden sink
    via ambient or persistent state written by a tainted flow."""
    pass


class ProvenanceMap:
    """Tracks the taint of the flow that last wrote each persistent key."""

    def __init__(self):
        self._writes = {}  # key -> taint label of writing flow

    def record_write(self, key, taint):
        self._writes[key] = taint

    def taint_of(self, key):
        return self._writes.get(key, "clean")


SINK_EFFECT_CLASSES = {"privileged_write", "exec", "network_egress", "credential_access"}


def enforce_invocation(tool, args, arg_taints, ambient_reads, provenance):
    """
    tool: descriptor with .name, .effect_class, .ambient_deps (list of keys it reads)
    args: concrete arguments
    arg_taints: dict arg_name -> taint label
    ambient_reads: keys the tool will read from persistent/ambient state this call
    provenance: ProvenanceMap
    """
    # Question 1: label gate on declared arguments.
    dirty_args = [k for k, v in arg_taints.items() if v != "clean"]
    if dirty_args:
        return {"decision": "deny", "reason": f"tainted args: {dirty_args}"}

    # Question 2: reachability gate. A label-clean call is NOT sufficient
    # when the tool reaches into state written by a tainted flow.
    if tool.effect_class in SINK_EFFECT_CLASSES:
        for key in ambient_reads:
            if key not in tool.ambient_deps:
                raise SinkReachabilityError(
                    f"tool {tool.name!r} reads undeclared ambient key {key!r}; "
                    f"reachability cannot be proven for a {tool.effect_class} sink"
                )
            taint = provenance.taint_of(key)
            if taint != "clean":
                raise SinkReachabilityError(
                    f"tool {tool.name!r} (effect={tool.effect_class}) is label-clean "
                    f"but reads {key!r} last written by a {taint!r} flow; "
                    f"refusing to treat argument-cleanliness as effect-cleanliness"
                )

    return {"decision": "allow", "reason": "label-clean and reachability-closed"}
