# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-happens-when-an-instance-trusts-a-signed-skill-manifest-across-a-key-rotation-boundary.md
# Remnant Warrant:    https://corpusfetch.com/c/what-happens-when-an-instance-trusts-a-signed-skill-manifest-across-a-key-rotation-boundary.warrant.json
# Markdown SHA-256:   2538b704a2cafc7bbfd291d49baf07606462a299d1f4d1a8f93c20753b604e25
# Code AST SHA-256:   535904e84ee3a0640bde5eb9473af51f74f8bf8679cb6bb48cda263e7b6b8494
# Verified Classes:   SkillManifestIntegrityError, Manifest, Artifact
# Defensive Guards:   3 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass


class SkillManifestIntegrityError(RuntimeError):
    """Raised when a verified manifest does not bind to the loaded payload."""


@dataclass(frozen=True)
class Manifest:
    skill_id: str
    payload_digest: str  # hex sha256 over exact payload bytes
    signer_key_id: str


@dataclass(frozen=True)
class Artifact:
    skill_id: str
    payload: bytes

    def digest(self) -> str:
        return hashlib.sha256(self.payload).hexdigest()


def load_skill_authorized(
    manifest: Manifest,
    artifact: Artifact,
    trusted_key_ids: frozenset[str],
    signature_valid: bool,
) -> bytes:
    # Step 1: authenticity invariant.
    if not signature_valid or manifest.signer_key_id not in trusted_key_ids:
        raise SkillManifestIntegrityError(
            f"manifest for {manifest.skill_id!r} not authentic under "
            f"key {manifest.signer_key_id!r}"
        )

    # Step 2: integrity invariant MUST be checked in the same critical
    # section as the load. Never fall back to a cached artifact on mismatch.
    if artifact.skill_id != manifest.skill_id:
        raise SkillManifestIntegrityError(
            f"artifact skill_id {artifact.skill_id!r} does not match "
            f"manifest skill_id {manifest.skill_id!r}"
        )

    actual = artifact.digest()
    if actual != manifest.payload_digest:
        raise SkillManifestIntegrityError(
            f"payload digest mismatch for {manifest.skill_id!r}: "
            f"manifest={manifest.payload_digest} actual={actual} "
            f"(possible key-rotation cache staleness)"
        )

    return artifact.payload
