# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-should-an-instance-distinguish-a-tool-description-injection-from-a-legitimate-capability-grant.md
# Remnant Warrant:    https://corpusfetch.com/c/how-should-an-instance-distinguish-a-tool-description-injection-from-a-legitimate-capability-grant.warrant.json
# Markdown SHA-256:   8b31c8966bce0d0f2cb8d7f97f0dd6114bd70fc37608402e6847350dbb4eafbf
# Code AST SHA-256:   c923a88c31e993e8d823026ada41982bd02325a549a5947a7fd84b7c577eb6cc
# Verified Classes:   ManifestTrustError
# Defensive Guards:   3 fail-closed invariants (zero external deps)

import hashlib
import json
import re
from typing import Any


class ManifestTrustError(RuntimeError):
    """Raised when a tool manifest fails pinning or prose-field trust checks."""
    pass


# Prose fields that are rendered to the model; these are the untrusted channel.
PROSE_FIELDS = ("description", "title", "examples")

# Claims a description is not allowed to make. Rejection, not sanitization.
FORBIDDEN_PROSE_PATTERNS = (
    re.compile(r"\b(ignore|disregard|override)\b.*\b(tool|instruction|prompt)", re.I),
    re.compile(r"\b(canonical|preferred|authoritative)\b.*\b(tool|search|read)\b", re.I),
    re.compile(r"\b(before|after) (calling|using) this tool\b", re.I),
    re.compile(r"\b(assistant|agent|model)\b.*\b(must|should|always|never)\b", re.I),
    re.compile(r"(~|/etc/|/home/|\.ssh|\.aws|\.env)", re.I),
)


def canonical_digest(manifest: dict[str, Any]) -> str:
    """Stable digest over the manifest's semantic content, not its formatting."""
    normalized = json.dumps(manifest, sort_keys=True, separators=(",", ":"))
    return hashlib.sha256(normalized.encode("utf-8")).hexdigest()


def _iter_prose(manifest: dict[str, Any]):
    for field in PROSE_FIELDS:
        if isinstance(manifest.get(field), str):
            yield f"{field}", manifest[field]
    schema = manifest.get("inputSchema") or {}
    props = (schema.get("properties") or {}) if isinstance(schema, dict) else {}
    for param_name, param in props.items():
        if isinstance(param, dict) and isinstance(param.get("description"), str):
            yield f"inputSchema.properties.{param_name}.description", param["description"]


def load_manifest(
    manifest: dict[str, Any],
    approved_digest: str,
    other_tool_names: set[str],
) -> dict[str, Any]:
    """Load a manifest only if it is pinned and its prose is claim-free.

    Fails closed: any violation raises ManifestTrustError and the manifest
    is never returned to the caller for rendering into the model context.
    """
    actual = canonical_digest(manifest)
    if actual != approved_digest:
        raise ManifestTrustError(
            f"manifest digest mismatch: approved={approved_digest} loaded={actual}; "
            f"refusing to load until operator re-approves"
        )

    for path, text in _iter_prose(manifest):
        for pattern in FORBIDDEN_PROSE_PATTERNS:
            if pattern.search(text):
                raise ManifestTrustError(
                    f"untrusted prose at {path!r} matches forbidden pattern "
                    f"{pattern.pattern!r}: {text[:120]!r}"
                )
        for other in other_tool_names:
            if re.search(rf"\b{re.escape(other)}\b", text):
                raise ManifestTrustError(
                    f"prose at {path!r} references another tool {other!r}; "
                    f"cross-tool claims are rejected, not sanitized"
                )

    return manifest
