1use serde::{Deserialize, Serialize};
11use crate::{Address, BlockHeight, Timestamp};
12use crate::agreement::{AttachmentRef, EncryptionMeta};
13
14pub type CaseId = [u8; 32];
20pub type ProcessEventId = [u8; 32];
22pub type OrderId = [u8; 32];
24pub type BenefitId = [u8; 32];
26pub type PolicyId = [u8; 32];
28pub type ProofId = [u8; 32];
30pub type SubjectId = [u8; 32];
32
33pub const CASE_DOMAIN_SEP: &[u8] = b"SRC851-CASE:";
38pub const CASE_COMMITMENT_SEP: &[u8] = b"SRC851-COMMITMENT:v1:";
39pub const PROCESS_EVENT_DOMAIN_SEP: &[u8] = b"SRC852-EVENT:";
40pub const EVENT_COMMITMENT_SEP: &[u8] = b"SRC852-COMMITMENT:v1:";
41pub const ORDER_DOMAIN_SEP: &[u8] = b"SRC853-ORDER:";
42pub const ORDER_COMMITMENT_SEP: &[u8] = b"SRC853-COMMITMENT:v1:";
43pub const BENEFIT_DOMAIN_SEP: &[u8] = b"SRC854-BENEFIT:";
44pub const DETERMINATION_COMMITMENT_SEP: &[u8] = b"SRC854-DETERMINATION:v1:";
45pub const LEGAL_PROOF_DOMAIN_SEP: &[u8] = b"SRC855-PROOF:";
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
53#[repr(u8)]
54pub enum CaseType {
55 Civil = 0,
57 Criminal = 1,
59 Administrative = 2,
61 Family = 3,
63 Probate = 4,
65 Bankruptcy = 5,
67 SmallClaims = 6,
69 Arbitration = 7,
71 Mediation = 8,
73 Regulatory = 9,
75 TaxCourt = 10,
77 Immigration = 11,
79 Other = 255,
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
85#[repr(u8)]
86pub enum CaseStatus {
87 Filed = 0,
89 Active = 1,
91 Stayed = 2,
93 Closed = 3,
95 Dismissed = 4,
97 Settled = 5,
99 Consolidated = 6,
101 Transferred = 7,
103 OnAppeal = 8,
105 Sealed = 9,
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
111#[repr(u8)]
112pub enum LegalIssuerClass {
113 CourtSystem = 0,
115 GovernmentAgency = 1,
117 Tribunal = 2,
119 ArbitrationBody = 3,
121 LawFirm = 10,
123 Notary = 11,
125 Auditor = 12,
127 LegalAid = 13,
129 ProcessServer = 14,
131 CourtReporter = 15,
133 GuardianAdLitem = 16,
135 Mediator = 17,
137 Other = 255,
139}
140
141impl LegalIssuerClass {
142 pub fn is_official(&self) -> bool {
144 matches!(self, Self::CourtSystem | Self::GovernmentAgency | Self::Tribunal)
145 }
146
147 pub fn is_lowkey(&self) -> bool {
149 matches!(
150 self,
151 Self::LawFirm
152 | Self::Notary
153 | Self::Auditor
154 | Self::LegalAid
155 | Self::ProcessServer
156 )
157 }
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
162pub struct CaseAnchor {
163 pub case_id: CaseId,
165 pub case_commitment: [u8; 32],
167 pub jurisdiction_code: String,
169 pub case_type: Option<CaseType>,
171 pub public_reference: Option<String>,
173 pub policy_id: PolicyId,
175 pub issuer_class: LegalIssuerClass,
177 pub issuer_address: Address,
179 pub status: CaseStatus,
181 pub created_at: Timestamp,
183 pub updated_at: Timestamp,
185 pub anchored_at_height: BlockHeight,
187 pub related_cases: Vec<CaseId>,
189}
190
191impl CaseAnchor {
192 pub fn generate_id(
194 issuer: &Address,
195 case_commitment: &[u8; 32],
196 jurisdiction: &str,
197 nonce: &[u8; 32],
198 ) -> CaseId {
199 let mut hasher = blake3::Hasher::new();
200 hasher.update(CASE_DOMAIN_SEP);
201 hasher.update(b":v1:");
202 hasher.update(issuer.as_ref());
203 hasher.update(case_commitment);
204 hasher.update(jurisdiction.as_bytes());
205 hasher.update(nonce);
206 *hasher.finalize().as_bytes()
207 }
208
209 pub fn generate_commitment(
211 case_number: &str,
212 parties_commitment: &[u8; 32],
213 filing_date: Timestamp,
214 additional_data: Option<&[u8]>,
215 ) -> [u8; 32] {
216 let mut hasher = blake3::Hasher::new();
217 hasher.update(CASE_COMMITMENT_SEP);
218 hasher.update(case_number.as_bytes());
219 hasher.update(parties_commitment);
220 hasher.update(&filing_date.to_le_bytes());
221 if let Some(data) = additional_data {
222 hasher.update(data);
223 }
224 *hasher.finalize().as_bytes()
225 }
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
234#[repr(u8)]
235pub enum ProcessEventType {
236 Filed = 0,
239 AnswerFiled = 1,
241 MotionFiled = 2,
243 AmendmentFiled = 3,
245 DiscoveryFiled = 4,
247 AppealFiled = 5,
249
250 Served = 10,
253 NoticeDelivered = 11,
255 SubpoenaServed = 12,
257 PublicationCompleted = 13,
259
260 HearingScheduled = 20,
263 HearingHeld = 21,
265 HearingContinued = 22,
267 HearingCancelled = 23,
269 TrialStarted = 24,
271 TrialConcluded = 25,
273
274 OrderIssued = 30,
277 JudgmentEntered = 31,
279 RulingIssued = 32,
281 VerdictRendered = 33,
283
284 CaseStayed = 40,
287 StayLifted = 41,
289 CaseSealed = 42,
291 CaseUnsealed = 43,
293 CaseDismissed = 44,
295 CaseSettled = 45,
297 CaseClosed = 46,
299 CaseReopened = 47,
301
302 EvidenceAdmitted = 50,
305 WitnessTestimony = 51,
307 ExpertOpinion = 52,
309 MediationCompleted = 53,
311 SettlementConference = 54,
313
314 Other = 255,
316}
317
318#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
320#[repr(u8)]
321pub enum ProcessEventStatus {
322 Recorded = 0,
324 Superseded = 1,
326 Revoked = 2,
328 Corrected = 3,
330}
331
332#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
334pub struct ProcessEvent {
335 pub event_id: ProcessEventId,
337 pub case_id: CaseId,
339 pub event_type: ProcessEventType,
341 pub event_commitment: [u8; 32],
343 pub issuer_address: Address,
345 pub issuer_class: LegalIssuerClass,
347 pub event_time_start: Option<Timestamp>,
349 pub event_time_end: Option<Timestamp>,
351 pub attachments: Vec<AttachmentRef>,
353 pub policy_id: PolicyId,
355 pub revocation_ref: Option<[u8; 32]>,
357 pub status: ProcessEventStatus,
359 pub created_at: Timestamp,
361 pub recorded_at_height: BlockHeight,
363 pub supersedes: Option<ProcessEventId>,
365}
366
367impl ProcessEvent {
368 pub fn generate_id(
370 case_id: &CaseId,
371 event_type: ProcessEventType,
372 issuer: &Address,
373 nonce: &[u8; 32],
374 ) -> ProcessEventId {
375 let mut hasher = blake3::Hasher::new();
376 hasher.update(PROCESS_EVENT_DOMAIN_SEP);
377 hasher.update(b":v1:");
378 hasher.update(case_id);
379 hasher.update(&[event_type as u8]);
380 hasher.update(issuer.as_ref());
381 hasher.update(nonce);
382 *hasher.finalize().as_bytes()
383 }
384
385 pub fn generate_commitment(
387 event_details: &[u8],
388 timestamp: Timestamp,
389 participants_commitment: Option<&[u8; 32]>,
390 ) -> [u8; 32] {
391 let mut hasher = blake3::Hasher::new();
392 hasher.update(EVENT_COMMITMENT_SEP);
393 hasher.update(event_details);
394 hasher.update(×tamp.to_le_bytes());
395 if let Some(pc) = participants_commitment {
396 hasher.update(pc);
397 }
398 *hasher.finalize().as_bytes()
399 }
400}
401
402#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
408#[repr(u8)]
409pub enum OrderType {
410 Tro = 0,
413 PreliminaryInjunction = 1,
415 ProtectiveOrder = 2,
417 DiscoveryOrder = 3,
419 SchedulingOrder = 4,
421
422 DefaultJudgment = 10,
425 SummaryJudgment = 11,
427 FinalJudgment = 12,
429 ConsentJudgment = 13,
431 DeclaratoryJudgment = 14,
433
434 PermanentInjunction = 20,
437 MandatoryInjunction = 21,
439 ProhibitoryInjunction = 22,
441
442 MoneyJudgment = 30,
445 GarnishmentOrder = 31,
447 AttachmentOrder = 32,
449 RestitutionOrder = 33,
451 CostOrder = 34,
453
454 ChildCustodyOrder = 40,
457 SupportOrder = 41,
459 DivorceDecree = 42,
461 ProbateOrder = 43,
463 GuardianshipOrder = 44,
465
466 Sentence = 50,
469 BailOrder = 51,
471 ProbationOrder = 52,
473 ExpungementOrder = 53,
475
476 AdministrativeOrder = 60,
479 ConsentDecree = 61,
481 ComplianceOrder = 62,
483
484 Other = 255,
486}
487
488#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
490#[repr(u8)]
491pub enum OrderStatus {
492 Active = 0,
494 Stayed = 1,
496 Vacated = 2,
498 Superseded = 3,
500 Expired = 4,
502 Satisfied = 5,
504 Modified = 6,
506 Reversed = 7,
508 Affirmed = 8,
510}
511
512#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
514pub struct CourtOrder {
515 pub order_id: OrderId,
517 pub case_id: CaseId,
519 pub order_type: OrderType,
521 pub order_commitment: [u8; 32],
523 pub issuer_address: Address,
525 pub issuer_class: LegalIssuerClass,
527 pub status: OrderStatus,
529 pub effective_from: Timestamp,
531 pub expiry: Option<Timestamp>,
533 pub policy_id: PolicyId,
535 pub revocation_ref: Option<[u8; 32]>,
537 pub created_at: Timestamp,
539 pub updated_at: Timestamp,
541 pub issued_at_height: BlockHeight,
543 pub supersedes_order_id: Option<OrderId>,
545 pub attachments: Vec<AttachmentRef>,
547}
548
549impl CourtOrder {
550 pub fn generate_id(
552 case_id: &CaseId,
553 order_type: OrderType,
554 issuer: &Address,
555 nonce: &[u8; 32],
556 ) -> OrderId {
557 let mut hasher = blake3::Hasher::new();
558 hasher.update(ORDER_DOMAIN_SEP);
559 hasher.update(b":v1:");
560 hasher.update(case_id);
561 hasher.update(&[order_type as u8]);
562 hasher.update(issuer.as_ref());
563 hasher.update(nonce);
564 *hasher.finalize().as_bytes()
565 }
566
567 pub fn generate_commitment(
569 order_text_hash: &[u8; 32],
570 obligations_hash: Option<&[u8; 32]>,
571 parties_hash: &[u8; 32],
572 ) -> [u8; 32] {
573 let mut hasher = blake3::Hasher::new();
574 hasher.update(ORDER_COMMITMENT_SEP);
575 hasher.update(order_text_hash);
576 if let Some(oh) = obligations_hash {
577 hasher.update(oh);
578 }
579 hasher.update(parties_hash);
580 *hasher.finalize().as_bytes()
581 }
582
583 pub fn is_in_effect(&self, current_time: Timestamp) -> bool {
585 if !matches!(self.status, OrderStatus::Active | OrderStatus::Affirmed) {
586 return false;
587 }
588 if current_time < self.effective_from {
589 return false;
590 }
591 if let Some(exp) = self.expiry {
592 if current_time >= exp {
593 return false;
594 }
595 }
596 true
597 }
598}
599
600#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
606#[repr(u8)]
607pub enum BenefitType {
608 SocialSecurityRetirement = 0,
610 SocialSecurityDisability = 1,
611 SupplementalSecurityIncome = 2,
612 SurvivorsInsurance = 3,
613
614 Medicare = 10,
616 Medicaid = 11,
617 ChildHealthInsurance = 12,
618 VeteranHealthcare = 13,
619
620 UnemploymentInsurance = 20,
622 WorkersCompensation = 21,
623 DisabilityInsurance = 22,
624 TrainingBenefit = 23,
625
626 FoodAssistance = 30,
628 HousingAssistance = 31,
629 EnergyAssistance = 32,
630 ChildNutrition = 33,
631
632 ChildTaxCredit = 40,
634 EarnedIncomeCredit = 41,
635 ChildcareAssistance = 42,
636 FamilyLeave = 43,
637
638 EducationGrant = 50,
640 StudentLoanSubsidy = 51,
641 TuitionAssistance = 52,
642
643 VeteranPension = 60,
645 VeteranDisability = 61,
646 GiBill = 62,
647 VeteranHousing = 63,
648
649 RefugeeAssistance = 70,
651 AsylumSupport = 71,
652
653 Other = 255,
655}
656
657#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
659#[repr(u8)]
660pub enum BenefitStatus {
661 Pending = 0,
663 Eligible = 1,
665 Approved = 2,
667 Denied = 3,
669 Terminated = 4,
671 Suspended = 5,
673 UnderReview = 6,
675 Expired = 7,
677 Reduced = 8,
679 Increased = 9,
681}
682
683#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
685pub struct BenefitDetermination {
686 pub benefit_id: BenefitId,
688 pub benefit_type: BenefitType,
690 pub jurisdiction_code: String,
692 pub status: BenefitStatus,
694 pub determination_commitment: [u8; 32],
696 pub subject_nullifier: [u8; 32],
698 pub issuer_address: Address,
700 pub issuer_class: LegalIssuerClass,
702 pub valid_from: Timestamp,
704 pub expiry: Option<Timestamp>,
706 pub policy_id: PolicyId,
708 pub revocation_ref: Option<[u8; 32]>,
710 pub created_at: Timestamp,
712 pub updated_at: Timestamp,
714 pub recorded_at_height: BlockHeight,
716 pub supersedes: Option<BenefitId>,
718}
719
720impl BenefitDetermination {
721 pub fn generate_id(
723 subject_nullifier: &[u8; 32],
724 benefit_type: BenefitType,
725 jurisdiction: &str,
726 nonce: &[u8; 32],
727 ) -> BenefitId {
728 let mut hasher = blake3::Hasher::new();
729 hasher.update(BENEFIT_DOMAIN_SEP);
730 hasher.update(b":v1:");
731 hasher.update(subject_nullifier);
732 hasher.update(&[benefit_type as u8]);
733 hasher.update(jurisdiction.as_bytes());
734 hasher.update(nonce);
735 *hasher.finalize().as_bytes()
736 }
737
738 pub fn generate_commitment(
740 eligibility_criteria_hash: &[u8; 32],
741 amount_commitment: Option<&[u8; 32]>,
742 conditions_hash: Option<&[u8; 32]>,
743 ) -> [u8; 32] {
744 let mut hasher = blake3::Hasher::new();
745 hasher.update(DETERMINATION_COMMITMENT_SEP);
746 hasher.update(eligibility_criteria_hash);
747 if let Some(ac) = amount_commitment {
748 hasher.update(ac);
749 }
750 if let Some(ch) = conditions_hash {
751 hasher.update(ch);
752 }
753 *hasher.finalize().as_bytes()
754 }
755
756 pub fn is_valid(&self, current_time: Timestamp) -> bool {
758 if !matches!(
759 self.status,
760 BenefitStatus::Eligible | BenefitStatus::Approved | BenefitStatus::Increased
761 ) {
762 return false;
763 }
764 if current_time < self.valid_from {
765 return false;
766 }
767 if let Some(exp) = self.expiry {
768 if current_time >= exp {
769 return false;
770 }
771 }
772 true
773 }
774}
775
776#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
782#[repr(u8)]
783pub enum LegalProofProfile {
784 ActiveOrderOfType = 0,
786 BenefitApproved = 1,
788 CaseEventExists = 2,
790 CaseStatus = 3,
792 OrderIssuedByValid = 4,
794 BenefitEligible = 5,
796 NoActiveOrderOfType = 6,
798}
799
800#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
802#[repr(u8)]
803pub enum LegalProofType {
804 Mock = 0,
806 Groth16 = 1,
808 Plonk = 2,
810 ThresholdSignature = 3,
812 MerkleInclusion = 4,
814}
815
816#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
818pub struct LegalProofEnvelope {
819 pub proof_id: ProofId,
821 pub profile: LegalProofProfile,
823 pub profile_id: String,
825 pub policy_ids: Vec<PolicyId>,
827 pub public_inputs: Vec<u8>,
829 pub proof_data: Vec<u8>,
831 pub proof_type: LegalProofType,
833 pub subject_nullifier: [u8; 32],
835 pub generated_at: Timestamp,
837 pub expires_at: Timestamp,
839}
840
841impl LegalProofEnvelope {
842 pub fn generate_id(
844 profile: LegalProofProfile,
845 subject_nullifier: &[u8; 32],
846 policy_ids: &[PolicyId],
847 nonce: &[u8; 32],
848 ) -> ProofId {
849 let mut hasher = blake3::Hasher::new();
850 hasher.update(LEGAL_PROOF_DOMAIN_SEP);
851 hasher.update(b":v1:");
852 hasher.update(&[profile as u8]);
853 hasher.update(subject_nullifier);
854 for policy_id in policy_ids {
855 hasher.update(policy_id);
856 }
857 hasher.update(nonce);
858 *hasher.finalize().as_bytes()
859 }
860}
861
862#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
868#[repr(u8)]
869pub enum LegalOperation {
870 AnchorCase = 0,
872 UpdateCase = 1,
873 CloseCase = 2,
874 SealCase = 3,
875 UnsealCase = 4,
876 ConsolidateCase = 5,
877 TransferCase = 6,
878
879 RecordEvent = 10,
881 UpdateEvent = 11,
882 SupersedeEvent = 12,
883 RevokeEvent = 13,
884
885 IssueOrder = 20,
887 UpdateOrderStatus = 21,
888 StayOrder = 22,
889 VacateOrder = 23,
890 SupersedeOrder = 24,
891 ModifyOrder = 25,
892
893 DetermineBenefit = 30,
895 UpdateBenefitStatus = 31,
896 TerminateBenefit = 32,
897 SuspendBenefit = 33,
898 ReinstateBenefit = 34,
899
900 SubmitProof = 40,
902 VerifyProof = 41,
903}
904
905#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
907pub struct LegalTxData {
908 pub operation: LegalOperation,
909 pub data: Vec<u8>,
910 pub recipient: crate::Address,
912}
913
914#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
920pub enum LegalEvent {
921 CaseAnchored {
923 case_id: CaseId,
924 jurisdiction: String,
925 case_commitment: [u8; 32],
926 timestamp: Timestamp,
927 },
928 CaseUpdated {
929 case_id: CaseId,
930 new_status: CaseStatus,
931 timestamp: Timestamp,
932 },
933 CaseSealed {
934 case_id: CaseId,
935 timestamp: Timestamp,
936 },
937 CaseUnsealed {
938 case_id: CaseId,
939 timestamp: Timestamp,
940 },
941
942 CaseEventRecorded {
944 case_id: CaseId,
945 event_type: ProcessEventType,
946 issuer: Address,
947 event_hash: [u8; 32],
948 timestamp: Timestamp,
949 },
950 CaseEventSuperseded {
951 old_event_id: ProcessEventId,
952 new_event_id: ProcessEventId,
953 timestamp: Timestamp,
954 },
955
956 OrderIssued {
958 order_id: OrderId,
959 case_id: CaseId,
960 order_type: OrderType,
961 status: OrderStatus,
962 timestamp: Timestamp,
963 },
964 OrderStatusUpdated {
965 order_id: OrderId,
966 new_status: OrderStatus,
967 timestamp: Timestamp,
968 },
969
970 BenefitDetermined {
972 benefit_id: BenefitId,
973 benefit_type: BenefitType,
974 status: BenefitStatus,
975 jurisdiction: String,
976 timestamp: Timestamp,
977 },
978 BenefitUpdated {
979 benefit_id: BenefitId,
980 new_status: BenefitStatus,
981 timestamp: Timestamp,
982 },
983
984 LegalProofSubmitted {
986 proof_id: ProofId,
987 profile: LegalProofProfile,
988 timestamp: Timestamp,
989 },
990 LegalProofVerified {
991 proof_id: ProofId,
992 valid: bool,
993 timestamp: Timestamp,
994 },
995}
996
997#[cfg(test)]
998mod tests {
999 use super::*;
1000
1001 #[test]
1002 fn test_case_id_generation() {
1003 let issuer = Address::new([1u8; 20]);
1004 let commitment = [2u8; 32];
1005 let nonce = [3u8; 32];
1006
1007 let id = CaseAnchor::generate_id(&issuer, &commitment, "US-NY", &nonce);
1008 assert_ne!(id, [0u8; 32]);
1009
1010 let id2 = CaseAnchor::generate_id(&issuer, &commitment, "US-NY", &nonce);
1012 assert_eq!(id, id2);
1013
1014 let id3 = CaseAnchor::generate_id(&issuer, &commitment, "US-CA", &nonce);
1016 assert_ne!(id, id3);
1017 }
1018
1019 #[test]
1020 fn test_case_commitment() {
1021 let parties = [1u8; 32];
1022 let commitment = CaseAnchor::generate_commitment("2024-CV-12345", &parties, 1000, None);
1023 assert_ne!(commitment, [0u8; 32]);
1024 }
1025
1026 #[test]
1027 fn test_process_event_id() {
1028 let case_id = [1u8; 32];
1029 let issuer = Address::new([2u8; 20]);
1030 let nonce = [3u8; 32];
1031
1032 let id = ProcessEvent::generate_id(&case_id, ProcessEventType::Filed, &issuer, &nonce);
1033 assert_ne!(id, [0u8; 32]);
1034 }
1035
1036 #[test]
1037 fn test_order_id_generation() {
1038 let case_id = [1u8; 32];
1039 let issuer = Address::new([2u8; 20]);
1040 let nonce = [3u8; 32];
1041
1042 let id = CourtOrder::generate_id(&case_id, OrderType::FinalJudgment, &issuer, &nonce);
1043 assert_ne!(id, [0u8; 32]);
1044 }
1045
1046 #[test]
1047 fn test_order_in_effect() {
1048 let order = CourtOrder {
1049 order_id: [1u8; 32],
1050 case_id: [2u8; 32],
1051 order_type: OrderType::FinalJudgment,
1052 order_commitment: [3u8; 32],
1053 issuer_address: Address::new([4u8; 20]),
1054 issuer_class: LegalIssuerClass::CourtSystem,
1055 status: OrderStatus::Active,
1056 effective_from: 1000,
1057 expiry: Some(2000),
1058 policy_id: [5u8; 32],
1059 revocation_ref: None,
1060 created_at: 1000,
1061 updated_at: 1000,
1062 issued_at_height: 100,
1063 supersedes_order_id: None,
1064 attachments: vec![],
1065 };
1066
1067 assert!(!order.is_in_effect(500)); assert!(order.is_in_effect(1500)); assert!(!order.is_in_effect(2500)); }
1071
1072 #[test]
1073 fn test_benefit_id_generation() {
1074 let nullifier = [1u8; 32];
1075 let nonce = [2u8; 32];
1076
1077 let id = BenefitDetermination::generate_id(
1078 &nullifier,
1079 BenefitType::SocialSecurityRetirement,
1080 "US",
1081 &nonce,
1082 );
1083 assert_ne!(id, [0u8; 32]);
1084 }
1085
1086 #[test]
1087 fn test_benefit_validity() {
1088 let benefit = BenefitDetermination {
1089 benefit_id: [1u8; 32],
1090 benefit_type: BenefitType::Medicare,
1091 jurisdiction_code: "US".to_string(),
1092 status: BenefitStatus::Approved,
1093 determination_commitment: [2u8; 32],
1094 subject_nullifier: [3u8; 32],
1095 issuer_address: Address::new([4u8; 20]),
1096 issuer_class: LegalIssuerClass::GovernmentAgency,
1097 valid_from: 1000,
1098 expiry: None,
1099 policy_id: [5u8; 32],
1100 revocation_ref: None,
1101 created_at: 1000,
1102 updated_at: 1000,
1103 recorded_at_height: 100,
1104 supersedes: None,
1105 };
1106
1107 assert!(!benefit.is_valid(500)); assert!(benefit.is_valid(1500)); }
1110
1111 #[test]
1112 fn test_legal_issuer_class() {
1113 assert!(LegalIssuerClass::CourtSystem.is_official());
1114 assert!(LegalIssuerClass::GovernmentAgency.is_official());
1115 assert!(!LegalIssuerClass::LawFirm.is_official());
1116
1117 assert!(LegalIssuerClass::LawFirm.is_lowkey());
1118 assert!(LegalIssuerClass::Notary.is_lowkey());
1119 assert!(!LegalIssuerClass::CourtSystem.is_lowkey());
1120 }
1121
1122 #[test]
1123 fn test_legal_proof_id() {
1124 let nullifier = [1u8; 32];
1125 let policies = vec![[2u8; 32], [3u8; 32]];
1126 let nonce = [4u8; 32];
1127
1128 let id = LegalProofEnvelope::generate_id(
1129 LegalProofProfile::BenefitApproved,
1130 &nullifier,
1131 &policies,
1132 &nonce,
1133 );
1134 assert_ne!(id, [0u8; 32]);
1135 }
1136}