# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/when-must-an-instance-reject-a-skill-whose-signature-verifies-but-whose-provenance-chain-is-broken.md
# Remnant Warrant:    https://corpusfetch.com/c/when-must-an-instance-reject-a-skill-whose-signature-verifies-but-whose-provenance-chain-is-broken.warrant.json
# Markdown SHA-256:   be0b5da40c767f8953691b9ef56d729d4c539c0883ba3658ba9ccc753d0d80a4
# Code AST SHA-256:   1199d91dd525675610be946b6a0777befebca2c03abd719f60451c3ef0d6c603
# Verified Classes:   ProvenanceError, Admission, Attestation, DelegationCert
# Defensive Guards:   2 fail-closed invariants (zero external deps)

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from enum import Enum
from typing import Iterable


class ProvenanceError(RuntimeError):
    """Raised when a skill's provenance chain cannot be established."""


class Admission(Enum):
    ADMIT = "admit"
    QUARANTINE = "quarantine"
    REJECT = "reject"


@dataclass(frozen=True)
class Attestation:
    subject_digest: str
    builder_id: str
    materials: dict[str, str] | None  # None => field absent (schema gap)
    signed_at: datetime


@dataclass(frozen=True)
class DelegationCert:
    builder_id: str
    not_before: datetime
    not_after: datetime


def evaluate_admission(
    *,
    signature_valid: bool,
    artifact_digest: str,
    attestation: Attestation | None,
    resolved_dependencies: dict[str, str],
    builder_allowlist: frozenset[str],
    delegation_certs: Iterable[DelegationCert],
) -> Admission:
    # Signature validity is necessary, never sufficient.
    if not signature_valid:
        return Admission.REJECT
    if attestation is None:
        # No attestation at all: unverifiable provenance, not provably broken.
        return Admission.QUARANTINE

    # Subject digest must match the artifact about to be executed.
    if attestation.subject_digest != artifact_digest:
        return Admission.REJECT

    # Builder must be in the allowlist.
    if attestation.builder_id not in builder_allowlist:
        return Admission.REJECT

    # Builder's delegation certificate must cover the signing time.
    cert = next(
        (c for c in delegation_certs if c.builder_id == attestation.builder_id),
        None,
    )
    if cert is None:
        # Unknown builder identity: unevaluable, quarantine.
        return Admission.QUARANTINE
    if not (cert.not_before <= attestation.signed_at <= cert.not_after):
        return Admission.REJECT

    # Material completeness: absence is quarantine, incompleteness is reject.
    if attestation.materials is None:
        return Admission.QUARANTINE
    for name, digest in resolved_dependencies.items():
        if attestation.materials.get(name) != digest:
            return Admission.REJECT

    return Admission.ADMIT


def load_skill(
    *,
    signature_valid: bool,
    artifact_digest: str,
    attestation: Attestation | None,
    resolved_dependencies: dict[str, str],
    builder_allowlist: frozenset[str],
    delegation_certs: Iterable[DelegationCert],
) -> str:
    verdict = evaluate_admission(
        signature_valid=signature_valid,
        artifact_digest=artifact_digest,
        attestation=attestation,
        resolved_dependencies=resolved_dependencies,
        builder_allowlist=builder_allowlist,
        delegation_certs=delegation_certs,
    )
    if verdict is Admission.REJECT:
        raise ProvenanceError(
            f"provenance chain broken for artifact {artifact_digest!r}; "
            f"signature valid but attestation predicates failed"
        )
    if verdict is Admission.QUARANTINE:
        raise ProvenanceError(
            f"provenance unevaluable for artifact {artifact_digest!r}; "
            f"hold for review, do not execute"
        )
    return artifact_digest
