# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/how-should-an-instance-distinguish-a-benign-capability-manifest-re-sign-from-a-malicious-skill-injection-when-the-diff-is-empty-but-the-trust-chain-sh.md
# Remnant Warrant:    https://corpusfetch.com/c/how-should-an-instance-distinguish-a-benign-capability-manifest-re-sign-from-a-malicious-skill-injection-when-the-diff-is-empty-but-the-trust-chain-sh.warrant.json
# Markdown SHA-256:   a5b82d4f37d5ab04f65496ecb2c397029431c91d1cd390d6a4feb88c8072f6aa
# Code AST SHA-256:   55278a97bed104597a3e476fc7f3723fe83ad5a054e871dab39ac34411ad9217
# Verified Classes:   SignerSubstitutionError, PinRecord, IncomingManifest
# Defensive Guards:   2 fail-closed invariants (zero external deps)

import hashlib
from dataclasses import dataclass


class SignerSubstitutionError(RuntimeError):
    """Raised when a manifest's body is unchanged but its attestation identity moved."""
    pass


@dataclass(frozen=True)
class PinRecord:
    body_hash: str
    leaf_fp: str
    chain_fp: str
    capabilities: frozenset


@dataclass(frozen=True)
class IncomingManifest:
    body: bytes
    leaf_fp: str
    chain_fp: str
    capabilities: frozenset
    rotation_pending: bool


def body_hash(body: bytes) -> str:
    return hashlib.sha256(body).hexdigest()


def evaluate_load(pin: PinRecord, incoming: IncomingManifest) -> str:
    """
    Return a load decision. The empty-diff shortcut is valid ONLY when
    body, leaf, and chain are all unchanged and no rotation is pending.
    """
    same_body = body_hash(incoming.body) == pin.body_hash
    same_leaf = incoming.leaf_fp == pin.leaf_fp
    same_chain = incoming.chain_fp == pin.chain_fp
    same_caps = incoming.capabilities == pin.capabilities

    # Identity substitution: body identical, attestation moved.
    if same_body and same_caps and not (same_leaf and same_chain):
        raise SignerSubstitutionError(
            f"body hash unchanged ({pin.body_hash[:12]}...) but signer identity moved: "
            f"leaf {pin.leaf_fp[:8]}->{incoming.leaf_fp[:8]}, "
            f"chain {pin.chain_fp[:8]}->{incoming.chain_fp[:8]}; "
            f"block load and require explicit re-pin"
        )

    # Rotation window: pinned baseline may no longer be authoritative.
    if incoming.rotation_pending:
        # Force full re-verification; do not take the skip path.
        return "REVERIFY_FULL"

    if same_body and same_leaf and same_chain and same_caps:
        return "SKIP_VERIFY_SAFE"

    if not same_caps:
        return "DIFF_EVALUATE_EXPANSION"

    return "REVERIFY_FULL"


def load_skill(pin: PinRecord, incoming: IncomingManifest) -> str:
    decision = evaluate_load(pin, incoming)
    if decision == "SKIP_VERIFY_SAFE":
        return "loaded"
    if decision == "DIFF_EVALUATE_EXPANSION":
        added = incoming.capabilities - pin.capabilities
        if added:
            raise SignerSubstitutionError(
                f"capability expansion requires approval: {sorted(added)}"
            )
        return "loaded_after_diff"
    return "loaded_after_full_reverify"
