Skip to main content

zlicenser_server/storage/
types.rs

1use uuid::Uuid;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum ConnectivityMode {
5    AirGapped,
6    Online,
7    AlwaysOnline,
8}
9
10impl std::fmt::Display for ConnectivityMode {
11    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12        f.write_str(match self {
13            Self::AirGapped => "AirGapped",
14            Self::Online => "Online",
15            Self::AlwaysOnline => "AlwaysOnline",
16        })
17    }
18}
19
20impl std::str::FromStr for ConnectivityMode {
21    type Err = crate::Error;
22    fn from_str(s: &str) -> crate::Result<Self> {
23        match s {
24            "AirGapped" => Ok(Self::AirGapped),
25            "Online" => Ok(Self::Online),
26            "AlwaysOnline" => Ok(Self::AlwaysOnline),
27            _ => Err(crate::Error::Corrupt(format!(
28                "unknown ConnectivityMode: {s}"
29            ))),
30        }
31    }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum TsaTier {
36    Free,
37    Standard,
38    Qualified,
39}
40
41impl std::fmt::Display for TsaTier {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        f.write_str(match self {
44            Self::Free => "Free",
45            Self::Standard => "Standard",
46            Self::Qualified => "Qualified",
47        })
48    }
49}
50
51impl std::str::FromStr for TsaTier {
52    type Err = crate::Error;
53    fn from_str(s: &str) -> crate::Result<Self> {
54        match s {
55            "Free" => Ok(Self::Free),
56            "Standard" => Ok(Self::Standard),
57            "Qualified" => Ok(Self::Qualified),
58            _ => Err(crate::Error::Corrupt(format!("unknown TsaTier: {s}"))),
59        }
60    }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum TransferPolicy {
65    NotAvailable,
66    VendorApproval,
67}
68
69impl std::fmt::Display for TransferPolicy {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        f.write_str(match self {
72            Self::NotAvailable => "NotAvailable",
73            Self::VendorApproval => "VendorApproval",
74        })
75    }
76}
77
78impl std::str::FromStr for TransferPolicy {
79    type Err = crate::Error;
80    fn from_str(s: &str) -> crate::Result<Self> {
81        match s {
82            "NotAvailable" => Ok(Self::NotAvailable),
83            "VendorApproval" => Ok(Self::VendorApproval),
84            _ => Err(crate::Error::Corrupt(format!(
85                "unknown TransferPolicy: {s}"
86            ))),
87        }
88    }
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub enum TermsValidationStatus {
93    Valid,
94    Warnings,
95    Conflicts,
96    PendingReview,
97}
98
99impl std::fmt::Display for TermsValidationStatus {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        f.write_str(match self {
102            Self::Valid => "Valid",
103            Self::Warnings => "Warnings",
104            Self::Conflicts => "Conflicts",
105            Self::PendingReview => "PendingReview",
106        })
107    }
108}
109
110impl std::str::FromStr for TermsValidationStatus {
111    type Err = crate::Error;
112    fn from_str(s: &str) -> crate::Result<Self> {
113        match s {
114            "Valid" => Ok(Self::Valid),
115            "Warnings" => Ok(Self::Warnings),
116            "Conflicts" => Ok(Self::Conflicts),
117            "PendingReview" => Ok(Self::PendingReview),
118            _ => Err(crate::Error::Corrupt(format!(
119                "unknown TermsValidationStatus: {s}"
120            ))),
121        }
122    }
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub enum LicenseStatus {
127    Active,
128    Revoked,
129    Superseded,
130}
131
132impl std::fmt::Display for LicenseStatus {
133    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134        f.write_str(match self {
135            Self::Active => "Active",
136            Self::Revoked => "Revoked",
137            Self::Superseded => "Superseded",
138        })
139    }
140}
141
142impl std::str::FromStr for LicenseStatus {
143    type Err = crate::Error;
144    fn from_str(s: &str) -> crate::Result<Self> {
145        match s {
146            "Active" => Ok(Self::Active),
147            "Revoked" => Ok(Self::Revoked),
148            "Superseded" => Ok(Self::Superseded),
149            _ => Err(crate::Error::Corrupt(format!("unknown LicenseStatus: {s}"))),
150        }
151    }
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq)]
155pub enum PaymentProvider {
156    Stripe,
157    Custom,
158}
159
160impl std::fmt::Display for PaymentProvider {
161    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162        f.write_str(match self {
163            Self::Stripe => "Stripe",
164            Self::Custom => "Custom",
165        })
166    }
167}
168
169impl std::str::FromStr for PaymentProvider {
170    type Err = crate::Error;
171    fn from_str(s: &str) -> crate::Result<Self> {
172        match s {
173            "Stripe" => Ok(Self::Stripe),
174            "Custom" => Ok(Self::Custom),
175            _ => Err(crate::Error::Corrupt(format!(
176                "unknown PaymentProvider: {s}"
177            ))),
178        }
179    }
180}
181
182#[derive(Debug, Clone, Copy, PartialEq, Eq)]
183pub enum PaymentStatus {
184    Pending,
185    Confirmed,
186    Failed,
187}
188
189impl std::fmt::Display for PaymentStatus {
190    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191        f.write_str(match self {
192            Self::Pending => "Pending",
193            Self::Confirmed => "Confirmed",
194            Self::Failed => "Failed",
195        })
196    }
197}
198
199impl std::str::FromStr for PaymentStatus {
200    type Err = crate::Error;
201    fn from_str(s: &str) -> crate::Result<Self> {
202        match s {
203            "Pending" => Ok(Self::Pending),
204            "Confirmed" => Ok(Self::Confirmed),
205            "Failed" => Ok(Self::Failed),
206            _ => Err(crate::Error::Corrupt(format!("unknown PaymentStatus: {s}"))),
207        }
208    }
209}
210
211#[derive(Debug, Clone, Copy, PartialEq, Eq)]
212pub enum ProviderTier {
213    Verified,
214    Pseudonymous,
215    Anonymous,
216}
217
218impl std::fmt::Display for ProviderTier {
219    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
220        f.write_str(match self {
221            Self::Verified => "Verified",
222            Self::Pseudonymous => "Pseudonymous",
223            Self::Anonymous => "Anonymous",
224        })
225    }
226}
227
228impl std::str::FromStr for ProviderTier {
229    type Err = crate::Error;
230    fn from_str(s: &str) -> crate::Result<Self> {
231        match s {
232            "Verified" => Ok(Self::Verified),
233            "Pseudonymous" => Ok(Self::Pseudonymous),
234            "Anonymous" => Ok(Self::Anonymous),
235            _ => Err(crate::Error::Corrupt(format!("unknown ProviderTier: {s}"))),
236        }
237    }
238}
239
240#[derive(Debug, Clone, Copy, PartialEq, Eq)]
241pub enum TransferStatus {
242    Pending,
243    Approved,
244    Rejected,
245}
246
247impl std::fmt::Display for TransferStatus {
248    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249        f.write_str(match self {
250            Self::Pending => "Pending",
251            Self::Approved => "Approved",
252            Self::Rejected => "Rejected",
253        })
254    }
255}
256
257impl std::str::FromStr for TransferStatus {
258    type Err = crate::Error;
259    fn from_str(s: &str) -> crate::Result<Self> {
260        match s {
261            "Pending" => Ok(Self::Pending),
262            "Approved" => Ok(Self::Approved),
263            "Rejected" => Ok(Self::Rejected),
264            _ => Err(crate::Error::Corrupt(format!(
265                "unknown TransferStatus: {s}"
266            ))),
267        }
268    }
269}
270
271#[derive(Debug, Clone, Copy, PartialEq, Eq)]
272pub enum SessionStatus {
273    Active,
274    Suspect,
275    Quarantined,
276    Expired,
277    Terminated,
278}
279
280impl std::fmt::Display for SessionStatus {
281    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
282        f.write_str(match self {
283            Self::Active => "Active",
284            Self::Suspect => "Suspect",
285            Self::Quarantined => "Quarantined",
286            Self::Expired => "Expired",
287            Self::Terminated => "Terminated",
288        })
289    }
290}
291
292impl std::str::FromStr for SessionStatus {
293    type Err = crate::Error;
294    fn from_str(s: &str) -> crate::Result<Self> {
295        match s {
296            "Active" => Ok(Self::Active),
297            "Suspect" => Ok(Self::Suspect),
298            "Quarantined" => Ok(Self::Quarantined),
299            "Expired" => Ok(Self::Expired),
300            "Terminated" => Ok(Self::Terminated),
301            _ => Err(crate::Error::Corrupt(format!("unknown SessionStatus: {s}"))),
302        }
303    }
304}
305
306#[derive(Debug, Clone, Copy, PartialEq, Eq)]
307pub enum QuarantineTrigger {
308    MissedHeartbeat,
309    SecurityEvent,
310    VendorAction,
311}
312
313impl std::fmt::Display for QuarantineTrigger {
314    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
315        f.write_str(match self {
316            Self::MissedHeartbeat => "MissedHeartbeat",
317            Self::SecurityEvent => "SecurityEvent",
318            Self::VendorAction => "VendorAction",
319        })
320    }
321}
322
323impl std::str::FromStr for QuarantineTrigger {
324    type Err = crate::Error;
325    fn from_str(s: &str) -> crate::Result<Self> {
326        match s {
327            "MissedHeartbeat" => Ok(Self::MissedHeartbeat),
328            "SecurityEvent" => Ok(Self::SecurityEvent),
329            "VendorAction" => Ok(Self::VendorAction),
330            _ => Err(crate::Error::Corrupt(format!(
331                "unknown QuarantineTrigger: {s}"
332            ))),
333        }
334    }
335}
336
337#[derive(Debug, Clone, Copy, PartialEq, Eq)]
338pub enum QuarantineStatus {
339    Active,
340    Resolved,
341}
342
343impl std::fmt::Display for QuarantineStatus {
344    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
345        f.write_str(match self {
346            Self::Active => "Active",
347            Self::Resolved => "Resolved",
348        })
349    }
350}
351
352impl std::str::FromStr for QuarantineStatus {
353    type Err = crate::Error;
354    fn from_str(s: &str) -> crate::Result<Self> {
355        match s {
356            "Active" => Ok(Self::Active),
357            "Resolved" => Ok(Self::Resolved),
358            _ => Err(crate::Error::Corrupt(format!(
359                "unknown QuarantineStatus: {s}"
360            ))),
361        }
362    }
363}
364
365#[derive(Debug, Clone, Copy, PartialEq, Eq)]
366pub enum SecurityEventSeverity {
367    Info,
368    Warning,
369    Critical,
370}
371
372impl std::fmt::Display for SecurityEventSeverity {
373    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
374        f.write_str(match self {
375            Self::Info => "Info",
376            Self::Warning => "Warning",
377            Self::Critical => "Critical",
378        })
379    }
380}
381
382impl std::str::FromStr for SecurityEventSeverity {
383    type Err = crate::Error;
384    fn from_str(s: &str) -> crate::Result<Self> {
385        match s {
386            "Info" => Ok(Self::Info),
387            "Warning" => Ok(Self::Warning),
388            "Critical" => Ok(Self::Critical),
389            _ => Err(crate::Error::Corrupt(format!(
390                "unknown SecurityEventSeverity: {s}"
391            ))),
392        }
393    }
394}
395
396#[derive(Debug, Clone, Copy, PartialEq, Eq)]
397pub enum SecurityEventResponse {
398    Log,
399    Warn,
400    Quarantine,
401    Terminate,
402}
403
404impl std::fmt::Display for SecurityEventResponse {
405    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
406        f.write_str(match self {
407            Self::Log => "Log",
408            Self::Warn => "Warn",
409            Self::Quarantine => "Quarantine",
410            Self::Terminate => "Terminate",
411        })
412    }
413}
414
415impl std::str::FromStr for SecurityEventResponse {
416    type Err = crate::Error;
417    fn from_str(s: &str) -> crate::Result<Self> {
418        match s {
419            "Log" => Ok(Self::Log),
420            "Warn" => Ok(Self::Warn),
421            "Quarantine" => Ok(Self::Quarantine),
422            "Terminate" => Ok(Self::Terminate),
423            _ => Err(crate::Error::Corrupt(format!(
424                "unknown SecurityEventResponse: {s}"
425            ))),
426        }
427    }
428}
429
430#[derive(Debug, Clone, Copy, PartialEq, Eq)]
431pub enum RevocationSource {
432    VendorDashboard,
433    Api,
434}
435
436impl std::fmt::Display for RevocationSource {
437    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
438        f.write_str(match self {
439            Self::VendorDashboard => "VendorDashboard",
440            Self::Api => "API",
441        })
442    }
443}
444
445impl std::str::FromStr for RevocationSource {
446    type Err = crate::Error;
447    fn from_str(s: &str) -> crate::Result<Self> {
448        match s {
449            "VendorDashboard" => Ok(Self::VendorDashboard),
450            "API" => Ok(Self::Api),
451            _ => Err(crate::Error::Corrupt(format!(
452                "unknown RevocationSource: {s}"
453            ))),
454        }
455    }
456}
457
458#[derive(Debug, Clone, Copy, PartialEq, Eq)]
459pub enum GdprBasis {
460    Contract,
461    LegalObligation,
462    LegitimateInterest,
463}
464
465impl std::fmt::Display for GdprBasis {
466    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
467        f.write_str(match self {
468            Self::Contract => "Contract",
469            Self::LegalObligation => "LegalObligation",
470            Self::LegitimateInterest => "LegitimateInterest",
471        })
472    }
473}
474
475impl std::str::FromStr for GdprBasis {
476    type Err = crate::Error;
477    fn from_str(s: &str) -> crate::Result<Self> {
478        match s {
479            "Contract" => Ok(Self::Contract),
480            "LegalObligation" => Ok(Self::LegalObligation),
481            "LegitimateInterest" => Ok(Self::LegitimateInterest),
482            _ => Err(crate::Error::Corrupt(format!("unknown GdprBasis: {s}"))),
483        }
484    }
485}
486
487#[derive(Debug, Clone, Copy, PartialEq, Eq)]
488pub enum UpgradePolicy {
489    AutoApprove,
490    RequireNewPurchase,
491    FreeUpgrade,
492}
493
494impl std::fmt::Display for UpgradePolicy {
495    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
496        f.write_str(match self {
497            Self::AutoApprove => "AutoApprove",
498            Self::RequireNewPurchase => "RequireNewPurchase",
499            Self::FreeUpgrade => "FreeUpgrade",
500        })
501    }
502}
503
504impl std::str::FromStr for UpgradePolicy {
505    type Err = crate::Error;
506    fn from_str(s: &str) -> crate::Result<Self> {
507        match s {
508            "AutoApprove" => Ok(Self::AutoApprove),
509            "RequireNewPurchase" => Ok(Self::RequireNewPurchase),
510            "FreeUpgrade" => Ok(Self::FreeUpgrade),
511            _ => Err(crate::Error::Corrupt(format!("unknown UpgradePolicy: {s}"))),
512        }
513    }
514}
515
516#[derive(Debug, Clone, Copy, PartialEq, Eq)]
517pub enum EmailType {
518    GrantConfirmation,
519}
520
521impl std::fmt::Display for EmailType {
522    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
523        f.write_str(match self {
524            Self::GrantConfirmation => "GrantConfirmation",
525        })
526    }
527}
528
529impl std::str::FromStr for EmailType {
530    type Err = crate::Error;
531    fn from_str(s: &str) -> crate::Result<Self> {
532        match s {
533            "GrantConfirmation" => Ok(Self::GrantConfirmation),
534            _ => Err(crate::Error::Corrupt(format!("unknown EmailType: {s}"))),
535        }
536    }
537}
538
539#[derive(Debug, Clone, PartialEq)]
540pub struct VendorConfig {
541    pub id: i64,
542    pub public_key: Vec<u8>,
543    pub public_key_fingerprint: String,
544    pub registered_at: i64,
545    pub rotated_from_key: Option<Vec<u8>>,
546    pub rotated_at: Option<i64>,
547}
548
549#[derive(Debug, Clone, PartialEq)]
550pub struct Product {
551    pub id: Uuid,
552    pub name: String,
553    pub description: String,
554    pub connectivity_mode: ConnectivityMode,
555    pub seat_count: i64,
556    pub expiry_policy: String,
557    pub grace_period_days: Option<i64>,
558    pub heartbeat_interval_secs: Option<i64>,
559    pub heartbeat_grace_secs: Option<i64>,
560    pub shutdown_countdown_secs: Option<i64>,
561    pub tsa_tier: TsaTier,
562    pub bundle_version: String,
563    pub transfer_policy: TransferPolicy,
564    pub pricing_amount: i64,
565    pub pricing_currency: String,
566    pub payment_provider: PaymentProvider,
567    pub min_client_version_warning: Option<String>,
568    pub min_client_version_required: Option<String>,
569    pub active: bool,
570    pub created_at: i64,
571    pub updated_at: i64,
572}
573
574#[derive(Debug, Clone, PartialEq)]
575pub struct ProductTermDeclaration {
576    pub product_id: Uuid,
577    pub warranty: String,
578    pub refund: String,
579    pub revocation: String,
580    pub expiry: String,
581    pub support_available: bool,
582    pub support_channels: String,
583    pub response_sla_hours: Option<i64>,
584    pub support_scope: Option<String>,
585    pub support_coverage: Option<String>,
586    pub updates_policy: String,
587}
588
589#[derive(Debug, Clone, PartialEq)]
590pub struct ProductTermsDocument {
591    pub id: Uuid,
592    pub product_id: Uuid,
593    pub typst_source: String,
594    pub rendered_hash: String,
595    pub validation_status: TermsValidationStatus,
596    pub validation_findings: String,
597    pub vendor_acknowledged_at: Option<i64>,
598    pub vendor_acknowledged_findings: Option<String>,
599    pub activated_at: Option<i64>,
600    pub created_at: i64,
601}
602
603#[derive(Debug, Clone, PartialEq)]
604pub struct ProductCustomerField {
605    pub id: Uuid,
606    pub product_id: Uuid,
607    pub field_key: String,
608    pub required: bool,
609    pub gdpr_basis: GdprBasis,
610}
611
612#[derive(Debug, Clone, PartialEq)]
613pub struct UpgradePolicyRow {
614    pub id: Uuid,
615    pub product_id: Uuid,
616    pub from_version: String,
617    pub to_version: String,
618    pub policy: UpgradePolicy,
619}
620
621#[derive(Debug, Clone, PartialEq)]
622pub struct Customer {
623    pub id: Uuid,
624    pub product_id: Uuid,
625    pub full_name: String,
626    pub email: String,
627    pub field_values: String,
628    pub created_at: i64,
629    pub updated_at: i64,
630}
631
632#[derive(Debug, Clone, PartialEq)]
633pub struct ConsentRecord {
634    pub id: Uuid,
635    pub customer_id: Uuid,
636    pub license_id: Uuid,
637    pub terms_document_id: Uuid,
638    pub terms_rendered_hash: String,
639    pub checkboxes_ticked: String,
640    pub accepted_at_ns: i64,
641    pub ip_address: String,
642    pub client_version: String,
643    pub protocol_version: i64,
644    pub terms_findings_shown: String,
645    pub payment_provider: PaymentProvider,
646    pub payment_provider_tier: ProviderTier,
647}
648
649#[derive(Debug, Clone, PartialEq)]
650pub struct License {
651    pub id: Uuid,
652    pub customer_id: Uuid,
653    pub product_id: Uuid,
654    pub bundle_version: String,
655    pub connectivity_mode: ConnectivityMode,
656    pub seat_count: i64,
657    pub expiry_at: Option<i64>,
658    pub status: LicenseStatus,
659    pub superseded_by: Option<Uuid>,
660    pub revoked_at: Option<i64>,
661    pub revocation_reason: Option<String>,
662    pub created_at: i64,
663    pub email_sent_at: Option<i64>,
664}
665
666#[derive(Debug, Clone, PartialEq)]
667pub struct FingerprintSeatBinding {
668    pub id: Uuid,
669    pub license_id: Uuid,
670    pub fingerprint_commitment: Vec<u8>,
671    pub seat_index: i64,
672    pub bound_at: i64,
673    pub last_verified_at: Option<i64>,
674    pub revoked_at: Option<i64>,
675    pub transfer_pending_at: Option<i64>,
676}
677
678#[derive(Debug, Clone, PartialEq)]
679pub struct IssuanceSecret {
680    pub license_id: Uuid,
681    pub secret: Vec<u8>,
682    pub created_at: i64,
683}
684
685#[derive(Debug, Clone, PartialEq)]
686pub struct PaymentTransaction {
687    pub id: Uuid,
688    pub license_id: Uuid,
689    pub provider: PaymentProvider,
690    pub provider_transaction_id: String,
691    pub amount: i64,
692    pub currency: String,
693    pub provider_tier: ProviderTier,
694    pub test_mode: bool,
695    pub status: PaymentStatus,
696    pub created_at: i64,
697    pub confirmed_at: Option<i64>,
698}
699
700#[derive(Debug, Clone, PartialEq)]
701pub struct TransferRequest {
702    pub id: Uuid,
703    pub license_id: Uuid,
704    pub old_fingerprint_commitment: Vec<u8>,
705    pub new_fingerprint_commitment: Vec<u8>,
706    pub requested_at: i64,
707    pub status: TransferStatus,
708    pub vendor_note: Option<String>,
709    pub resolved_at: Option<i64>,
710}
711
712#[derive(Debug, Clone, PartialEq)]
713pub struct ActiveSession {
714    pub id: Uuid,
715    pub binding_id: Uuid,
716    pub ephemeral_pubkey: Vec<u8>,
717    pub issued_at: i64,
718    pub expires_at: i64,
719    pub last_heartbeat_at: Option<i64>,
720    pub seq_no: i64,
721    pub status: SessionStatus,
722}
723
724#[derive(Debug, Clone, PartialEq)]
725pub struct QuarantineCase {
726    pub id: Uuid,
727    pub case_id: Uuid,
728    pub binding_id: Uuid,
729    pub session_id: Option<Uuid>,
730    pub trigger: QuarantineTrigger,
731    pub triggered_at: i64,
732    pub status: QuarantineStatus,
733    pub resolution: Option<String>,
734    pub resolved_at: Option<i64>,
735    pub vendor_note: Option<String>,
736}
737
738#[derive(Debug, Clone, PartialEq)]
739pub struct SecurityEvent {
740    pub id: i64,
741    pub event_id: Uuid,
742    pub license_id: Uuid,
743    pub binding_id: Uuid,
744    pub session_id: Option<Uuid>,
745    pub occurred_at_ns: i64,
746    pub received_at_ns: i64,
747    pub event_type: String,
748    pub severity: SecurityEventSeverity,
749    pub payload: String,
750    pub response: SecurityEventResponse,
751    pub reviewed_by: Option<String>,
752    pub reviewed_at: Option<i64>,
753    pub case_id: Option<Uuid>,
754}
755
756#[derive(Debug, Clone, PartialEq)]
757pub struct RevocationRecord {
758    pub license_id: Uuid,
759    pub revoked_at: i64,
760    pub revoked_by: RevocationSource,
761    pub reason: Option<String>,
762}
763
764#[derive(Debug, Clone, PartialEq)]
765pub struct EmailLogEntry {
766    pub id: Uuid,
767    pub license_id: Uuid,
768    pub email_type: EmailType,
769    pub sent_to: String,
770    pub sent_at: i64,
771    pub success: bool,
772    pub error_message: Option<String>,
773}
774
775#[derive(Debug, Clone, Copy, PartialEq, Eq)]
776pub enum EnrollmentState {
777    OfferPending,
778    ReceiptPending,
779    PaymentHeld,
780    TSAPending,
781    GrantReady,
782    Issued,
783    Abandoned,
784}
785
786impl std::fmt::Display for EnrollmentState {
787    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
788        f.write_str(match self {
789            Self::OfferPending => "OfferPending",
790            Self::ReceiptPending => "ReceiptPending",
791            Self::PaymentHeld => "PaymentHeld",
792            Self::TSAPending => "TSAPending",
793            Self::GrantReady => "GrantReady",
794            Self::Issued => "Issued",
795            Self::Abandoned => "Abandoned",
796        })
797    }
798}
799
800impl std::str::FromStr for EnrollmentState {
801    type Err = crate::Error;
802    fn from_str(s: &str) -> crate::Result<Self> {
803        match s {
804            "OfferPending" => Ok(Self::OfferPending),
805            "ReceiptPending" => Ok(Self::ReceiptPending),
806            "PaymentHeld" => Ok(Self::PaymentHeld),
807            "TSAPending" => Ok(Self::TSAPending),
808            "GrantReady" => Ok(Self::GrantReady),
809            "Issued" => Ok(Self::Issued),
810            "Abandoned" => Ok(Self::Abandoned),
811            _ => Err(crate::Error::Corrupt(format!(
812                "unknown EnrollmentState: {s}"
813            ))),
814        }
815    }
816}
817
818#[derive(Debug, Clone, PartialEq)]
819pub struct EnrollmentSession {
820    pub id: Uuid,
821    pub product_id: Uuid,
822    pub fingerprint_commitment: Vec<u8>,
823    pub customer_pubkey: Vec<u8>,
824    pub client_version: String,
825    pub protocol_version: i64,
826    pub state: EnrollmentState,
827    pub offer_nonce: Option<Vec<u8>>,
828    pub offer_expires_at: Option<i64>,
829    pub terms_document_id: Option<Uuid>,
830    pub request_bytes: Vec<u8>,
831    pub offer_bytes: Option<Vec<u8>>,
832    pub receipt_bytes: Option<Vec<u8>>,
833    pub payment_intent_id: Option<String>,
834    pub payment_captured: bool,
835    pub grant_bytes: Option<Vec<u8>>,
836    pub transfer_request_id: Option<Uuid>,
837    pub license_id: Option<Uuid>,
838    pub abandon_reason: Option<String>,
839    pub created_at: i64,
840    pub updated_at: i64,
841}
842
843#[derive(Default)]
844pub struct EnrollmentSessionUpdate {
845    pub state: Option<EnrollmentState>,
846    pub receipt_bytes: Option<Vec<u8>>,
847    pub payment_intent_id: Option<String>,
848    pub payment_captured: Option<bool>,
849    pub grant_bytes: Option<Vec<u8>>,
850    pub license_id: Option<Option<Uuid>>,
851    pub abandon_reason: Option<String>,
852    pub updated_at: i64,
853}
854
855pub mod abandon_reason {
856    pub const OFFER_EXPIRED: &str = "OfferExpired";
857    pub const PAYMENT_FAILED: &str = "PaymentFailed";
858    pub const TSA_FAILED: &str = "TsaFailed";
859    pub const CAPTURE_FAILED: &str = "CaptureFailed";
860}