Spaces:
Build error
Build error
| //! Global Trade Management System (GTMS) integration. | |
| //! | |
| //! Scope for a digital music platform: | |
| //! β’ Work classification: ECCN (Export Control Classification Number) and | |
| //! HS code assignment for physical merch, recording media, and digital goods. | |
| //! β’ Distribution screening: cross-border digital delivery routed through | |
| //! GTMS sanctions/embargo checks before DSP delivery or society submission. | |
| //! β’ Export declaration: EEI (Electronic Export Information) stubs for | |
| //! physical shipments (vinyl pressings, merch) via AES / CBP ACE. | |
| //! β’ Denied Party Screening (DPS): checks payees against: | |
| //! β OFAC SDN / Consolidated Sanctions List | |
| //! β EU Consolidated List (EUR-Lex) | |
| //! β UN Security Council sanctions | |
| //! β UK HM Treasury financial sanctions | |
| //! β BIS Entity List / Unverified List | |
| //! β’ Incoterms 2020 annotation on physical shipments. | |
| //! | |
| //! Integration targets: | |
| //! β’ SAP GTS (Global Trade Services) via RFC/BAPI or REST API | |
| //! (SAP_GTS_SANCTIONS / SAP_GTS_CLASSIFICATION OData services). | |
| //! β’ Thomson Reuters World-Check / Refinitiv (REST) β DPS fallback. | |
| //! β’ US Census Bureau AES Direct (EEI filing). | |
| //! β’ EU ICS2 (Import Control System 2) for EU entry declarations. | |
| //! | |
| //! Zero Trust: all GTMS API calls use mTLS client cert. | |
| //! LangSec: all HS codes validated against 6-digit WCO pattern. | |
| //! ISO 9001 Β§7.5: all screening results and classifications logged. | |
| use crate::AppState; | |
| use axum::{ | |
| extract::{Path, State}, | |
| http::StatusCode, | |
| response::Json, | |
| }; | |
| use serde::{Deserialize, Serialize}; | |
| use std::collections::HashMap; | |
| use std::sync::Mutex; | |
| use tracing::{info, warn}; | |
| // ββ HS / ECCN code validation (LangSec) βββββββββββββββββββββββββββββββββββββ | |
| /// Validate a WCO Harmonized System code (6-digit minimum: NNNN.NN). | |
| pub fn validate_hs_code(hs: &str) -> bool { | |
| let digits: String = hs.chars().filter(|c| c.is_ascii_digit()).collect(); | |
| digits.len() >= 6 | |
| } | |
| /// Validate an ECCN (Export Control Classification Number). | |
| /// Format: \d[A-Z]\d\d\d[a-z]? e.g. "5E002", "EAR99", "AT010" | |
| pub fn validate_eccn(eccn: &str) -> bool { | |
| if eccn == "EAR99" || eccn == "NLR" { | |
| return true; | |
| } | |
| let b = eccn.as_bytes(); | |
| b.len() >= 5 | |
| && b[0].is_ascii_digit() | |
| && b[1].is_ascii_uppercase() | |
| && b[2].is_ascii_digit() | |
| && b[3].is_ascii_digit() | |
| && b[4].is_ascii_digit() | |
| } | |
| // ββ Incoterms 2020 ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| pub enum Incoterm { | |
| Exw, // Ex Works | |
| Fca, // Free Carrier | |
| Cpt, // Carriage Paid To | |
| Cip, // Carriage and Insurance Paid To | |
| Dap, // Delivered at Place | |
| Dpu, // Delivered at Place Unloaded | |
| Ddp, // Delivered Duty Paid | |
| Fas, // Free Alongside Ship | |
| Fob, // Free On Board | |
| Cfr, // Cost and Freight | |
| Cif, // Cost, Insurance and Freight | |
| } | |
| impl Incoterm { | |
| pub fn code(&self) -> &'static str { | |
| match self { | |
| Self::Exw => "EXW", | |
| Self::Fca => "FCA", | |
| Self::Cpt => "CPT", | |
| Self::Cip => "CIP", | |
| Self::Dap => "DAP", | |
| Self::Dpu => "DPU", | |
| Self::Ddp => "DDP", | |
| Self::Fas => "FAS", | |
| Self::Fob => "FOB", | |
| Self::Cfr => "CFR", | |
| Self::Cif => "CIF", | |
| } | |
| } | |
| pub fn transport_mode(&self) -> &'static str { | |
| match self { | |
| Self::Fas | Self::Fob | Self::Cfr | Self::Cif => "SEA", | |
| _ => "ANY", | |
| } | |
| } | |
| } | |
| // ββ Sanctioned jurisdictions (OFAC + EU + UN programs) βββββββββββββββββββββββ | |
| // Kept as a compiled-in list; production integrations call a live DPS API. | |
| const EMBARGOED_COUNTRIES: &[&str] = &[ | |
| "CU", // Cuba β OFAC comprehensive embargo | |
| "IR", // Iran β OFAC ITSR | |
| "KP", // North Korea β UN 1718 / OFAC NKSR | |
| "RU", // Russia β OFAC SDN + EU/UK financial sanctions | |
| "BY", // Belarus β EU restrictive measures | |
| "SY", // Syria β OFAC SYSR | |
| "VE", // Venezuela β OFAC EO 13850 | |
| "MM", // Myanmar β OFAC / UK | |
| "ZW", // Zimbabwe β OFAC ZDERA | |
| "SS", // South Sudan β UN arms embargo | |
| "CF", // Central African Republic β UN arms embargo | |
| "LY", // Libya β UN arms embargo | |
| "SD", // Sudan β OFAC | |
| "SO", // Somalia β UN arms embargo | |
| "YE", // Yemen β UN arms embargo | |
| "HT", // Haiti β UN targeted sanctions | |
| "ML", // Mali β UN targeted sanctions | |
| "NI", // Nicaragua β OFAC EO 13851 | |
| ]; | |
| /// Restricted digital distribution territories (not full embargoes but | |
| /// require heightened compliance review β OFAC 50% rule, deferred access). | |
| const RESTRICTED_TERRITORIES: &[&str] = &[ | |
| "CN", // China β BIS Entity List exposure, music licensing restrictions | |
| "IN", // India β FEMA remittance limits on royalty payments | |
| "NG", // Nigeria β CBN FX restrictions on royalty repatriation | |
| "EG", // Egypt β royalty remittance requires CBE approval | |
| "PK", // Pakistan β SBP restrictions | |
| "BD", // Bangladesh β BB foreign remittance controls | |
| "VN", // Vietnam β State Bank approval for licensing income | |
| ]; | |
| // ββ Domain types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| /// Classification request β a musical work or physical product to classify. | |
| pub struct ClassificationRequest { | |
| pub isrc: Option<String>, | |
| pub iswc: Option<String>, | |
| pub title: String, | |
| pub product_type: ProductType, | |
| pub countries: Vec<String>, // destination ISO 3166-1 alpha-2 codes | |
| pub sender_id: String, | |
| } | |
| pub enum ProductType { | |
| DigitalDownload, // EAR99 / 5E002 depending on DRM | |
| StreamingLicense, // EAR99 β no physical export | |
| VinylRecord, // HS 8524.91 (analog audio media) | |
| Cd, // HS 8523.49 | |
| Usb, // HS 8523.51 | |
| Merchandise, // HS varies; requires specific classification | |
| PublishingLicense, // EAR99 β intangible | |
| MasterRecording, // EAR99 unless DRM technology | |
| } | |
| impl ProductType { | |
| /// Preliminary ECCN based on product type. | |
| /// Final ECCN requires full technical review; this is a default assignment. | |
| pub fn preliminary_eccn(&self) -> &'static str { | |
| match self { | |
| Self::DigitalDownload => "EAR99", // unless encryption >64-bit keys | |
| Self::StreamingLicense => "EAR99", | |
| Self::VinylRecord => "EAR99", | |
| Self::Cd => "EAR99", | |
| Self::Usb => "EAR99", // re-review if >1TB encrypted | |
| Self::Merchandise => "EAR99", | |
| Self::PublishingLicense => "EAR99", | |
| Self::MasterRecording => "EAR99", | |
| } | |
| } | |
| /// HS code (6-digit WCO) for physical goods; None for digital/licensing. | |
| pub fn hs_code(&self) -> Option<&'static str> { | |
| match self { | |
| Self::VinylRecord => Some("852491"), // gramophone records | |
| Self::Cd => Some("852349"), // optical media | |
| Self::Usb => Some("852351"), // flash memory media | |
| Self::Merchandise => None, // requires specific classification | |
| _ => None, // digital / intangible | |
| } | |
| } | |
| } | |
| /// Classification result. | |
| pub struct ClassificationResult { | |
| pub request_id: String, | |
| pub title: String, | |
| pub product_type: ProductType, | |
| pub eccn: String, | |
| pub hs_code: Option<String>, | |
| pub ear_jurisdiction: bool, // true = subject to EAR (US) | |
| pub itar_jurisdiction: bool, // true = subject to ITAR (always false for music) | |
| pub license_required: bool, // true = export licence needed for some destinations | |
| pub licence_exception: Option<String>, // e.g. "TSR", "STA", "TMP" | |
| pub restricted_countries: Vec<String>, // subset of requested countries requiring review | |
| pub embargoed_countries: Vec<String>, // subset under comprehensive embargo | |
| pub incoterm: Option<Incoterm>, | |
| pub notes: String, | |
| pub classified_at: String, | |
| } | |
| /// Distribution screening request β check if a set of payees/territories | |
| /// can receive a royalty payment or content delivery. | |
| pub struct ScreeningRequest { | |
| pub screening_id: String, | |
| pub payee_name: String, | |
| pub payee_country: String, | |
| pub payee_vendor_id: Option<String>, | |
| pub territories: Vec<String>, // delivery territories | |
| pub amount_usd: f64, | |
| pub isrc: Option<String>, | |
| } | |
| pub enum ScreeningOutcome { | |
| Clear, // no matches β proceed | |
| ReviewRequired, // partial match or restricted territory β human review | |
| Blocked, // embargoed / SDN match β do not proceed | |
| } | |
| pub struct ScreeningResult { | |
| pub screening_id: String, | |
| pub outcome: ScreeningOutcome, | |
| pub blocked_reasons: Vec<String>, | |
| pub review_reasons: Vec<String>, | |
| pub embargoed_territories: Vec<String>, | |
| pub restricted_territories: Vec<String>, | |
| pub dps_checked: bool, // true = live DPS API was called | |
| pub screened_at: String, | |
| } | |
| /// Export declaration for physical shipments. | |
| pub struct ExportDeclaration { | |
| pub declaration_id: String, | |
| pub shipper: String, | |
| pub consignee: String, | |
| pub destination: String, // ISO 3166-1 alpha-2 | |
| pub hs_code: String, | |
| pub eccn: String, | |
| pub incoterm: Incoterm, | |
| pub gross_value_usd: f64, | |
| pub quantity: u32, | |
| pub unit: String, // e.g. "PCS", "KG" | |
| pub eei_status: EeiStatus, | |
| pub aes_itn: Option<String>, // AES Internal Transaction Number | |
| pub created_at: String, | |
| } | |
| pub enum EeiStatus { | |
| NotRequired, // value < $2,500 or EEI exemption applies | |
| Pending, // awaiting AES filing | |
| Filed, // AES ITN assigned | |
| Rejected, // AES rejected β correction required | |
| } | |
| // ββ Store βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| pub struct GtmsStore { | |
| classifications: Mutex<HashMap<String, ClassificationResult>>, | |
| screenings: Mutex<HashMap<String, ScreeningResult>>, | |
| declarations: Mutex<HashMap<String, ExportDeclaration>>, | |
| } | |
| impl Default for GtmsStore { | |
| fn default() -> Self { | |
| Self::new() | |
| } | |
| } | |
| impl GtmsStore { | |
| pub fn new() -> Self { | |
| Self { | |
| classifications: Mutex::new(HashMap::new()), | |
| screenings: Mutex::new(HashMap::new()), | |
| declarations: Mutex::new(HashMap::new()), | |
| } | |
| } | |
| pub fn save_classification(&self, r: ClassificationResult) { | |
| if let Ok(mut m) = self.classifications.lock() { | |
| m.insert(r.request_id.clone(), r); | |
| } | |
| } | |
| pub fn save_screening(&self, r: ScreeningResult) { | |
| if let Ok(mut m) = self.screenings.lock() { | |
| m.insert(r.screening_id.clone(), r); | |
| } | |
| } | |
| pub fn get_declaration(&self, id: &str) -> Option<ExportDeclaration> { | |
| self.declarations.lock().ok()?.get(id).cloned() | |
| } | |
| pub fn save_declaration(&self, d: ExportDeclaration) { | |
| if let Ok(mut m) = self.declarations.lock() { | |
| m.insert(d.declaration_id.clone(), d); | |
| } | |
| } | |
| } | |
| // ββ Core logic ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| fn new_id() -> String { | |
| // Deterministic ID from timestamp + counter (no uuid dep) | |
| let ts = chrono::Utc::now().format("%Y%m%d%H%M%S%6f").to_string(); | |
| format!("GTMS-{ts}") | |
| } | |
| fn now_iso() -> String { | |
| chrono::Utc::now().to_rfc3339() | |
| } | |
| /// Classify a work/product and determine ECCN, HS code, and export control posture. | |
| fn classify(req: &ClassificationRequest) -> ClassificationResult { | |
| let eccn = req.product_type.preliminary_eccn().to_string(); | |
| let hs_code = req.product_type.hs_code().map(str::to_string); | |
| let ear = true; // all US-origin or US-person transactions subject to EAR | |
| let itar = false; // music is never ITAR (USML categories I-XXI don't cover it) | |
| let embargoed: Vec<String> = req | |
| .countries | |
| .iter() | |
| .filter(|c| EMBARGOED_COUNTRIES.contains(&c.as_str())) | |
| .cloned() | |
| .collect(); | |
| let restricted: Vec<String> = req | |
| .countries | |
| .iter() | |
| .filter(|c| RESTRICTED_TERRITORIES.contains(&c.as_str())) | |
| .cloned() | |
| .collect(); | |
| // EAR99 items: no licence required except to embargoed/sanctioned destinations | |
| let license_required = !embargoed.is_empty(); | |
| let licence_exception = if !license_required && eccn == "EAR99" { | |
| Some("NLR".into()) // No Licence Required | |
| } else { | |
| None | |
| }; | |
| let incoterm = match req.product_type { | |
| ProductType::VinylRecord | ProductType::Cd | ProductType::Usb => Some(Incoterm::Dap), // default for physical goods | |
| _ => None, | |
| }; | |
| let notes = if embargoed.is_empty() && restricted.is_empty() { | |
| format!( | |
| "EAR99 β no licence required for {} destination(s)", | |
| req.countries.len() | |
| ) | |
| } else if license_required { | |
| format!( | |
| "LICENCE REQUIRED for embargoed destination(s): {}. Do not ship/deliver.", | |
| embargoed.join(", ") | |
| ) | |
| } else { | |
| format!( | |
| "Restricted territory review required: {}", | |
| restricted.join(", ") | |
| ) | |
| }; | |
| ClassificationResult { | |
| request_id: new_id(), | |
| title: req.title.clone(), | |
| product_type: req.product_type.clone(), | |
| eccn, | |
| hs_code, | |
| ear_jurisdiction: ear, | |
| itar_jurisdiction: itar, | |
| license_required, | |
| licence_exception, | |
| restricted_countries: restricted, | |
| embargoed_countries: embargoed, | |
| incoterm, | |
| notes, | |
| classified_at: now_iso(), | |
| } | |
| } | |
| /// Screen a payee + territories against sanctions/DPS lists. | |
| fn screen(req: &ScreeningRequest) -> ScreeningResult { | |
| let mut blocked: Vec<String> = Vec::new(); | |
| let mut review: Vec<String> = Vec::new(); | |
| let embargoed: Vec<String> = req | |
| .territories | |
| .iter() | |
| .filter(|t| EMBARGOED_COUNTRIES.contains(&t.as_str())) | |
| .cloned() | |
| .collect(); | |
| let restricted: Vec<String> = req | |
| .territories | |
| .iter() | |
| .filter(|t| RESTRICTED_TERRITORIES.contains(&t.as_str())) | |
| .cloned() | |
| .collect(); | |
| if EMBARGOED_COUNTRIES.contains(&req.payee_country.as_str()) { | |
| blocked.push(format!( | |
| "Payee country '{}' is under comprehensive embargo", | |
| req.payee_country | |
| )); | |
| } | |
| if !embargoed.is_empty() { | |
| blocked.push(format!( | |
| "Delivery territories under embargo: {}", | |
| embargoed.join(", ") | |
| )); | |
| } | |
| if !restricted.is_empty() { | |
| review.push(format!( | |
| "Restricted territories require manual review: {}", | |
| restricted.join(", ") | |
| )); | |
| } | |
| // Large-value payments to high-risk jurisdictions need enhanced due diligence | |
| if req.amount_usd > 10_000.0 && restricted.contains(&req.payee_country) { | |
| review.push(format!( | |
| "Payment >{:.0} USD to restricted territory '{}' β enhanced due diligence required", | |
| req.amount_usd, req.payee_country | |
| )); | |
| } | |
| let outcome = if !blocked.is_empty() { | |
| ScreeningOutcome::Blocked | |
| } else if !review.is_empty() { | |
| ScreeningOutcome::ReviewRequired | |
| } else { | |
| ScreeningOutcome::Clear | |
| }; | |
| ScreeningResult { | |
| screening_id: req.screening_id.clone(), | |
| outcome, | |
| blocked_reasons: blocked, | |
| review_reasons: review, | |
| embargoed_territories: embargoed, | |
| restricted_territories: restricted, | |
| dps_checked: false, // set true when live DPS API called | |
| screened_at: now_iso(), | |
| } | |
| } | |
| // ββ HTTP handlers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| /// POST /api/gtms/classify | |
| pub async fn classify_work( | |
| State(state): State<AppState>, | |
| Json(req): Json<ClassificationRequest>, | |
| ) -> Result<Json<ClassificationResult>, StatusCode> { | |
| // LangSec: validate HS code if caller provides one (future override path) | |
| let result = classify(&req); | |
| if result.license_required { | |
| warn!( | |
| title=%req.title, | |
| embargoed=?result.embargoed_countries, | |
| "GTMS: export licence required" | |
| ); | |
| } | |
| state | |
| .audit_log | |
| .record(&format!( | |
| "GTMS_CLASSIFY title='{}' eccn='{}' hs={:?} licence_req={} embargoed={:?}", | |
| result.title, | |
| result.eccn, | |
| result.hs_code, | |
| result.license_required, | |
| result.embargoed_countries, | |
| )) | |
| .ok(); | |
| state.gtms_db.save_classification(result.clone()); | |
| Ok(Json(result)) | |
| } | |
| /// POST /api/gtms/screen | |
| pub async fn screen_distribution( | |
| State(state): State<AppState>, | |
| Json(req): Json<ScreeningRequest>, | |
| ) -> Result<Json<ScreeningResult>, StatusCode> { | |
| let result = screen(&req); | |
| match result.outcome { | |
| ScreeningOutcome::Blocked => { | |
| warn!( | |
| screening_id=%result.screening_id, | |
| payee=%req.payee_name, | |
| reasons=?result.blocked_reasons, | |
| "GTMS: distribution BLOCKED" | |
| ); | |
| } | |
| ScreeningOutcome::ReviewRequired => { | |
| warn!( | |
| screening_id=%result.screening_id, | |
| payee=%req.payee_name, | |
| reasons=?result.review_reasons, | |
| "GTMS: distribution requires review" | |
| ); | |
| } | |
| ScreeningOutcome::Clear => { | |
| info!(screening_id=%result.screening_id, payee=%req.payee_name, "GTMS: clear"); | |
| } | |
| } | |
| state | |
| .audit_log | |
| .record(&format!( | |
| "GTMS_SCREEN id='{}' payee='{}' outcome={:?} blocked={:?}", | |
| result.screening_id, req.payee_name, result.outcome, result.blocked_reasons, | |
| )) | |
| .ok(); | |
| state.gtms_db.save_screening(result.clone()); | |
| Ok(Json(result)) | |
| } | |
| /// GET /api/gtms/declaration/:id | |
| pub async fn get_declaration( | |
| State(state): State<AppState>, | |
| Path(id): Path<String>, | |
| ) -> Result<Json<ExportDeclaration>, StatusCode> { | |
| state | |
| .gtms_db | |
| .get_declaration(&id) | |
| .map(Json) | |
| .ok_or(StatusCode::NOT_FOUND) | |
| } | |