Skip to main content

chio_market/
lib.rs

1//! Liability-market provider, quote, and claims contracts for the Chio
2//! protocol.
3//!
4//! This crate models liability coverage for metered tool access: quoting,
5//! binding policies, and settling claims against signed receipt evidence. It
6//! defines the insurance flow (`quote_and_bind`, bound policies, coverage
7//! limits, premium sources) and the claim-settlement path (claim evidence,
8//! decisions, denial reasons, settlement requests), with receipt fingerprints
9//! linking claims back to the receipts they cover. It builds on the appraisal,
10//! credit, and underwriting surfaces.
11//!
12//! # Modules
13//!
14//! - [`insurance_flow`] -- quote/bind and claim-settlement flow.
15
16#![forbid(unsafe_code)]
17
18pub use chio_appraisal as appraisal;
19pub use chio_core_types::{capability, crypto, receipt};
20pub use chio_credit as credit;
21pub use chio_underwriting as underwriting;
22
23pub mod insurance_flow;
24pub mod parametric;
25pub use insurance_flow::{
26    quote_and_bind, BoundPolicy, ClaimDecision, ClaimDenialReason, ClaimEvidence, ClaimSettlement,
27    ClaimSettlementRequest, ClaimSettlementSink, CoverageLimit, InsuranceFlowError, PolicyStatus,
28    PremiumSource, ReceiptEvidenceSource, ReceiptFingerprint, ResolvedReceiptEvidence,
29    StaticPremiumSource,
30};
31pub use parametric::*;
32
33use serde::Serialize;
34
35use crate::capability::scope::MonetaryAmount;
36use crate::receipt::lineage::SignedExportEnvelope;
37
38pub const LIABILITY_PROVIDER_ARTIFACT_SCHEMA: &str = "chio.market.provider.v1";
39pub const LIABILITY_PROVIDER_LIST_REPORT_SCHEMA: &str = "chio.market.provider-list.v1";
40pub const LIABILITY_PROVIDER_RESOLUTION_REPORT_SCHEMA: &str = "chio.market.provider-resolution.v1";
41pub const LIABILITY_QUOTE_REQUEST_ARTIFACT_SCHEMA: &str = "chio.market.quote-request.v1";
42pub const LIABILITY_QUOTE_RESPONSE_ARTIFACT_SCHEMA: &str = "chio.market.quote-response.v1";
43pub const LIABILITY_PRICING_AUTHORITY_ARTIFACT_SCHEMA: &str = "chio.market.pricing-authority.v1";
44pub const LIABILITY_PLACEMENT_ARTIFACT_SCHEMA: &str = "chio.market.placement.v1";
45pub const LIABILITY_BOUND_COVERAGE_ARTIFACT_SCHEMA: &str = "chio.market.bound-coverage.v1";
46pub const LIABILITY_AUTO_BIND_DECISION_ARTIFACT_SCHEMA: &str = "chio.market.auto-bind.v1";
47pub const LIABILITY_MARKET_WORKFLOW_REPORT_SCHEMA: &str = "chio.market.workflow-list.v1";
48pub const LIABILITY_CLAIM_PACKAGE_ARTIFACT_SCHEMA: &str = "chio.market.claim-package.v1";
49pub const LIABILITY_CLAIM_RESPONSE_ARTIFACT_SCHEMA: &str = "chio.market.claim-response.v1";
50pub const LIABILITY_CLAIM_DISPUTE_ARTIFACT_SCHEMA: &str = "chio.market.claim-dispute.v1";
51pub const LIABILITY_CLAIM_ADJUDICATION_ARTIFACT_SCHEMA: &str = "chio.market.claim-adjudication.v1";
52pub const LIABILITY_CLAIM_PAYOUT_INSTRUCTION_ARTIFACT_SCHEMA: &str =
53    "chio.market.claim-payout-instruction.v1";
54pub const LIABILITY_CLAIM_PAYOUT_RECEIPT_ARTIFACT_SCHEMA: &str =
55    "chio.market.claim-payout-receipt.v1";
56pub const LIABILITY_CLAIM_SETTLEMENT_INSTRUCTION_ARTIFACT_SCHEMA: &str =
57    "chio.market.claim-settlement-instruction.v1";
58pub const LIABILITY_CLAIM_SETTLEMENT_RECEIPT_ARTIFACT_SCHEMA: &str =
59    "chio.market.claim-settlement-receipt.v1";
60pub const LIABILITY_CLAIM_WORKFLOW_REPORT_SCHEMA: &str = "chio.market.claim-workflow-list.v1";
61pub const MAX_LIABILITY_PROVIDER_LIST_LIMIT: usize = 100;
62pub const MAX_LIABILITY_MARKET_WORKFLOW_LIMIT: usize = 100;
63pub const MAX_LIABILITY_CLAIM_WORKFLOW_LIMIT: usize = 100;
64
65fn bounded_market_query_limit(limit: Option<usize>, max: usize) -> usize {
66    limit.unwrap_or(50).clamp(1, max)
67}
68
69mod claim;
70mod placement;
71mod provider;
72mod quote;
73mod settlement;
74mod workflow;
75
76pub use claim::*;
77pub use placement::*;
78pub use provider::*;
79pub use quote::*;
80pub use settlement::*;
81pub use workflow::*;
82
83fn liability_claim_adjudication_payable_amount(
84    adjudication: &LiabilityClaimAdjudicationArtifact,
85) -> Result<&MonetaryAmount, String> {
86    match adjudication.outcome {
87        LiabilityClaimAdjudicationOutcome::ClaimUpheld
88        | LiabilityClaimAdjudicationOutcome::PartialSettlement => {
89            adjudication.awarded_amount.as_ref().ok_or_else(|| {
90                "claim payout instructions require adjudications with awarded_amount".to_string()
91            })
92        }
93        LiabilityClaimAdjudicationOutcome::ProviderUpheld => {
94            Err("claim payout instructions require a payable adjudication outcome".to_string())
95        }
96    }
97}
98
99fn validate_currency_code(value: &str, field_name: &str) -> Result<(), String> {
100    let currency = value.trim().to_ascii_uppercase();
101    if currency.len() != 3
102        || !currency
103            .chars()
104            .all(|character| character.is_ascii_uppercase())
105    {
106        return Err(format!(
107            "{field_name} must be a three-letter uppercase ISO-style code"
108        ));
109    }
110    Ok(())
111}
112
113fn verify_signed_artifact<T>(
114    artifact: &SignedExportEnvelope<T>,
115    field_name: &str,
116) -> Result<(), String>
117where
118    T: Serialize + Clone,
119{
120    if artifact
121        .verify_signature()
122        .map_err(|error| format!("{field_name} signature verification failed: {error}"))?
123    {
124        Ok(())
125    } else {
126        Err(format!("{field_name} signature verification failed"))
127    }
128}
129
130fn validate_positive_money(amount: &MonetaryAmount, field_name: &str) -> Result<(), String> {
131    if amount.units == 0 {
132        return Err(format!("{field_name} must be greater than zero"));
133    }
134    validate_currency_code(&amount.currency, &format!("{field_name} currency"))?;
135    Ok(())
136}
137
138#[cfg(test)]
139mod tests;