Files
vm-core/docs/VAULTMESH-IMPLEMENTATION-SCAFFOLDS.md
2025-12-27 00:10:32 +00:00

50 KiB

VAULTMESH-IMPLEMENTATION-SCAFFOLDS.md

From Pattern to Code

Every specification deserves a skeleton.

This document provides implementation scaffolds for all VaultMesh engines — Rust structs for core types and Python CLI skeletons for tooling.


1. Shared Types (Rust)

1.1 Core Receipt Types

// vaultmesh-core/src/receipt.rs

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Universal receipt header present in all receipts
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReceiptHeader {
    pub receipt_type: String,
    pub timestamp: DateTime<Utc>,
    pub root_hash: String,
    pub tags: Vec<String>,
}

/// Receipt metadata for tracking and querying
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReceiptMeta {
    pub scroll: Scroll,
    pub sequence: u64,
    pub anchor_epoch: Option<u64>,
    pub proof_path: Option<String>,
}

/// Scroll identifiers
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum Scroll {
    Drills,
    Compliance,
    Guardian,
    Treasury,
    Mesh,
    OffSec,
    Identity,
    Observability,
    Automation,
    PsiField,
}

impl Scroll {
    pub fn jsonl_path(&self) -> &'static str {
        match self {
            Scroll::Drills => "receipts/drills/drill_runs.jsonl",
            Scroll::Compliance => "receipts/compliance/oracle_answers.jsonl",
            Scroll::Guardian => "receipts/guardian/anchor_events.jsonl",
            Scroll::Treasury => "receipts/treasury/treasury_events.jsonl",
            Scroll::Mesh => "receipts/mesh/mesh_events.jsonl",
            Scroll::OffSec => "receipts/offsec/offsec_events.jsonl",
            Scroll::Identity => "receipts/identity/identity_events.jsonl",
            Scroll::Observability => "receipts/observability/observability_events.jsonl",
            Scroll::Automation => "receipts/automation/automation_events.jsonl",
            Scroll::PsiField => "receipts/psi/psi_events.jsonl",
        }
    }

    pub fn root_file(&self) -> &'static str {
        match self {
            Scroll::Drills => "ROOT.drills.txt",
            Scroll::Compliance => "ROOT.compliance.txt",
            Scroll::Guardian => "ROOT.guardian.txt",
            Scroll::Treasury => "ROOT.treasury.txt",
            Scroll::Mesh => "ROOT.mesh.txt",
            Scroll::OffSec => "ROOT.offsec.txt",
            Scroll::Identity => "ROOT.identity.txt",
            Scroll::Observability => "ROOT.observability.txt",
            Scroll::Automation => "ROOT.automation.txt",
            Scroll::PsiField => "ROOT.psi.txt",
        }
    }
}

/// Generic receipt wrapper
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Receipt<T> {
    #[serde(flatten)]
    pub header: ReceiptHeader,
    #[serde(flatten)]
    pub meta: ReceiptMeta,
    #[serde(flatten)]
    pub body: T,
}

1.2 DID Types

// vaultmesh-core/src/did.rs

use serde::{Deserialize, Serialize};

/// VaultMesh DID
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct Did(String);

impl Did {
    pub fn new(did_type: DidType, identifier: &str) -> Self {
        Did(format!("did:vm:{}:{}", did_type.as_str(), identifier))
    }

    pub fn parse(s: &str) -> Result<Self, DidParseError> {
        if !s.starts_with("did:vm:") {
            return Err(DidParseError::InvalidPrefix);
        }
        Ok(Did(s.to_string()))
    }

    pub fn did_type(&self) -> Option<DidType> {
        let parts: Vec<&str> = self.0.split(':').collect();
        if parts.len() >= 3 {
            DidType::from_str(parts[2])
        } else {
            None
        }
    }

    pub fn identifier(&self) -> Option<&str> {
        let parts: Vec<&str> = self.0.split(':').collect();
        if parts.len() >= 4 {
            Some(parts[3])
        } else {
            None
        }
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DidType {
    Node,
    Human,
    Agent,
    Service,
    Mesh,
}

impl DidType {
    pub fn as_str(&self) -> &'static str {
        match self {
            DidType::Node => "node",
            DidType::Human => "human",
            DidType::Agent => "agent",
            DidType::Service => "service",
            DidType::Mesh => "mesh",
        }
    }

    pub fn from_str(s: &str) -> Option<Self> {
        match s {
            "node" => Some(DidType::Node),
            "human" => Some(DidType::Human),
            "agent" => Some(DidType::Agent),
            "service" => Some(DidType::Service),
            "mesh" => Some(DidType::Mesh),
            _ => None,
        }
    }
}

#[derive(Debug)]
pub enum DidParseError {
    InvalidPrefix,
    MissingType,
    MissingIdentifier,
}

1.3 Hash Utilities

// vaultmesh-core/src/hash.rs

use blake3::Hasher;
use serde::{Deserialize, Serialize};

/// VaultMesh hash with algorithm prefix
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct VmHash(String);

impl VmHash {
    /// Create hash from bytes using Blake3
    pub fn blake3(data: &[u8]) -> Self {
        let hash = blake3::hash(data);
        VmHash(format!("blake3:{}", hash.to_hex()))
    }

    /// Create hash from JSON-serializable value
    pub fn from_json<T: Serialize>(value: &T) -> Result<Self, serde_json::Error> {
        let json = serde_json::to_vec(value)?;
        Ok(Self::blake3(&json))
    }

    /// Create hash from file contents
    pub fn from_file(path: &std::path::Path) -> std::io::Result<Self> {
        let contents = std::fs::read(path)?;
        Ok(Self::blake3(&contents))
    }

    /// Get the raw hex value without prefix
    pub fn hex(&self) -> &str {
        self.0.strip_prefix("blake3:").unwrap_or(&self.0)
    }

    /// Get full prefixed value
    pub fn as_str(&self) -> &str {
        &self.0
    }
}

/// Compute Merkle root from list of hashes
pub fn merkle_root(hashes: &[VmHash]) -> VmHash {
    if hashes.is_empty() {
        return VmHash::blake3(b"empty");
    }
    if hashes.len() == 1 {
        return hashes[0].clone();
    }

    let mut current_level: Vec<VmHash> = hashes.to_vec();

    while current_level.len() > 1 {
        let mut next_level = Vec::new();

        for chunk in current_level.chunks(2) {
            let combined = if chunk.len() == 2 {
                format!("{}{}", chunk[0].hex(), chunk[1].hex())
            } else {
                format!("{}{}", chunk[0].hex(), chunk[0].hex())
            };
            next_level.push(VmHash::blake3(combined.as_bytes()));
        }

        current_level = next_level;
    }

    current_level.remove(0)
}

2. Treasury Engine (Rust)

// vaultmesh-treasury/src/lib.rs

use chrono::{DateTime, Utc};
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use vaultmesh_core::{Did, Receipt, ReceiptHeader, ReceiptMeta, Scroll, VmHash};

/// Treasury account
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Account {
    pub account_id: String,
    pub display_name: String,
    pub account_type: AccountType,
    pub currency: Currency,
    pub balance: Decimal,
    pub created_at: DateTime<Utc>,
    pub tags: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AccountType {
    Operational,
    Reserve,
    Escrow,
    External,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Currency {
    EUR,
    USD,
    GBP,
    BTC,
    ETH,
}

/// Treasury entry (single debit or credit)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entry {
    pub entry_id: String,
    pub entry_type: EntryType,
    pub account: String,
    pub amount: Decimal,
    pub currency: Currency,
    pub memo: String,
    pub timestamp: DateTime<Utc>,
    pub tags: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EntryType {
    Debit,
    Credit,
}

/// Settlement contract
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SettlementContract {
    pub settlement_id: String,
    pub title: String,
    pub initiated_by: Did,
    pub initiated_at: DateTime<Utc>,
    pub parties: Vec<Did>,
    pub entries: Vec<Entry>,
    pub requires_signatures: Vec<String>,
    pub settlement_type: SettlementType,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SettlementType {
    InterNodeResource,
    VendorPayment,
    ClientInvoice,
    GrantDisbursement,
}

/// Settlement state
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SettlementState {
    pub settlement_id: String,
    pub status: SettlementStatus,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub signatures: std::collections::HashMap<String, Option<Signature>>,
    pub entries_applied: bool,
    pub balance_snapshot_before: std::collections::HashMap<String, Decimal>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SettlementStatus {
    Draft,
    PendingSignatures,
    Executing,
    Completed,
    Disputed,
    Expired,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Signature {
    pub signed_at: DateTime<Utc>,
    pub signature: String,
}

// Receipt types

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TreasuryCreditReceipt {
    pub entry_id: String,
    pub account: String,
    pub amount: Decimal,
    pub currency: Currency,
    pub memo: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TreasuryDebitReceipt {
    pub entry_id: String,
    pub account: String,
    pub amount: Decimal,
    pub currency: Currency,
    pub memo: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TreasurySettlementReceipt {
    pub settlement_id: String,
    pub title: String,
    pub timestamp_initiated: DateTime<Utc>,
    pub timestamp_completed: DateTime<Utc>,
    pub status: SettlementStatus,
    pub parties: Vec<Did>,
    pub entries_count: usize,
    pub net_flow: std::collections::HashMap<String, Decimal>,
    pub currency: Currency,
    pub settlement_type: SettlementType,
    pub signatures_manifest: String,
}

/// Treasury engine
pub struct TreasuryEngine {
    accounts: std::collections::HashMap<String, Account>,
    pending_settlements: std::collections::HashMap<String, (SettlementContract, SettlementState)>,
}

impl TreasuryEngine {
    pub fn new() -> Self {
        TreasuryEngine {
            accounts: std::collections::HashMap::new(),
            pending_settlements: std::collections::HashMap::new(),
        }
    }

    pub fn create_account(&mut self, account: Account) -> Result<(), TreasuryError> {
        if self.accounts.contains_key(&account.account_id) {
            return Err(TreasuryError::AccountExists);
        }
        self.accounts.insert(account.account_id.clone(), account);
        Ok(())
    }

    pub fn record_entry(&mut self, entry: Entry) -> Result<Receipt<TreasuryCreditReceipt>, TreasuryError> {
        let account = self.accounts.get_mut(&entry.account)
            .ok_or(TreasuryError::AccountNotFound)?;

        match entry.entry_type {
            EntryType::Credit => account.balance += entry.amount,
            EntryType::Debit => {
                if account.balance < entry.amount {
                    return Err(TreasuryError::InsufficientBalance);
                }
                account.balance -= entry.amount;
            }
        }

        let receipt_body = TreasuryCreditReceipt {
            entry_id: entry.entry_id.clone(),
            account: entry.account.clone(),
            amount: entry.amount,
            currency: entry.currency,
            memo: entry.memo,
        };

        let root_hash = VmHash::from_json(&receipt_body)
            .map_err(|_| TreasuryError::SerializationError)?;

        Ok(Receipt {
            header: ReceiptHeader {
                receipt_type: "treasury_credit".to_string(),
                timestamp: entry.timestamp,
                root_hash: root_hash.as_str().to_string(),
                tags: entry.tags,
            },
            meta: ReceiptMeta {
                scroll: Scroll::Treasury,
                sequence: 0, // Set by receipt store
                anchor_epoch: None,
                proof_path: None,
            },
            body: receipt_body,
        })
    }

    pub fn initiate_settlement(&mut self, contract: SettlementContract) -> Result<SettlementState, TreasuryError> {
        // Validate all accounts exist
        for entry in &contract.entries {
            if !self.accounts.contains_key(&entry.account) {
                return Err(TreasuryError::AccountNotFound);
            }
        }

        // Capture balance snapshot
        let mut snapshot = std::collections::HashMap::new();
        for entry in &contract.entries {
            if !snapshot.contains_key(&entry.account) {
                let balance = self.accounts.get(&entry.account).unwrap().balance;
                snapshot.insert(entry.account.clone(), balance);
            }
        }

        let state = SettlementState {
            settlement_id: contract.settlement_id.clone(),
            status: SettlementStatus::PendingSignatures,
            created_at: contract.initiated_at,
            updated_at: Utc::now(),
            signatures: contract.requires_signatures.iter()
                .map(|s| (s.clone(), None))
                .collect(),
            entries_applied: false,
            balance_snapshot_before: snapshot,
        };

        self.pending_settlements.insert(
            contract.settlement_id.clone(),
            (contract, state.clone()),
        );

        Ok(state)
    }

    pub fn add_signature(
        &mut self,
        settlement_id: &str,
        signer: &str,
        signature: Signature,
    ) -> Result<SettlementState, TreasuryError> {
        let (_, state) = self.pending_settlements.get_mut(settlement_id)
            .ok_or(TreasuryError::SettlementNotFound)?;

        if !state.signatures.contains_key(signer) {
            return Err(TreasuryError::UnauthorizedSigner);
        }

        state.signatures.insert(signer.to_string(), Some(signature));
        state.updated_at = Utc::now();

        // Check if all signatures collected
        let all_signed = state.signatures.values().all(|s| s.is_some());
        if all_signed {
            state.status = SettlementStatus::Executing;
        }

        Ok(state.clone())
    }

    pub fn execute_settlement(&mut self, settlement_id: &str) -> Result<Receipt<TreasurySettlementReceipt>, TreasuryError> {
        let (contract, state) = self.pending_settlements.get_mut(settlement_id)
            .ok_or(TreasuryError::SettlementNotFound)?;

        if state.status != SettlementStatus::Executing {
            return Err(TreasuryError::SettlementNotReady);
        }

        // Apply all entries
        let mut net_flow: std::collections::HashMap<String, Decimal> = std::collections::HashMap::new();
        for entry in &contract.entries {
            let account = self.accounts.get_mut(&entry.account).unwrap();
            match entry.entry_type {
                EntryType::Credit => {
                    account.balance += entry.amount;
                    *net_flow.entry(entry.account.clone()).or_insert(Decimal::ZERO) += entry.amount;
                }
                EntryType::Debit => {
                    account.balance -= entry.amount;
                    *net_flow.entry(entry.account.clone()).or_insert(Decimal::ZERO) -= entry.amount;
                }
            }
        }

        state.entries_applied = true;
        state.status = SettlementStatus::Completed;
        state.updated_at = Utc::now();

        let receipt_body = TreasurySettlementReceipt {
            settlement_id: contract.settlement_id.clone(),
            title: contract.title.clone(),
            timestamp_initiated: contract.initiated_at,
            timestamp_completed: state.updated_at,
            status: SettlementStatus::Completed,
            parties: contract.parties.clone(),
            entries_count: contract.entries.len(),
            net_flow,
            currency: contract.entries.first().map(|e| e.currency.clone()).unwrap_or(Currency::EUR),
            settlement_type: contract.settlement_type.clone(),
            signatures_manifest: format!("cases/treasury/{}/SIGNATURES.json", settlement_id),
        };

        let root_hash = VmHash::from_json(&receipt_body)
            .map_err(|_| TreasuryError::SerializationError)?;

        Ok(Receipt {
            header: ReceiptHeader {
                receipt_type: "treasury_settlement".to_string(),
                timestamp: state.updated_at,
                root_hash: root_hash.as_str().to_string(),
                tags: vec!["treasury".to_string(), "settlement".to_string()],
            },
            meta: ReceiptMeta {
                scroll: Scroll::Treasury,
                sequence: 0,
                anchor_epoch: None,
                proof_path: Some(format!("cases/treasury/{}/PROOF.json", settlement_id)),
            },
            body: receipt_body,
        })
    }
}

#[derive(Debug)]
pub enum TreasuryError {
    AccountExists,
    AccountNotFound,
    InsufficientBalance,
    SettlementNotFound,
    SettlementNotReady,
    UnauthorizedSigner,
    SerializationError,
}

3. Identity Engine (Rust)

// vaultmesh-identity/src/lib.rs

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use vaultmesh_core::{Did, DidType, Receipt, ReceiptHeader, ReceiptMeta, Scroll, VmHash};

/// DID Document
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DidDocument {
    #[serde(rename = "@context")]
    pub context: Vec<String>,
    pub id: Did,
    pub controller: Option<Did>,
    #[serde(rename = "verificationMethod")]
    pub verification_method: Vec<VerificationMethod>,
    pub authentication: Vec<String>,
    #[serde(rename = "assertionMethod")]
    pub assertion_method: Vec<String>,
    pub service: Vec<Service>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VerificationMethod {
    pub id: String,
    #[serde(rename = "type")]
    pub method_type: String,
    pub controller: Did,
    #[serde(rename = "publicKeyMultibase")]
    pub public_key_multibase: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Service {
    pub id: String,
    #[serde(rename = "type")]
    pub service_type: String,
    #[serde(rename = "serviceEndpoint")]
    pub service_endpoint: String,
}

/// Verifiable Credential
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VerifiableCredential {
    pub credential_id: String,
    #[serde(rename = "@context")]
    pub context: Vec<String>,
    #[serde(rename = "type")]
    pub credential_type: Vec<String>,
    pub issuer: Did,
    #[serde(rename = "issuanceDate")]
    pub issuance_date: DateTime<Utc>,
    #[serde(rename = "expirationDate")]
    pub expiration_date: Option<DateTime<Utc>>,
    #[serde(rename = "credentialSubject")]
    pub credential_subject: CredentialSubject,
    pub proof: CredentialProof,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CredentialSubject {
    pub id: Did,
    #[serde(flatten)]
    pub claims: HashMap<String, serde_json::Value>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CredentialProof {
    #[serde(rename = "type")]
    pub proof_type: String,
    pub created: DateTime<Utc>,
    #[serde(rename = "verificationMethod")]
    pub verification_method: String,
    #[serde(rename = "proofPurpose")]
    pub proof_purpose: String,
    #[serde(rename = "proofValue")]
    pub proof_value: String,
}

/// Capability Token
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CapabilityToken {
    pub capability_id: String,
    pub holder: Did,
    pub capability: Capability,
    pub scope: CapabilityScope,
    pub granted_by: Did,
    pub granted_at: DateTime<Utc>,
    pub expires_at: DateTime<Utc>,
    pub constraints: HashMap<String, serde_json::Value>,
    pub proof: CredentialProof,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum Capability {
    Anchor,
    Storage,
    Compute,
    Oracle,
    Admin,
    Federate,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CapabilityScope {
    pub scrolls: Option<Vec<Scroll>>,
    pub backends: Option<Vec<String>>,
    pub max_rate: Option<String>,
}

/// Authentication Event
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthEvent {
    pub auth_event_id: String,
    pub subject: Did,
    pub target: Did,
    pub method: AuthMethod,
    pub result: AuthResult,
    pub timestamp: DateTime<Utc>,
    pub source_ip: Option<String>,
    pub session_id: Option<String>,
    pub credential_used: Option<String>,
    pub mfa_verified: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuthMethod {
    SshKey,
    Password,
    Certificate,
    Token,
    Passkey,
    Mfa,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AuthResult {
    Success,
    Failure,
    Denied,
    Expired,
}

// Receipt bodies

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DidCreateReceipt {
    pub did: Did,
    pub did_type: String,
    pub controller: Option<Did>,
    pub created_by: Did,
    pub initial_keys: Vec<String>,
    pub did_document_hash: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CredentialIssueReceipt {
    pub credential_id: String,
    pub credential_type: String,
    pub issuer: Did,
    pub subject: Did,
    pub expires_at: Option<DateTime<Utc>>,
    pub claims_summary: HashMap<String, String>,
    pub credential_hash: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CapabilityGrantReceipt {
    pub capability_id: String,
    pub holder: Did,
    pub capability: Capability,
    pub scope_summary: String,
    pub granted_by: Did,
    pub expires_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthEventReceipt {
    pub auth_event_id: String,
    pub subject: Did,
    pub target: Did,
    pub method: AuthMethod,
    pub result: AuthResult,
    pub source_ip_hash: Option<String>,
    pub mfa_verified: bool,
}

/// Identity Engine
pub struct IdentityEngine {
    did_documents: HashMap<Did, DidDocument>,
    credentials: HashMap<String, VerifiableCredential>,
    capabilities: HashMap<String, CapabilityToken>,
    revoked_credentials: HashMap<String, DateTime<Utc>>,
}

impl IdentityEngine {
    pub fn new() -> Self {
        IdentityEngine {
            did_documents: HashMap::new(),
            credentials: HashMap::new(),
            capabilities: HashMap::new(),
            revoked_credentials: HashMap::new(),
        }
    }

    pub fn create_did(
        &mut self,
        did_type: DidType,
        identifier: &str,
        controller: Option<Did>,
        public_key: &str,
        created_by: Did,
    ) -> Result<Receipt<DidCreateReceipt>, IdentityError> {
        let did = Did::new(did_type, identifier);

        if self.did_documents.contains_key(&did) {
            return Err(IdentityError::DidExists);
        }

        let key_id = format!("{}#key-1", did.as_str());

        let doc = DidDocument {
            context: vec![
                "https://www.w3.org/ns/did/v1".to_string(),
                "https://vaultmesh.io/ns/did/v1".to_string(),
            ],
            id: did.clone(),
            controller: controller.clone(),
            verification_method: vec![VerificationMethod {
                id: key_id.clone(),
                method_type: "Ed25519VerificationKey2020".to_string(),
                controller: did.clone(),
                public_key_multibase: public_key.to_string(),
            }],
            authentication: vec![key_id.clone()],
            assertion_method: vec![key_id.clone()],
            service: vec![],
        };

        let doc_hash = VmHash::from_json(&doc)
            .map_err(|_| IdentityError::SerializationError)?;

        self.did_documents.insert(did.clone(), doc);

        let receipt_body = DidCreateReceipt {
            did: did.clone(),
            did_type: did_type.as_str().to_string(),
            controller,
            created_by,
            initial_keys: vec![key_id],
            did_document_hash: doc_hash.as_str().to_string(),
        };

        let root_hash = VmHash::from_json(&receipt_body)
            .map_err(|_| IdentityError::SerializationError)?;

        Ok(Receipt {
            header: ReceiptHeader {
                receipt_type: "identity_did_create".to_string(),
                timestamp: Utc::now(),
                root_hash: root_hash.as_str().to_string(),
                tags: vec!["identity".to_string(), "did".to_string(), "create".to_string()],
            },
            meta: ReceiptMeta {
                scroll: Scroll::Identity,
                sequence: 0,
                anchor_epoch: None,
                proof_path: None,
            },
            body: receipt_body,
        })
    }

    pub fn resolve_did(&self, did: &Did) -> Option<&DidDocument> {
        self.did_documents.get(did)
    }

    pub fn issue_credential(
        &mut self,
        credential: VerifiableCredential,
    ) -> Result<Receipt<CredentialIssueReceipt>, IdentityError> {
        // Verify issuer exists
        if !self.did_documents.contains_key(&credential.issuer) {
            return Err(IdentityError::IssuerNotFound);
        }

        let credential_hash = VmHash::from_json(&credential)
            .map_err(|_| IdentityError::SerializationError)?;

        let claims_summary: HashMap<String, String> = credential.credential_subject.claims
            .iter()
            .map(|(k, v)| (k.clone(), v.to_string()))
            .collect();

        let receipt_body = CredentialIssueReceipt {
            credential_id: credential.credential_id.clone(),
            credential_type: credential.credential_type.join(", "),
            issuer: credential.issuer.clone(),
            subject: credential.credential_subject.id.clone(),
            expires_at: credential.expiration_date,
            claims_summary,
            credential_hash: credential_hash.as_str().to_string(),
        };

        self.credentials.insert(credential.credential_id.clone(), credential);

        let root_hash = VmHash::from_json(&receipt_body)
            .map_err(|_| IdentityError::SerializationError)?;

        Ok(Receipt {
            header: ReceiptHeader {
                receipt_type: "identity_credential_issue".to_string(),
                timestamp: Utc::now(),
                root_hash: root_hash.as_str().to_string(),
                tags: vec!["identity".to_string(), "credential".to_string(), "issue".to_string()],
            },
            meta: ReceiptMeta {
                scroll: Scroll::Identity,
                sequence: 0,
                anchor_epoch: None,
                proof_path: None,
            },
            body: receipt_body,
        })
    }

    pub fn verify_credential(&self, credential_id: &str) -> Result<bool, IdentityError> {
        // Check if revoked
        if self.revoked_credentials.contains_key(credential_id) {
            return Ok(false);
        }

        let credential = self.credentials.get(credential_id)
            .ok_or(IdentityError::CredentialNotFound)?;

        // Check expiration
        if let Some(expires) = credential.expiration_date {
            if Utc::now() > expires {
                return Ok(false);
            }
        }

        // In production, would verify cryptographic proof here
        Ok(true)
    }

    pub fn check_capability(&self, holder: &Did, capability: Capability) -> bool {
        self.capabilities.values().any(|cap| {
            &cap.holder == holder
                && cap.capability == capability
                && Utc::now() < cap.expires_at
        })
    }
}

#[derive(Debug)]
pub enum IdentityError {
    DidExists,
    DidNotFound,
    IssuerNotFound,
    CredentialNotFound,
    CredentialRevoked,
    CapabilityDenied,
    SerializationError,
}

4. Python CLI Skeleton

#!/usr/bin/env python3
"""
VaultMesh Unified CLI
vm-cli - Gateway to all VaultMesh engines
"""

import click
from datetime import datetime
from pathlib import Path
from typing import Optional
import json

# ============================================================================
# Shared utilities
# ============================================================================

def emit_receipt(scroll: str, receipt_type: str, body: dict, tags: list[str]) -> dict:
    """Create and emit a receipt to the appropriate scroll."""
    import hashlib

    receipt = {
        "type": receipt_type,
        "timestamp": datetime.utcnow().isoformat() + "Z",
        "tags": tags,
        **body
    }

    # Compute root hash
    receipt_json = json.dumps(receipt, sort_keys=True)
    root_hash = f"blake3:{hashlib.blake3(receipt_json.encode()).hexdigest()}"
    receipt["root_hash"] = root_hash

    # Append to scroll
    scroll_path = Path(f"receipts/{scroll}/{scroll}_events.jsonl")
    scroll_path.parent.mkdir(parents=True, exist_ok=True)

    with open(scroll_path, "a") as f:
        f.write(json.dumps(receipt) + "\n")

    # Update Merkle root (simplified)
    root_file = Path(f"ROOT.{scroll}.txt")
    root_file.write_text(root_hash)

    return receipt

def load_receipts(scroll: str, filters: dict = None) -> list[dict]:
    """Load and optionally filter receipts from a scroll."""
    scroll_path = Path(f"receipts/{scroll}/{scroll}_events.jsonl")

    if not scroll_path.exists():
        return []

    receipts = []
    with open(scroll_path) as f:
        for line in f:
            receipt = json.loads(line.strip())

            # Apply filters
            if filters:
                match = True
                for key, value in filters.items():
                    if key == "from_date":
                        if receipt.get("timestamp", "") < value:
                            match = False
                    elif key == "to_date":
                        if receipt.get("timestamp", "") > value:
                            match = False
                    elif key == "type":
                        if receipt.get("type") not in value:
                            match = False
                    elif receipt.get(key) != value:
                        match = False

                if match:
                    receipts.append(receipt)
            else:
                receipts.append(receipt)

    return receipts

# ============================================================================
# Main CLI Group
# ============================================================================

@click.group()
@click.version_option(version="0.1.0")
def cli():
    """VaultMesh Civilization Ledger CLI"""
    pass

# ============================================================================
# Treasury Commands
# ============================================================================

@cli.group()
def treasury():
    """Treasury Engine - Financial operations"""
    pass

@treasury.command("debit")
@click.option("--from", "from_account", required=True, help="Source account")
@click.option("--amount", required=True, type=float, help="Amount")
@click.option("--currency", default="EUR", help="Currency code")
@click.option("--memo", required=True, help="Transaction memo")
@click.option("--tags", default="", help="Comma-separated tags")
def treasury_debit(from_account: str, amount: float, currency: str, memo: str, tags: str):
    """Record a debit entry."""
    entry_id = f"entry-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}"

    receipt = emit_receipt(
        scroll="treasury",
        receipt_type="treasury_debit",
        body={
            "entry_id": entry_id,
            "account": from_account,
            "amount": amount,
            "currency": currency,
            "memo": memo,
        },
        tags=["treasury", "debit"] + (tags.split(",") if tags else [])
    )

    click.echo(f"✓ Debit recorded: {entry_id}")
    click.echo(f"  Amount: {amount} {currency}")
    click.echo(f"  Hash: {receipt['root_hash'][:20]}...")

@treasury.command("credit")
@click.option("--to", "to_account", required=True, help="Destination account")
@click.option("--amount", required=True, type=float, help="Amount")
@click.option("--currency", default="EUR", help="Currency code")
@click.option("--memo", required=True, help="Transaction memo")
@click.option("--tags", default="", help="Comma-separated tags")
def treasury_credit(to_account: str, amount: float, currency: str, memo: str, tags: str):
    """Record a credit entry."""
    entry_id = f"entry-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}"

    receipt = emit_receipt(
        scroll="treasury",
        receipt_type="treasury_credit",
        body={
            "entry_id": entry_id,
            "account": to_account,
            "amount": amount,
            "currency": currency,
            "memo": memo,
        },
        tags=["treasury", "credit"] + (tags.split(",") if tags else [])
    )

    click.echo(f"✓ Credit recorded: {entry_id}")
    click.echo(f"  Amount: {amount} {currency}")
    click.echo(f"  Hash: {receipt['root_hash'][:20]}...")

@treasury.command("query")
@click.option("--account", help="Filter by account")
@click.option("--from", "from_date", help="From date (ISO format)")
@click.option("--to", "to_date", help="To date (ISO format)")
@click.option("--type", "entry_type", help="Entry type (credit/debit)")
@click.option("--format", "output_format", default="table", type=click.Choice(["table", "json", "csv"]))
def treasury_query(account: str, from_date: str, to_date: str, entry_type: str, output_format: str):
    """Query treasury entries."""
    filters = {}
    if account:
        filters["account"] = account
    if from_date:
        filters["from_date"] = from_date
    if to_date:
        filters["to_date"] = to_date
    if entry_type:
        filters["type"] = [f"treasury_{entry_type}"]

    receipts = load_receipts("treasury", filters)

    if output_format == "json":
        click.echo(json.dumps(receipts, indent=2))
    elif output_format == "csv":
        if receipts:
            click.echo(",".join(receipts[0].keys()))
            for r in receipts:
                click.echo(",".join(str(v) for v in r.values()))
    else:
        click.echo(f"Found {len(receipts)} entries:")
        for r in receipts:
            click.echo(f"  {r.get('timestamp', 'N/A')[:19]} | {r.get('type', 'N/A'):20} | {r.get('amount', 'N/A'):>10} {r.get('currency', '')}")

# ============================================================================
# Mesh Commands
# ============================================================================

@cli.group()
def mesh():
    """Mesh Engine - Federation topology"""
    pass

@mesh.command("node")
@click.argument("action", type=click.Choice(["list", "show", "join", "leave"]))
@click.option("--id", "node_id", help="Node identifier")
@click.option("--config", type=click.Path(exists=True), help="Node config file")
def mesh_node(action: str, node_id: str, config: str):
    """Manage mesh nodes."""
    if action == "list":
        receipts = load_receipts("mesh", {"type": ["mesh_node_join"]})
        click.echo("Active nodes:")
        for r in receipts:
            click.echo(f"  • {r.get('node_id', 'unknown')} ({r.get('node_type', 'unknown')})")

    elif action == "show" and node_id:
        receipts = load_receipts("mesh", {"node_id": f"did:vm:node:{node_id}"})
        if receipts:
            click.echo(json.dumps(receipts[-1], indent=2))
        else:
            click.echo(f"Node not found: {node_id}")

    elif action == "join" and config:
        with open(config) as f:
            node_config = json.load(f)

        receipt = emit_receipt(
            scroll="mesh",
            receipt_type="mesh_node_join",
            body={
                "node_id": node_config.get("node_id"),
                "display_name": node_config.get("display_name"),
                "node_type": node_config.get("node_type", "infrastructure"),
                "endpoints_hash": "blake3:...",  # Would compute from endpoints
            },
            tags=["mesh", "node", "join"]
        )

        click.echo(f"✓ Node joined: {node_config.get('node_id')}")

    elif action == "leave" and node_id:
        receipt = emit_receipt(
            scroll="mesh",
            receipt_type="mesh_node_leave",
            body={
                "node_id": f"did:vm:node:{node_id}",
                "reason": "manual_leave",
            },
            tags=["mesh", "node", "leave"]
        )

        click.echo(f"✓ Node left: {node_id}")

@mesh.command("topology")
@click.option("--output", type=click.Path(), help="Output file")
def mesh_topology(output: str):
    """Show current mesh topology."""
    node_receipts = load_receipts("mesh", {"type": ["mesh_node_join", "mesh_node_leave"]})
    route_receipts = load_receipts("mesh", {"type": ["mesh_route_change"]})

    # Build current state (simplified)
    nodes = {}
    for r in node_receipts:
        node_id = r.get("node_id")
        if r["type"] == "mesh_node_join":
            nodes[node_id] = r
        elif r["type"] == "mesh_node_leave" and node_id in nodes:
            del nodes[node_id]

    topology = {
        "timestamp": datetime.utcnow().isoformat() + "Z",
        "node_count": len(nodes),
        "nodes": list(nodes.keys()),
    }

    if output:
        with open(output, "w") as f:
            json.dump(topology, f, indent=2)
        click.echo(f"✓ Topology saved to {output}")
    else:
        click.echo(json.dumps(topology, indent=2))

# ============================================================================
# Identity Commands
# ============================================================================

@cli.group()
def identity():
    """Identity Engine - DIDs and credentials"""
    pass

@identity.command("did")
@click.argument("action", type=click.Choice(["create", "show", "list", "rotate-key"]))
@click.option("--type", "did_type", type=click.Choice(["node", "human", "agent", "service"]))
@click.option("--id", "identifier", help="DID identifier")
@click.option("--controller", help="Controller DID")
def identity_did(action: str, did_type: str, identifier: str, controller: str):
    """Manage decentralized identifiers."""
    if action == "create" and did_type and identifier:
        did = f"did:vm:{did_type}:{identifier}"

        receipt = emit_receipt(
            scroll="identity",
            receipt_type="identity_did_create",
            body={
                "did": did,
                "did_type": did_type,
                "controller": controller,
                "initial_keys": [f"{did}#key-1"],
                "did_document_hash": "blake3:...",
            },
            tags=["identity", "did", "create", did_type]
        )

        click.echo(f"✓ DID created: {did}")

    elif action == "show" and identifier:
        did = f"did:vm:node:{identifier}"  # Simplified
        receipts = load_receipts("identity", {"did": did})
        if receipts:
            click.echo(json.dumps(receipts[-1], indent=2))
        else:
            click.echo(f"DID not found: {did}")

    elif action == "list":
        receipts = load_receipts("identity", {"type": ["identity_did_create"]})
        click.echo("Registered DIDs:")
        for r in receipts:
            click.echo(f"  • {r.get('did', 'unknown')} ({r.get('did_type', 'unknown')})")

@identity.command("capability")
@click.argument("action", type=click.Choice(["grant", "check", "list", "revoke"]))
@click.option("--holder", help="Capability holder DID")
@click.option("--capability", type=click.Choice(["anchor", "storage", "compute", "oracle", "admin"]))
@click.option("--expires", help="Expiration date (ISO format)")
def identity_capability(action: str, holder: str, capability: str, expires: str):
    """Manage capability tokens."""
    if action == "grant" and holder and capability:
        cap_id = f"cap:vm:{datetime.utcnow().strftime('%Y-%m-%d')}:{capability}:{holder.split(':')[-1]}"

        receipt = emit_receipt(
            scroll="identity",
            receipt_type="identity_capability_grant",
            body={
                "capability_id": cap_id,
                "holder": holder,
                "capability": capability,
                "granted_by": "did:vm:node:portal-01",  # Would come from context
                "expires_at": expires or "2026-01-01T00:00:00Z",
            },
            tags=["identity", "capability", "grant", capability]
        )

        click.echo(f"✓ Capability granted: {cap_id}")

    elif action == "check" and holder and capability:
        receipts = load_receipts("identity", {"holder": holder, "capability": capability})
        grants = [r for r in receipts if r["type"] == "identity_capability_grant"]
        revokes = [r for r in receipts if r["type"] == "identity_capability_revoke"]

        # Check if any valid grant exists
        valid = False
        for g in grants:
            grant_id = g.get("capability_id")
            if not any(r.get("capability_id") == grant_id for r in revokes):
                expires = g.get("expires_at", "")
                if expires > datetime.utcnow().isoformat():
                    valid = True
                    break

        if valid:
            click.echo(f"✓ {holder} HAS capability: {capability}")
        else:
            click.echo(f"✗ {holder} does NOT have capability: {capability}")

    elif action == "list" and holder:
        receipts = load_receipts("identity", {"holder": holder, "type": ["identity_capability_grant"]})
        click.echo(f"Capabilities for {holder}:")
        for r in receipts:
            click.echo(f"  • {r.get('capability', 'unknown')} (expires: {r.get('expires_at', 'never')[:10]})")

# ============================================================================
# Psi-Field Commands
# ============================================================================

@cli.group()
def psi():
    """Ψ-Field Engine - Alchemical consciousness"""
    pass

@psi.command("phase")
@click.argument("action", type=click.Choice(["current", "history", "transition"]))
@click.option("--to", "to_phase", type=click.Choice(["nigredo", "albedo", "citrinitas", "rubedo"]))
@click.option("--trigger", help="Transition trigger description")
def psi_phase(action: str, to_phase: str, trigger: str):
    """Manage alchemical phases."""
    if action == "current":
        receipts = load_receipts("psi", {"type": ["psi_phase_transition"]})
        if receipts:
            last = receipts[-1]
            phase = last.get("to_phase", "unknown")
            symbols = {"nigredo": "🜁", "albedo": "🜄", "citrinitas": "🜆", "rubedo": "🜂"}
            click.echo(f"Current Phase: {phase.upper()} {symbols.get(phase, '')}")
            click.echo(f"Since: {last.get('timestamp', 'unknown')[:19]}")
        else:
            click.echo("Current Phase: NIGREDO 🜁 (initial)")

    elif action == "history":
        receipts = load_receipts("psi", {"type": ["psi_phase_transition"]})
        click.echo("Phase History:")
        for r in receipts:
            click.echo(f"  {r.get('timestamp', '')[:19]} | {r.get('from_phase', 'init'):10}{r.get('to_phase', ''):10}")

    elif action == "transition" and to_phase and trigger:
        # Get current phase
        receipts = load_receipts("psi", {"type": ["psi_phase_transition"]})
        from_phase = receipts[-1].get("to_phase", "nigredo") if receipts else "nigredo"

        receipt = emit_receipt(
            scroll="psi",
            receipt_type="psi_phase_transition",
            body={
                "transition_id": f"psi-trans-{datetime.utcnow().strftime('%Y-%m-%d-%H%M%S')}",
                "from_phase": from_phase,
                "to_phase": to_phase,
                "trigger_type": "manual",
                "trigger_description": trigger,
            },
            tags=["psi", "phase", from_phase, to_phase]
        )

        click.echo(f"✓ Phase transition: {from_phase}{to_phase}")

@psi.command("transmute")
@click.option("--input", "input_ref", required=True, help="Input reference (e.g., INC-2025-12-001)")
@click.option("--input-type", required=True, type=click.Choice(["incident", "vulnerability", "drill"]))
@click.option("--title", required=True, help="Transmutation title")
def psi_transmute(input_ref: str, input_type: str, title: str):
    """Initiate a transmutation process."""
    trans_id = f"psi-transmute-{datetime.utcnow().strftime('%Y-%m-%d-%H%M%S')}"

    receipt = emit_receipt(
        scroll="psi",
        receipt_type="psi_transmutation",
        body={
            "transmutation_id": trans_id,
            "title": title,
            "input_type": input_type,
            "input_reference": input_ref,
            "status": "initiated",
            "alchemical_phase_target": "citrinitas",
        },
        tags=["psi", "transmutation", input_type]
    )

    click.echo(f"✓ Transmutation initiated: {trans_id}")
    click.echo(f"  Input: {input_ref} ({input_type})")
    click.echo(f"  Target phase: CITRINITAS 🜆")

@psi.command("opus")
def psi_opus():
    """Display Magnum Opus status."""
    # Get current phase
    phase_receipts = load_receipts("psi", {"type": ["psi_phase_transition"]})
    current_phase = phase_receipts[-1].get("to_phase", "nigredo") if phase_receipts else "nigredo"

    # Get transmutation counts
    trans_receipts = load_receipts("psi", {"type": ["psi_transmutation"]})

    # Get resonance count
    res_receipts = load_receipts("psi", {"type": ["psi_resonance"]})

    symbols = {"nigredo": "🜁", "albedo": "🜄", "citrinitas": "🜆", "rubedo": "🜂"}

    click.echo("=" * 50)
    click.echo("           MAGNUM OPUS STATUS")
    click.echo("=" * 50)
    click.echo()
    click.echo(f"  Current Phase: {current_phase.upper()} {symbols.get(current_phase, '')}")
    click.echo()
    click.echo("  Phase Progress:")
    phases = ["nigredo", "albedo", "citrinitas", "rubedo"]
    for i, p in enumerate(phases):
        marker = "●" if p == current_phase else ("○" if phases.index(p) > phases.index(current_phase) else "●")
        click.echo(f"    {marker} {p.upper():12} {symbols.get(p, '')}")
    click.echo()
    click.echo(f"  Transmutations: {len(trans_receipts)}")
    click.echo(f"  Resonances: {len(res_receipts)}")
    click.echo()
    click.echo("=" * 50)

# ============================================================================
# Guardian Commands (bridge to existing)
# ============================================================================

@cli.group()
def guardian():
    """Guardian Engine - Anchor and sentinel"""
    pass

@guardian.command("anchor-status")
def guardian_anchor_status():
    """Show current anchor status."""
    receipts = load_receipts("guardian", {"type": ["anchor_success", "anchor_failure"]})

    if receipts:
        last = receipts[-1]
        click.echo(f"Last Anchor: {last.get('timestamp', 'unknown')[:19]}")
        click.echo(f"Status: {last.get('type', 'unknown')}")
        click.echo(f"Root: {last.get('root_hash', 'unknown')[:30]}...")
    else:
        click.echo("No anchor events recorded")

@guardian.command("anchor-now")
@click.option("--scroll", multiple=True, help="Scrolls to anchor (default: all)")
def guardian_anchor_now(scroll: tuple):
    """Trigger immediate anchor cycle."""
    scrolls = list(scroll) if scroll else ["drills", "compliance", "treasury", "mesh", "identity", "psi"]

    click.echo(f"Anchoring scrolls: {', '.join(scrolls)}")

    # Would call actual Guardian anchor cycle here
    receipt = emit_receipt(
        scroll="guardian",
        receipt_type="anchor_success",
        body={
            "anchor_id": f"anchor-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}",
            "scrolls_anchored": scrolls,
            "backend": "local",  # Would be ots/ethereum/bitcoin in production
        },
        tags=["guardian", "anchor", "manual"]
    )

    click.echo(f"✓ Anchor cycle complete")
    click.echo(f"  ID: {receipt.get('anchor_id')}")

# ============================================================================
# Entry Point
# ============================================================================

if __name__ == "__main__":
    cli()

5. Directory Structure

vaultmesh/
├── Cargo.toml                      # Rust workspace
├── pyproject.toml                  # Python CLI
│
├── vaultmesh-core/                 # Shared Rust types
│   └── src/
│       ├── lib.rs
│       ├── receipt.rs
│       ├── did.rs
│       └── hash.rs
│
├── vaultmesh-treasury/             # Treasury engine
│   └── src/lib.rs
│
├── vaultmesh-mesh/                 # Mesh engine
│   └── src/lib.rs
│
├── vaultmesh-identity/             # Identity engine
│   └── src/lib.rs
│
├── vaultmesh-offsec/               # OffSec engine
│   └── src/lib.rs
│
├── vaultmesh-observability/        # Observability engine
│   └── src/lib.rs
│
├── vaultmesh-automation/           # Automation engine
│   └── src/lib.rs
│
├── vaultmesh-psi/                  # Ψ-Field engine
│   └── src/lib.rs
│
├── vaultmesh-guardian/             # Guardian (existing)
│   └── src/lib.rs
│
├── cli/                            # Python CLI
│   ├── __init__.py
│   └── vm_cli.py
│
├── receipts/                       # Receipt storage
│   ├── drills/
│   ├── compliance/
│   ├── guardian/
│   ├── treasury/
│   ├── mesh/
│   ├── offsec/
│   ├── identity/
│   ├── observability/
│   ├── automation/
│   └── psi/
│
├── cases/                          # Case artifacts
│   ├── drills/
│   ├── treasury/
│   ├── offsec/
│   ├── identity/
│   └── psi/
│
└── ROOT.*.txt                      # Merkle roots

6. Summary

This document provides:

  1. Rust Core Types (vaultmesh-core)

    • Receipt<T> — generic receipt wrapper
    • Scroll enum — all 10 scrolls with paths
    • Did — decentralized identifier type
    • VmHash — blake3 hash with prefix
    • merkle_root() — Merkle tree computation
  2. Treasury Engine (vaultmesh-treasury)

    • Account, Entry, SettlementContract, SettlementState
    • Full settlement workflow with signatures
    • Receipt generation for credits, debits, settlements
  3. Identity Engine (vaultmesh-identity)

    • DidDocument, VerifiableCredential, CapabilityToken
    • DID creation, credential issuance, capability checks
    • Authentication events
  4. Python CLI (vm-cli)

    • Unified CLI covering Treasury, Mesh, Identity, Ψ-Field, Guardian
    • emit_receipt() and load_receipts() utilities
    • Complete command structure matching engine specs
  5. Directory Structure

    • Rust workspace layout
    • Receipt and case storage paths
    • Merkle root file locations

All engines now have both specifications and implementation scaffolds following the Eternal Pattern.