1#![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;