chio-store-sqlite 0.1.2

SQLite-backed persistence, query, and report implementations for Chio
Documentation
use std::time::{SystemTime, UNIX_EPOCH};

use chio_core::crypto::Keypair;
use chio_core::receipt::{
    body::ChioReceipt, body::ChioReceiptBody, decision::Decision, decision::ToolCallAction,
};

pub(super) fn unique_db_path(prefix: &str) -> std::path::PathBuf {
    let nonce = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("time before epoch")
        .as_nanos();
    std::env::temp_dir().join(format!("{prefix}-{nonce}.sqlite3"))
}

fn valid_tool_action(parameters: serde_json::Value) -> ToolCallAction {
    ToolCallAction::from_parameters(parameters).unwrap()
}

#[derive(Clone, Copy)]
pub(super) struct ReceiptCost<'a> {
    charged: Option<u64>,
    currency: &'a str,
}

impl<'a> ReceiptCost<'a> {
    pub(super) const fn new(charged: Option<u64>, currency: &'a str) -> Self {
        Self { charged, currency }
    }
}

pub(super) fn make_receipt_with_metadata(
    id: &str,
    capability_id: &str,
    tool_server: &str,
    tool_name: &str,
    decision: Decision,
    timestamp: u64,
    metadata: Option<serde_json::Value>,
) -> ChioReceipt {
    let keypair = Keypair::generate();
    ChioReceipt::sign(
        ChioReceiptBody {
            id: id.to_string(),
            timestamp,
            capability_id: capability_id.to_string(),
            tool_server: tool_server.to_string(),
            tool_name: tool_name.to_string(),
            action: valid_tool_action(serde_json::json!({})),
            decision: Some(decision),
            receipt_kind: chio_core::receipt::kinds::ReceiptKind::MediatedDecision,
            boundary_class: chio_core::receipt::kinds::BoundaryClass::Prevent,
            observation_outcome: None,
            tool_origin: chio_core::receipt::kinds::ToolOrigin::CallerExecuted,
            redaction_mode: chio_core::receipt::kinds::RedactionMode::None,
            actor_chain: Vec::new(),
            content_hash: "content-hash".to_string(),
            policy_hash: "policy-hash".to_string(),
            evidence: Vec::new(),
            metadata,
            trust_level: chio_core::receipt::kinds::TrustLevel::default(),
            tenant_id: None,
            kernel_key: keypair.public_key(),
            bbs_projection_version: None,
        },
        &keypair,
    )
    .unwrap()
}

/// Build a receipt with given fields. cost populates financial metadata.
pub(super) fn make_receipt(
    id: &str,
    capability_id: &str,
    tool_server: &str,
    tool_name: &str,
    decision: Decision,
    timestamp: u64,
    cost: Option<u64>,
) -> ChioReceipt {
    make_receipt_with_currency(
        id,
        capability_id,
        tool_server,
        tool_name,
        decision,
        timestamp,
        ReceiptCost::new(cost, "USD"),
    )
}

pub(super) fn make_receipt_with_currency(
    id: &str,
    capability_id: &str,
    tool_server: &str,
    tool_name: &str,
    decision: Decision,
    timestamp: u64,
    cost: ReceiptCost<'_>,
) -> ChioReceipt {
    let metadata = cost.charged.map(|charged| {
        serde_json::json!({
            "financial": {
                "grant_index": 0u32,
                "cost_charged": charged,
                "currency": cost.currency,
                "budget_remaining": 1000u64,
                "budget_total": 2000u64,
                "delegation_depth": 0u32,
                "root_budget_holder": "root-agent",
                "settlement_status": "pending"
            }
        })
    });
    make_receipt_with_metadata(
        id,
        capability_id,
        tool_server,
        tool_name,
        decision,
        timestamp,
        metadata,
    )
}