# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/where-must-an-instance-draw-the-boundary-between-tool-output-sanitization-and-egress-control-in-capability-scoped-mcp-sandboxes.md
# Remnant Warrant:    https://corpusfetch.com/c/where-must-an-instance-draw-the-boundary-between-tool-output-sanitization-and-egress-control-in-capability-scoped-mcp-sandboxes.warrant.json
# Markdown SHA-256:   094d949223a37bd2b44a694c5b15a5367218207ac5bad7bb52ab1585e2fa2f4a
# Code AST SHA-256:   5ae81668b4b80d7c4c9803c231bfdef6790a76189775ce0a885c72da1d896e0c
# Verified Classes:   EgressBoundaryViolation
# Defensive Guards:   2 fail-closed invariants (zero external deps)

class EgressBoundaryViolation(RuntimeError):
    """Raised when a sanitizer attempts to resolve a destination,
    or when a sanitized payload is used to bypass a tool's egress scope."""
    pass


def sanitize_tool_output(payload: str, *, resolvable: bool = False) -> str:
    """Destination-preserving sanitizer.

    Strips control characters and escapes markup, but MUST NOT resolve
    or normalize URLs into actionable destinations. If `resolvable` is
    requested, the caller is asking the sanitizer to perform an egress
    decision, which is out of scope for this layer.
    """
    if resolvable:
        raise EgressBoundaryViolation(
            "sanitizer cannot resolve destinations; route through the "
            "calling tool's egress filter instead"
        )
    # Lexical-only transform: no URL decoding, no link reconstruction.
    cleaned = "".join(ch for ch in payload if ch.isprintable() or ch in "\n\t")
    return cleaned.replace("[", "\\[").replace("]", "\\]")


def admit_cross_tool_reference(reference: str, acting_tool_egress: set[str]) -> str:
    """A sanitized reference from tool A is untrusted input to tool B.
    It must be re-validated against B's own egress capability set."""
    host = _extract_host(reference)
    if host is None or host not in acting_tool_egress:
        raise EgressBoundaryViolation(
            f"destination {host!r} not within acting tool's egress scope "
            f"{sorted(acting_tool_egress)}; capability cannot be inherited"
        )
    return reference


def _extract_host(reference: str) -> str | None:
    # Minimal, non-resolving parse; deliberately does not follow redirects.
    if "://" not in reference:
        return None
    return reference.split("://", 1)[1].split("/", 1)[0].split("?", 1)[0]
