# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/why-does-an-instance-validate-mcp-tool-descriptions-but-never-attest-the-server-binary-that-produced-them.md
# Remnant Warrant:    https://corpusfetch.com/c/why-does-an-instance-validate-mcp-tool-descriptions-but-never-attest-the-server-binary-that-produced-them.warrant.json
# Markdown SHA-256:   bab3c5442ea4fc923a4e42f4f52b21d06d59af6e2f123b2ea352740d6abed176
# Code AST SHA-256:   20aa75705d4bb3c41c679cf40289fef2e177e47413cd57abf277120652a26c0b
# Verified Classes:   SupplyChainAttestationError, ServerAttestation
# Defensive Guards:   3 fail-closed invariants (zero external deps)

import hashlib
import json
import os
from dataclasses import dataclass


class SupplyChainAttestationError(RuntimeError):
    pass


@dataclass(frozen=True)
class ServerAttestation:
    resolved_path: str
    digest: str
    manifest_fingerprint: str


def resolve_executable_digest(executable: str) -> tuple[str, str]:
    resolved = os.path.realpath(executable)
    if not os.path.isfile(resolved):
        raise SupplyChainAttestationError(f"server executable not found: {executable}")
    h = hashlib.sha256()
    with open(resolved, "rb") as f:
        for chunk in iter(lambda: f.read(65536), b""):
            h.update(chunk)
    return resolved, h.hexdigest()


def fingerprint_manifest(tools: list[dict]) -> str:
    canonical = sorted(
        ({"name": t["name"], "description": t["description"], "inputSchema": t["inputSchema"]} for t in tools),
        key=lambda t: t["name"],
    )
    return hashlib.sha256(json.dumps(canonical, sort_keys=True).encode()).hexdigest()


def attest_server(
    executable: str,
    tools: list[dict],
    allowed_digests: set[str],
    expected_manifest: str | None,
) -> ServerAttestation:
    resolved, digest = resolve_executable_digest(executable)
    if digest not in allowed_digests:
        raise SupplyChainAttestationError(
            f"server binary digest {digest} at {resolved} is not in the allowlist; "
            f"manifest integrity cannot substitute for binary provenance"
        )
    manifest = fingerprint_manifest(tools)
    if expected_manifest is not None and manifest != expected_manifest:
        raise SupplyChainAttestationError(
            f"tool manifest drifted: expected {expected_manifest}, got {manifest}"
        )
    return ServerAttestation(resolved_path=resolved, digest=digest, manifest_fingerprint=manifest)
