"""Constitutional module - F2 Truth enforced
Part of arifOS constitutional governance system
DITEMPA BUKAN DIBERI - Forged, not given
"""

"""
eureka_receipt.py — EUREKA zkPC Receipt Manager for arifOS v37

Implements zkPC (Zero-Knowledge Proof of Cognition) receipts per:
- archive/versions/v36_3_omega/v36.3O/canon/VAULT999_ARCHITECTURE_v36.3O.md (L4 layer)
- archive/versions/v36_3_omega/v36.3O/spec/eureka_receipt_spec_v36.3O.json

Key concepts:
- EUREKA receipts anchor governed cognition without exposing internal reasoning
- Each receipt proves floor checks occurred without revealing actual values
- Hash-chained for integrity (like a blockchain of cognition proofs)
- Only SEAL/PARTIAL verdicts generate receipts (VOID/SABAR do not)

This is a STUB implementation using HMAC-SHA256 for signatures.
Production v37+ should use hardware-backed keys and actual zkSNARK proofs.

Author: arifOS Project
Version: v37
"""


import hashlib
import hmac
import json
import logging
import secrets
# Additional imports consolidated - F8 Tri-Witness
from dataclasses import dataclass, field
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Literal, Optional, Tuple, TYPE_CHECKING

if TYPE_CHECKING:
    from arifos_core.enforcement.metrics import Metrics


logger = logging.getLogger(__name__)


# =============================================================================
# TYPES
# =============================================================================

Stakeholder = Literal["user", "system", "earth", "third_party", "future"]
StakesClass = Literal["CLASS_A", "CLASS_B"]
ReceiptVerdict = Literal["SEAL", "PARTIAL"]


# =============================================================================
# DATA STRUCTURES
# =============================================================================

@dataclass
class CareScope:
    """
    Who/what this cognition was caring for.

    Fields:
        who: List of stakeholders in scope
        risk_cooled: Primary risk that was governed
        harm_prevented: Description of harm prevented (optional)
    """
    who: List[Stakeholder]
    risk_cooled: str
    harm_prevented: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {
            "who": self.who,
            "risk_cooled": self.risk_cooled,
            "harm_prevented": self.harm_prevented,
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "CareScope":
        return cls(
            who=data.get("who", ["user"]),
            risk_cooled=data.get("risk_cooled", "unspecified"),
            harm_prevented=data.get("harm_prevented"),
        )


@dataclass
class FloorProofs:
    """
    Per-floor proof status.

    Each boolean indicates that the floor was evaluated (not the result).
    This proves governance occurred without revealing actual metric values.
    """
    F1_truth: bool = True
    F2_delta_s: bool = True
    F3_peace_squared: bool = True
    F4_kappa_r: bool = True
    F5_omega_0: bool = True
    F6_amanah: bool = True
    F7_rasa: bool = True
    F8_tri_witness: bool = True
    F9_anti_hantu: bool = True

    def to_dict(self) -> Dict[str, bool]:
        return {
            "F1_truth": self.F1_truth,
            "F2_delta_s": self.F2_delta_s,
            "F3_peace_squared": self.F3_peace_squared,
            "F4_kappa_r": self.F4_kappa_r,
            "F5_omega_0": self.F5_omega_0,
            "F6_amanah": self.F6_amanah,
            "F7_rasa": self.F7_rasa,
            "F8_tri_witness": self.F8_tri_witness,
            "F9_anti_hantu": self.F9_anti_hantu,
        }

    def all_checked(self) -> bool:
        """Return True if all floors were evaluated."""
        return all([
            self.F1_truth, self.F2_delta_s, self.F3_peace_squared,
            self.F4_kappa_r, self.F5_omega_0, self.F6_amanah,
            self.F7_rasa, self.F8_tri_witness, self.F9_anti_hantu,
        ])


@dataclass
class CCEProofs:
    """
    CCE (Crown Cognitive Equation) audit proofs.

    Proves that the Delta/Omega/Psi/Phi computations were performed.
    """
    delta_p: bool = True
    omega_p: bool = True
    psi_p: bool = True
    phi_p: bool = False  # Phi (Paradox) is optional

    def to_dict(self) -> Dict[str, bool]:
        return {
            "delta_p": self.delta_p,
            "omega_p": self.omega_p,
            "psi_p": self.psi_p,
            "phi_p": self.phi_p,
        }


@dataclass
class TriWitnessScores:
    """
    Tri-Witness scores at the time of cognition.

    These are the actual scores (not proofs), included for transparency.
    In a true zkPC system, these would be committed but hidden.
    """
    human: float = 1.0
    ai: float = 1.0
    earth: float = 1.0
    consensus: float = 1.0

    def to_dict(self) -> Dict[str, float]:
        return {
            "human": self.human,
            "ai": self.ai,
            "earth": self.earth,
            "consensus": self.consensus,
        }

    @classmethod
    def from_metrics(cls, metrics: "Metrics") -> "TriWitnessScores":
        """Extract Tri-Witness scores from Metrics."""
        # Default to full scores; in production these would come from
        # actual witness consensus mechanisms
        return cls(
            human=1.0,
            ai=1.0,
            earth=1.0,
            consensus=getattr(metrics, "tri_witness", 1.0),
        )


@dataclass
class EurekaReceipt:
    """
    A EUREKA zkPC receipt per eureka_receipt_spec_v36.3O.json.

    Anchors governed cognition without exposing internal reasoning.
    Only SEAL/PARTIAL verdicts generate receipts.
    """
    receipt_id: str
    timestamp: str
    event_id: str  # SHA-256 of linked Cooling Ledger entry
    zkpc_hash: str  # SHA-256 of zkPC payload
    care_scope: CareScope
    floor_proofs: FloorProofs
    verdict: ReceiptVerdict
    stakes_class: StakesClass
    apex_signature: str
    merkle_root: str
    previous_receipt_hash: Optional[str]
    receipt_hash: str
    cce_proofs: Optional[CCEProofs] = None
    tri_witness: Optional[TriWitnessScores] = None
    extra: Dict[str, Any] = field(default_factory=dict)

    def to_dict(self) -> Dict[str, Any]:
        data = {
            "receipt_id": self.receipt_id,
            "timestamp": self.timestamp,
            "event_id": self.event_id,
            "zkpc_hash": self.zkpc_hash,
            "care_scope": self.care_scope.to_dict(),
            "floor_proofs": self.floor_proofs.to_dict(),
            "verdict": self.verdict,
            "class": self.stakes_class,
            "apex_signature": self.apex_signature,
            "merkle_root": self.merkle_root,
            "previous_receipt_hash": self.previous_receipt_hash,
            "receipt_hash": self.receipt_hash,
        }

        if self.cce_proofs:
            data["cce_proofs"] = self.cce_proofs.to_dict()

        if self.tri_witness:
            data["tri_witness"] = self.tri_witness.to_dict()

        if self.extra:
            data["extra"] = self.extra

        return data

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "EurekaReceipt":
        care_scope = CareScope.from_dict(data.get("care_scope", {}))

        floor_proofs_data = data.get("floor_proofs", {})
        floor_proofs = FloorProofs(
            F1_truth=floor_proofs_data.get("F1_truth", True),
            F2_delta_s=floor_proofs_data.get("F2_delta_s", True),
            F3_peace_squared=floor_proofs_data.get("F3_peace_squared", True),
            F4_kappa_r=floor_proofs_data.get("F4_kappa_r", True),
            F5_omega_0=floor_proofs_data.get("F5_omega_0", True),
            F6_amanah=floor_proofs_data.get("F6_amanah", True),
            F7_rasa=floor_proofs_data.get("F7_rasa", True),
            F8_tri_witness=floor_proofs_data.get("F8_tri_witness", True),
            F9_anti_hantu=floor_proofs_data.get("F9_anti_hantu", True),
        )

        cce_proofs = None
        if "cce_proofs" in data:
            cce_data = data["cce_proofs"]
            cce_proofs = CCEProofs(
                delta_p=cce_data.get("delta_p", True),
                omega_p=cce_data.get("omega_p", True),
                psi_p=cce_data.get("psi_p", True),
                phi_p=cce_data.get("phi_p", False),
            )

        tri_witness = None
        if "tri_witness" in data:
            tw_data = data["tri_witness"]
            tri_witness = TriWitnessScores(
                human=tw_data.get("human", 1.0),
                ai=tw_data.get("ai", 1.0),
                earth=tw_data.get("earth", 1.0),
                consensus=tw_data.get("consensus", 1.0),
            )

        return cls(
            receipt_id=data.get("receipt_id", ""),
            timestamp=data.get("timestamp", ""),
            event_id=data.get("event_id", ""),
            zkpc_hash=data.get("zkpc_hash", ""),
            care_scope=care_scope,
            floor_proofs=floor_proofs,
            verdict=data.get("verdict", "SEAL"),
            stakes_class=data.get("class", "CLASS_A"),
            apex_signature=data.get("apex_signature", ""),
            merkle_root=data.get("merkle_root", ""),
            previous_receipt_hash=data.get("previous_receipt_hash"),
            receipt_hash=data.get("receipt_hash", ""),
            cce_proofs=cce_proofs,
            tri_witness=tri_witness,
            extra=data.get("extra", {}),
        )


# =============================================================================
# EUREKA RECEIPT MANAGER
# =============================================================================

@dataclass
class EurekaConfig:
    """Configuration for EUREKA receipt manager."""
    receipts_path: Path = Path("runtime/vault_999/eureka_receipts.jsonl")
    merkle_state_path: Path = Path("runtime/vault_999/eureka_merkle_state.json")
    # HMAC key for signing (stub - in production use KMS)
    # TODO(Arif): Replace with hardware-backed keys in v37+
    hmac_key: bytes = field(default_factory=lambda: b"eureka_apex_stub_key_v37")


@dataclass
class MerkleState:
    """
    Merkle tree state for EUREKA receipt chain.

    In production, this would be a proper Merkle tree.
    This stub maintains just the root hash updated incrementally.
    """
    merkle_root: str = "0" * 64
    receipt_count: int = 0
    last_receipt_hash: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {
            "merkle_root": self.merkle_root,
            "receipt_count": self.receipt_count,
            "last_receipt_hash": self.last_receipt_hash,
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "MerkleState":
        return cls(
            merkle_root=data.get("merkle_root", "0" * 64),
            receipt_count=data.get("receipt_count", 0),
            last_receipt_hash=data.get("last_receipt_hash"),
        )


class EurekaReceiptManager:
    """
    Manager for EUREKA zkPC receipts (L4 layer of VAULT-999).

    Responsibilities:
    - Generate receipts for SEAL/PARTIAL verdicts
    - Maintain hash chain of receipts
    - Update Merkle root
    - Sign receipts with APEX PRIME authority

    This is a STUB implementation. Production v37+ should:
    - Use actual zkSNARK proofs
    - Use hardware-backed signing keys
    - Integrate with external transparency logs (e.g., Rekor)

    Usage:
        manager = EurekaReceiptManager()

        # Generate receipt for a governed cognition event
        receipt = manager.generate_receipt(
            ledger_entry_hash="abc123...",
            verdict="SEAL",
            stakes_class="CLASS_A",
            care_scope=CareScope(who=["user"], risk_cooled="misinformation"),
            metrics=metrics,
        )

        # Verify a receipt
        valid, error = manager.verify_receipt(receipt)
    """

    def __init__(self, config: Optional[EurekaConfig] = None):
        self.config = config or EurekaConfig()
        self.config.receipts_path.parent.mkdir(parents=True, exist_ok=True)

        # Load Merkle state
        self._merkle_state = self._load_merkle_state()

    def _load_merkle_state(self) -> MerkleState:
        """Load Merkle state from JSON file."""
        path = self.config.merkle_state_path
        if not path.exists():
            return MerkleState()

        try:
            with path.open("r", encoding="utf-8") as f:
                data = json.load(f)
                return MerkleState.from_dict(data)
        except (json.JSONDecodeError, IOError) as e:
            logger.warning(f"Failed to load Merkle state: {e}")
            return MerkleState()

    def _save_merkle_state(self) -> bool:
        """Save Merkle state to JSON file."""
        try:
            path = self.config.merkle_state_path
            path.parent.mkdir(parents=True, exist_ok=True)
            with path.open("w", encoding="utf-8") as f:
                json.dump(self._merkle_state.to_dict(), f, indent=2)
            return True
        except IOError as e:
            logger.error(f"Failed to save Merkle state: {e}")
            return False

    def _generate_receipt_id(self) -> str:
        """Generate a unique EUREKA receipt ID per spec pattern."""
        date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d")
        random_suffix = secrets.token_hex(4).upper()
        return f"EUREKA-{date_str}-{random_suffix}"

    def _compute_zkpc_hash(
        self,
        metrics: Optional["Metrics"],
        floor_proofs: FloorProofs,
    ) -> str:
        """
        Compute zkPC hash from metrics and floor proofs.

        In production, this would be the hash of an actual zkSNARK proof.
        This stub hashes the floor proof booleans and a metrics summary.
        """
        payload = {
            "floor_proofs": floor_proofs.to_dict(),
            "metrics_summary": "checked" if metrics else "none",
            "timestamp": time.time(),
        }
        canonical = json.dumps(payload, sort_keys=True)
        return hashlib.sha256(canonical.encode()).hexdigest()

    def _compute_receipt_hash(self, receipt_data: Dict[str, Any]) -> str:
        """
        Compute hash of receipt (excluding receipt_hash, apex_signature, merkle_root).

        These fields are added after the hash is computed, so they must be excluded
        from hash computation during verification.

        Uses canonical JSON representation.
        """
        # Exclude fields that are added after hash computation
        excluded_fields = {"receipt_hash", "apex_signature", "merkle_root"}
        data = {k: v for k, v in receipt_data.items() if k not in excluded_fields}
        canonical = json.dumps(data, sort_keys=True, separators=(",", ":"))
        return hashlib.sha256(canonical.encode()).hexdigest()

    def _sign_receipt(self, receipt_hash: str) -> str:
        """
        Sign the receipt hash using HMAC-SHA256.

        In production, this should use hardware-backed APEX PRIME keys.
        """
        sig = hmac.new(
            self.config.hmac_key,
            receipt_hash.encode(),
            hashlib.sha256,
        ).hexdigest()
        return sig

    def _update_merkle_root(self, receipt_hash: str) -> str:
        """
        Update the Merkle root with a new receipt.

        This stub uses a simple chain: new_root = hash(old_root + receipt_hash)
        Production should use a proper Merkle tree structure.
        """
        combined = self._merkle_state.merkle_root + receipt_hash
        new_root = hashlib.sha256(combined.encode()).hexdigest()
        return new_root

    def _append_receipt(self, receipt: EurekaReceipt) -> bool:
        """Append a receipt to the JSONL file."""
        try:
            path = self.config.receipts_path
            path.parent.mkdir(parents=True, exist_ok=True)
            with path.open("a", encoding="utf-8") as f:
                f.write(json.dumps(receipt.to_dict(), sort_keys=True) + "\n")
            return True
        except IOError as e:
            logger.error(f"Failed to append receipt: {e}")
            return False

    # =========================================================================
    # PUBLIC API
    # =========================================================================

    def generate_receipt(
        self,
        ledger_entry_hash: str,
        verdict: ReceiptVerdict,
        stakes_class: StakesClass,
        care_scope: CareScope,
        metrics: Optional["Metrics"] = None,
        floor_proofs: Optional[FloorProofs] = None,
        cce_proofs: Optional[CCEProofs] = None,
        extra: Optional[Dict[str, Any]] = None,
    ) -> Tuple[bool, Optional[EurekaReceipt], Optional[str]]:
        """
        Generate an EUREKA receipt for a governed cognition event.

        Only SEAL and PARTIAL verdicts should generate receipts.
        VOID and SABAR do not generate receipts (cognition was blocked).

        Args:
            ledger_entry_hash: SHA-256 hash of the linked Cooling Ledger entry
            verdict: The governance verdict (SEAL or PARTIAL)
            stakes_class: CLASS_A (fast path) or CLASS_B (full pipeline)
            care_scope: Who/what this cognition was caring for
            metrics: Optional Metrics instance for Tri-Witness extraction
            floor_proofs: Optional custom floor proofs (defaults to all True)
            cce_proofs: Optional CCE audit proofs
            extra: Optional extra fields

        Returns:
            Tuple of (success, EurekaReceipt or None, error message or None)
        """
        # Validate verdict
        if verdict not in ("SEAL", "PARTIAL"):
            return (False, None, f"Invalid verdict for receipt: {verdict}")

        # Generate IDs and timestamps
        receipt_id = self._generate_receipt_id()
        timestamp = datetime.now(timezone.utc).isoformat()

        # Floor proofs default to all checked
        if floor_proofs is None:
            floor_proofs = FloorProofs()

        # Compute zkPC hash
        zkpc_hash = self._compute_zkpc_hash(metrics, floor_proofs)

        # Extract Tri-Witness from metrics if available
        tri_witness = None
        if metrics:
            tri_witness = TriWitnessScores.from_metrics(metrics)

        # Get previous receipt hash for chaining
        previous_hash = self._merkle_state.last_receipt_hash

        # Build receipt data (without hash and signature yet)
        receipt_data = {
            "receipt_id": receipt_id,
            "timestamp": timestamp,
            "event_id": ledger_entry_hash,
            "zkpc_hash": zkpc_hash,
            "care_scope": care_scope.to_dict(),
            "floor_proofs": floor_proofs.to_dict(),
            "verdict": verdict,
            "class": stakes_class,
            "previous_receipt_hash": previous_hash,
        }

        if cce_proofs:
            receipt_data["cce_proofs"] = cce_proofs.to_dict()

        if tri_witness:
            receipt_data["tri_witness"] = tri_witness.to_dict()

        if extra:
            receipt_data["extra"] = extra

        # Compute receipt hash
        receipt_hash = self._compute_receipt_hash(receipt_data)
        receipt_data["receipt_hash"] = receipt_hash

        # Sign the receipt
        apex_signature = self._sign_receipt(receipt_hash)
        receipt_data["apex_signature"] = apex_signature

        # Update Merkle root
        new_merkle_root = self._update_merkle_root(receipt_hash)
        receipt_data["merkle_root"] = new_merkle_root

        # Create receipt object
        receipt = EurekaReceipt(
            receipt_id=receipt_id,
            timestamp=timestamp,
            event_id=ledger_entry_hash,
            zkpc_hash=zkpc_hash,
            care_scope=care_scope,
            floor_proofs=floor_proofs,
            verdict=verdict,
            stakes_class=stakes_class,
            apex_signature=apex_signature,
            merkle_root=new_merkle_root,
            previous_receipt_hash=previous_hash,
            receipt_hash=receipt_hash,
            cce_proofs=cce_proofs,
            tri_witness=tri_witness,
            extra=extra or {},
        )

        # Persist receipt
        if not self._append_receipt(receipt):
            return (False, None, "Failed to persist receipt")

        # Update Merkle state
        self._merkle_state.merkle_root = new_merkle_root
        self._merkle_state.receipt_count += 1
        self._merkle_state.last_receipt_hash = receipt_hash

        if not self._save_merkle_state():
            logger.warning("Receipt saved but Merkle state update failed")

        logger.info(f"Generated EUREKA receipt: {receipt_id}")
        return (True, receipt, None)

    def verify_receipt(self, receipt: EurekaReceipt) -> Tuple[bool, Optional[str]]:
        """
        Verify an EUREKA receipt.

        Checks:
        1. Receipt hash matches computed hash
        2. Signature is valid
        3. Floor proofs are present

        Note: Does NOT verify chain integrity (use verify_chain for that)

        Args:
            receipt: The receipt to verify

        Returns:
            Tuple of (valid, error message or None)
        """
        # Recompute receipt hash
        receipt_data = receipt.to_dict()
        computed_hash = self._compute_receipt_hash(receipt_data)

        if computed_hash != receipt.receipt_hash:
            return (False, f"Receipt hash mismatch: expected {receipt.receipt_hash[:8]}..., computed {computed_hash[:8]}...")

        # Verify signature
        expected_sig = self._sign_receipt(receipt.receipt_hash)
        if expected_sig != receipt.apex_signature:
            return (False, "Invalid APEX signature")

        # Check floor proofs are present
        if not receipt.floor_proofs.all_checked():
            return (False, "Not all floors were checked")

        return (True, None)

    def verify_chain(self) -> Tuple[bool, str]:
        """
        Verify the integrity of the EUREKA receipt chain.

        Checks that each receipt properly chains to the previous one.

        Returns:
            Tuple of (valid, status message)
        """
        path = self.config.receipts_path
        if not path.exists():
            return (True, "Empty receipt chain (valid)")

        receipts: List[EurekaReceipt] = []

        try:
            with path.open("r", encoding="utf-8") as f:
                for line_num, line in enumerate(f, start=1):
                    line = line.strip()
                    if not line:
                        continue
                    try:
                        data = json.loads(line)
                        receipt = EurekaReceipt.from_dict(data)
                        receipts.append(receipt)
                    except (json.JSONDecodeError, TypeError) as e:
                        return (False, f"Parse error at line {line_num}: {e}")
        except IOError as e:
            return (False, f"IO error: {e}")

        if not receipts:
            return (True, "Empty receipt chain (valid)")

        # Verify first receipt has no previous
        if receipts[0].previous_receipt_hash is not None:
            return (False, "First receipt should have null previous_receipt_hash")

        # Verify chain integrity
        for i, receipt in enumerate(receipts):
            # Verify individual receipt
            valid, error = self.verify_receipt(receipt)
            if not valid:
                return (False, f"Receipt {i} invalid: {error}")

            # Verify chain link
            if i > 0:
                expected_prev = receipts[i - 1].receipt_hash
                if receipt.previous_receipt_hash != expected_prev:
                    return (False, f"Receipt {i} chain break: expected prev={expected_prev[:8]}..., actual={receipt.previous_receipt_hash[:8] if receipt.previous_receipt_hash else 'null'}...")

        return (True, f"Chain verified: {len(receipts)} receipts")

    def get_merkle_state(self) -> MerkleState:
        """Return current Merkle state."""
        return self._merkle_state

    def get_receipt_count(self) -> int:
        """Return total number of receipts."""
        return self._merkle_state.receipt_count

    def iter_receipts(self, limit: int = 100) -> List[EurekaReceipt]:
        """
        Iterate over recent receipts (most recent first).

        Args:
            limit: Maximum number of receipts to return

        Returns:
            List of EurekaReceipts
        """
        path = self.config.receipts_path
        if not path.exists():
            return []

        receipts: List[EurekaReceipt] = []

        try:
            with path.open("r", encoding="utf-8") as f:
                for line in f:
                    line = line.strip()
                    if not line:
                        continue
                    try:
                        data = json.loads(line)
                        receipt = EurekaReceipt.from_dict(data)
                        receipts.append(receipt)
                    except (json.JSONDecodeError, TypeError):
                        continue
        except IOError:
            return []

        # Return most recent first
        receipts.reverse()
        return receipts[:limit]


# =============================================================================
# CONVENIENCE FUNCTIONS
# =============================================================================

def generate_eureka_receipt(
    ledger_entry_hash: str,
    verdict: str,
    stakes_class: str = "CLASS_A",
    risk_cooled: str = "general governance",
    stakeholders: Optional[List[str]] = None,
    metrics: Optional["Metrics"] = None,
) -> Tuple[bool, Optional[EurekaReceipt], Optional[str]]:
    """
    Convenience function to generate an EUREKA receipt.

    Args:
        ledger_entry_hash: Hash of the linked Cooling Ledger entry
        verdict: The governance verdict
        stakes_class: CLASS_A or CLASS_B
        risk_cooled: Description of the risk that was governed
        stakeholders: List of stakeholder types
        metrics: Optional Metrics instance

    Returns:
        Tuple of (success, EurekaReceipt or None, error message or None)
    """
    # Only generate for SEAL/PARTIAL
    if verdict not in ("SEAL", "PARTIAL"):
        return (True, None, None)  # Not an error, just no receipt needed

    care_scope = CareScope(
        who=stakeholders or ["user"],
        risk_cooled=risk_cooled,
    )

    manager = EurekaReceiptManager()
    return manager.generate_receipt(
        ledger_entry_hash=ledger_entry_hash,
        verdict=verdict,
        stakes_class=stakes_class,
        care_scope=care_scope,
        metrics=metrics,
    )


# =============================================================================
# PUBLIC EXPORTS
# =============================================================================

__all__ = [
    # Types
    "Stakeholder",
    "StakesClass",
    "ReceiptVerdict",
    # Data structures
    "CareScope",
    "FloorProofs",
    "CCEProofs",
    "TriWitnessScores",
    "EurekaReceipt",
    # Manager
    "EurekaConfig",
    "MerkleState",
    "EurekaReceiptManager",
    # Convenience
    "generate_eureka_receipt",
]
