Skip to main content

adk_payments/domain/
intervention.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4use crate::domain::{CommerceActor, ProtocolExtensions};
5
6/// Canonical intervention classes shared across protocols.
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "snake_case")]
9pub enum InterventionKind {
10    ThreeDsChallenge,
11    BiometricConfirmation,
12    AddressVerification,
13    BuyerReconfirmation,
14    MerchantReview,
15    Other(String),
16}
17
18/// Canonical intervention lifecycle state.
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(rename_all = "snake_case")]
21pub enum InterventionStatus {
22    Pending,
23    InProgress,
24    Satisfied,
25    Expired,
26    Failed,
27    Cancelled,
28}
29
30impl InterventionStatus {
31    /// Returns `true` when no further continuation is expected.
32    #[must_use]
33    pub fn is_terminal(self) -> bool {
34        matches!(self, Self::Satisfied | Self::Expired | Self::Failed | Self::Cancelled)
35    }
36}
37
38/// Canonical intervention details preserved in transaction state.
39#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub struct InterventionState {
42    pub intervention_id: String,
43    pub kind: InterventionKind,
44    pub status: InterventionStatus,
45    #[serde(default, skip_serializing_if = "Option::is_none")]
46    pub instructions: Option<String>,
47    #[serde(default, skip_serializing_if = "Option::is_none")]
48    pub continuation_token: Option<String>,
49    #[serde(default, skip_serializing_if = "Option::is_none")]
50    pub requested_by: Option<CommerceActor>,
51    #[serde(default, skip_serializing_if = "Option::is_none")]
52    pub expires_at: Option<DateTime<Utc>>,
53    #[serde(default, skip_serializing_if = "ProtocolExtensions::is_empty")]
54    pub extensions: ProtocolExtensions,
55}