coreason-urn-authority 0.45.1

Epistemic Ledger & OCI Trust Anchor for CoReason URNs.
Documentation
// Copyright (c) 2026 CoReason, Inc.
// All rights reserved.

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ThermodynamicCostRecord {
    pub tenant_cid: String,
    pub workflow_id: String,
    #[serde(default)]
    pub agent_cid: String,
    #[serde(default)]
    pub input_tokens: i64,
    #[serde(default)]
    pub output_tokens: i64,
    #[serde(default)]
    pub total_tokens: i64,
    #[serde(default)]
    pub cost_usd: f64,
    #[serde(default)]
    pub gpu_seconds: f64,
    pub timestamp: f64,
}

pub fn get_postgres_schema() -> &'static str {
    include_str!("../migrations/001_thermodynamic_costs.sql")
}

pub fn verify_cost_and_update(
    budget_limit_usd: f64,
    records: Vec<ThermodynamicCostRecord>,
    new_record: ThermodynamicCostRecord,
) -> Result<Vec<ThermodynamicCostRecord>, String> {
    if new_record.cost_usd < 0.0 {
        return Err(format!(
            "Cost must be non-negative, got {}",
            new_record.cost_usd
        ));
    }

    let mut tenant_totals = std::collections::HashMap::new();
    for r in &records {
        let entry = tenant_totals.entry(&r.tenant_cid).or_insert(0.0);
        *entry += r.cost_usd;
    }

    let current = tenant_totals
        .get(&new_record.tenant_cid)
        .cloned()
        .unwrap_or(0.0);
    if current + new_record.cost_usd > budget_limit_usd {
        return Err(format!(
            "Tenant '{}' budget exceeded: ${:.4} > ${:.2} limit",
            new_record.tenant_cid,
            current + new_record.cost_usd,
            budget_limit_usd
        ));
    }

    let mut updated_records = records;
    updated_records.push(new_record);
    Ok(updated_records)
}