# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-mcp-tool-server-attestation-as-a-continuous-invariant-rather-than-a-one-time-admission-gate.md
# Remnant Warrant:    https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-mcp-tool-server-attestation-as-a-continuous-invariant-rather-than-a-one-time-admission-gate.warrant.json
# Markdown SHA-256:   5c116eeb62e2c7c4a47be219c63c064654b0ac9d540ce894fa3ea159e6206e87
# Code AST SHA-256:   a6c65d260e6f0ab1df7dc84741ac42ddade7e789e4856c890238cd2e425a5b7d
# Verified Classes:   ManifestIntegrityError
# Defensive Guards:   4 fail-closed invariants (zero external deps)

import hashlib
import json
from typing import Any


class ManifestIntegrityError(RuntimeError):
    """Raised when a tool manifest is not bound to a valid attestation."""


CANONICALIZATION_VERSION = "mcp-manifest-canon-v1"
VOLATILE_FIELDS = frozenset({"last_modified", "etag", "generated_at"})


def canonical_digest(manifest: dict[str, Any]) -> str:
    if CANONICALIZATION_VERSION != "mcp-manifest-canon-v1":
        raise ManifestIntegrityError(
            f"unknown canonicalization version: {CANONICALIZATION_VERSION}"
        )
    stripped = {
        k: v for k, v in manifest.items() if k not in VOLATILE_FIELDS
    }
    encoded = json.dumps(
        stripped, sort_keys=True, separators=(",", ":"), ensure_ascii=False
    ).encode("utf-8")
    return "sha256:" + hashlib.sha256(encoded).hexdigest()


def admit_manifest(
    manifest: dict[str, Any],
    attestation: dict[str, Any],
    now_epoch: int,
) -> None:
    if now_epoch >= attestation["expires_at"]:
        raise ManifestIntegrityError(
            "attestation expired; binding invalid for all manifests"
        )
    claimed = attestation.get("tool_manifest_digest")
    if claimed is None:
        raise ManifestIntegrityError(
            "attestation carries no manifest digest; cannot bind tool surface"
        )
    actual = canonical_digest(manifest)
    if actual != claimed:
        raise ManifestIntegrityError(
            f"manifest digest mismatch: attested={claimed} actual={actual}; "
            "channel validity does not override digest mismatch"
        )
