registry_v7.rs (5228B)
1 use radroots_event::{ 2 contract::registry_v7::{ 3 ContractMatchError, ContractValidationError, EventContract, event_contract_registry_v7, 4 validate_event_contract_registry_v7, 5 }, 6 envelope::kind::{ 7 KIND_CLASSIFIED_LISTING, KIND_COMMENT, KIND_DELETION_REQUEST, KIND_POST, KIND_PROFILE, 8 }, 9 food::availability::RADROOTS_FOOD_AVAILABILITY_CONTRACT_ID, 10 }; 11 12 use crate::{ 13 comment::inbound::registry_v7::project_verified_nip22_comment_event_registry_v7, 14 deletion::reconciliation_v1::inbound::project_verified_nip09_deletion_request_event_v1, 15 food_availability::inbound::registry_v7::{ 16 RadrootsFoodAvailabilityProjectionOutcome, 17 project_verified_food_availability_event_registry_v7, 18 }, 19 post::inbound::registry_v7::project_verified_post_event_registry_v7, 20 profile::inbound::registry_v7::parse_inbound_profile_metadata_registry_v7, 21 reply::inbound::registry_v7::project_verified_nip10_reply_event_registry_v7, 22 verification::v1::RadrootsSignatureVerifiedEvent, 23 }; 24 25 const PROFILE_CONTRACT_ID: &str = "radroots.profile.metadata.v1"; 26 const INTERNAL_CONTRACT_MISSING: &str = "registry_v7_contract_missing"; 27 28 /// The closed admission decision persisted by event-store reconciliation v1. 29 /// 30 /// This intentionally excludes current typed admission enums and rich errors. 31 /// Later registries may grow those APIs without changing persisted v7 facts. 32 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 33 pub enum RadrootsRegistryV7AdmissionDecision { 34 Admitted { contract: &'static EventContract }, 35 Unsupported { code: &'static str }, 36 Invalid { code: &'static str }, 37 Defect { code: &'static str }, 38 } 39 40 /// Admits through the immutable event-contract registry-v7 behavior graph. 41 /// 42 /// Event-store migration 0002 calls this entry point. Later registries must 43 /// retain it and add a new versioned admission function. 44 pub fn admit_verified_event_registry_v7( 45 event: &RadrootsSignatureVerifiedEvent, 46 ) -> RadrootsRegistryV7AdmissionDecision { 47 match event.event().kind_u32() { 48 KIND_PROFILE => match parse_inbound_profile_metadata_registry_v7(event.event().content()) { 49 Ok(_) => admitted(PROFILE_CONTRACT_ID), 50 Err(error) => invalid(error.code()), 51 }, 52 KIND_POST => match project_verified_post_event_registry_v7(event) { 53 Ok(projection) if projection.classification().is_root_card() => { 54 admitted(projection.classification().contract_id()) 55 } 56 Ok(_) => match project_verified_nip10_reply_event_registry_v7(event) { 57 Ok(projection) => admitted(projection.contract_id()), 58 Err(error) => invalid(error.code()), 59 }, 60 Err(error) => invalid(error.code()), 61 }, 62 KIND_COMMENT => match project_verified_nip22_comment_event_registry_v7(event) { 63 Ok(projection) => admitted(projection.contract_id()), 64 Err(error) => invalid(error.code()), 65 }, 66 KIND_DELETION_REQUEST => match project_verified_nip09_deletion_request_event_v1(event) { 67 Ok(projection) => admitted(projection.contract_id()), 68 Err(error) => invalid(error.code()), 69 }, 70 KIND_CLASSIFIED_LISTING => { 71 match project_verified_food_availability_event_registry_v7(event) { 72 Ok(RadrootsFoodAvailabilityProjectionOutcome::Focused(_)) => { 73 admitted(RADROOTS_FOOD_AVAILABILITY_CONTRACT_ID) 74 } 75 Ok(RadrootsFoodAvailabilityProjectionOutcome::Excluded(_)) => { 76 admit_registry_contract_v7(event) 77 } 78 Err(error) => invalid(error.code()), 79 } 80 } 81 _ => admit_registry_contract_v7(event), 82 } 83 } 84 85 fn admit_registry_contract_v7( 86 event: &RadrootsSignatureVerifiedEvent, 87 ) -> RadrootsRegistryV7AdmissionDecision { 88 match validate_event_contract_registry_v7(event.event()) { 89 Ok(contract) => RadrootsRegistryV7AdmissionDecision::Admitted { contract }, 90 Err(ContractValidationError::ContractMatch { 91 error: ContractMatchError::UnsupportedKind(_), 92 }) => unsupported("unsupported_kind"), 93 Err(ContractValidationError::ContractMatch { 94 error: ContractMatchError::UnsupportedShape(_), 95 }) => unsupported("unsupported_shape"), 96 Err(ContractValidationError::ContractMatch { 97 error: ContractMatchError::AmbiguousShape(_), 98 }) => invalid("ambiguous_shape"), 99 Err(error) => invalid(error.code()), 100 } 101 } 102 103 fn admitted(contract_id: &str) -> RadrootsRegistryV7AdmissionDecision { 104 match event_contract_registry_v7(contract_id) { 105 Some(contract) => RadrootsRegistryV7AdmissionDecision::Admitted { contract }, 106 None => RadrootsRegistryV7AdmissionDecision::Defect { 107 code: INTERNAL_CONTRACT_MISSING, 108 }, 109 } 110 } 111 112 const fn unsupported(code: &'static str) -> RadrootsRegistryV7AdmissionDecision { 113 RadrootsRegistryV7AdmissionDecision::Unsupported { code } 114 } 115 116 const fn invalid(code: &'static str) -> RadrootsRegistryV7AdmissionDecision { 117 RadrootsRegistryV7AdmissionDecision::Invalid { code } 118 } 119 120 #[cfg(test)] 121 mod tests;