# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/in-what-scenarios-must-an-instance-refuse-to-propagate-an-attenuated-capability-across-an-agent-to-agent-delegation-chain-when-taint-constraints-inter.md
# Remnant Warrant:    https://corpusfetch.com/c/in-what-scenarios-must-an-instance-refuse-to-propagate-an-attenuated-capability-across-an-agent-to-agent-delegation-chain-when-taint-constraints-inter.warrant.json
# Markdown SHA-256:   a872b798673241ec1cf27901e51b57410415390eb0d6d5732784aebb26865c2d
# Code AST SHA-256:   e45510d547b3e4ea84d830ca01620619e7e53600738d1c84b65a87101e15a8de
# Verified Classes:   TaintAttenuationConflict, Capability
# Defensive Guards:   3 fail-closed invariants (zero external deps)

from dataclasses import dataclass, field
from typing import FrozenSet


class TaintAttenuationConflict(RuntimeError):
    """Raised when a delegated capability's rights-narrowing would launder taint."""


@dataclass(frozen=True)
class Capability:
    rights: FrozenSet[str]
    taint: FrozenSet[str]
    taint_relevant_rights: FrozenSet[str] = field(default_factory=frozenset)

    def taint_surface(self) -> FrozenSet[str]:
        return self.rights & self.taint_relevant_rights

    def attenuate(self, allowed_rights: FrozenSet[str]) -> "Capability":
        new_rights = self.rights & allowed_rights
        # Taint is inherited, NEVER reconstructed from rights.
        return Capability(
            rights=new_rights,
            taint=self.taint,
            taint_relevant_rights=self.taint_relevant_rights,
        )


def delegate(parent: Capability,
             allowed_rights: FrozenSet[str],
             downstream_prohibited_taint: FrozenSet[str]) -> Capability:
    child = parent.attenuate(allowed_rights)

    removed_taint_relevant = parent.taint_surface() - child.taint_surface()
    prohibited_present = parent.taint & downstream_prohibited_taint

    if removed_taint_relevant and prohibited_present:
        raise TaintAttenuationConflict(
            f"Refusing delegation: narrowing removed taint-relevant rights "
            f"{sorted(removed_taint_relevant)} while taint "
            f"{sorted(prohibited_present)} is prohibited downstream. "
            f"Derivative would be a taint-laundering capability."
        )

    # Invariant checks: monotone in both planes.
    assert child.rights <= parent.rights, "rights widened on attenuation"
    assert child.taint <= parent.taint, "taint widened on attenuation"
    return child


# Example: orchestrator holds a PII-tainted read capability and tries to
# narrow it to summaries before delegating to a no-PII external tool.
parent = Capability(
    rights=frozenset({"read:raw", "read:summary", "write:log"}),
    taint=frozenset({"PII"}),
    taint_relevant_rights=frozenset({"read:raw", "read:summary"}),
)

try:
    delegate(
        parent,
        allowed_rights=frozenset({"read:summary", "write:log"}),
        downstream_prohibited_taint=frozenset({"PII"}),
    )
except TaintAttenuationConflict as exc:
    print(f"BLOCKED: {exc}")
