Skip to main content

adk_payments/auth/
error.rs

1use adk_auth::AuthError;
2use adk_core::{AdkError, ErrorCategory, ErrorComponent};
3use thiserror::Error;
4
5use super::scopes::PaymentOperation;
6
7/// Local payment-auth errors mapped into the ADK structured error envelope.
8#[derive(Debug, Error)]
9pub enum PaymentsAuthError {
10    #[error(
11        "payment operation `{operation}` is missing required scopes {missing:?} (requires {required:?}). Grant the missing scopes before retrying the payment mutation."
12    )]
13    MissingScopes { operation: PaymentOperation, required: Vec<String>, missing: Vec<String> },
14
15    #[error(
16        "authenticated request value `{actual}` conflicts with transaction `{transaction_id}` binding `{binding}` expected `{expected}`. Reuse the original transaction identity instead of rebinding it implicitly."
17    )]
18    IdentityConflict {
19        transaction_id: String,
20        binding: &'static str,
21        expected: String,
22        actual: String,
23    },
24
25    #[error(
26        "failed to emit a payment audit event: {0}. Restore the configured audit sink before retrying the sensitive payment action."
27    )]
28    AuditSink(#[from] AuthError),
29}
30
31impl From<PaymentsAuthError> for AdkError {
32    fn from(value: PaymentsAuthError) -> Self {
33        match value {
34            PaymentsAuthError::MissingScopes { .. } => AdkError::new(
35                ErrorComponent::Auth,
36                ErrorCategory::Forbidden,
37                "payments.auth.scope_denied",
38                value.to_string(),
39            ),
40            PaymentsAuthError::IdentityConflict { .. } => AdkError::new(
41                ErrorComponent::Auth,
42                ErrorCategory::Forbidden,
43                "payments.auth.identity_conflict",
44                value.to_string(),
45            ),
46            PaymentsAuthError::AuditSink(err) => AdkError::new(
47                ErrorComponent::Auth,
48                ErrorCategory::Internal,
49                "payments.auth.audit_failed",
50                err.to_string(),
51            )
52            .with_source(err),
53        }
54    }
55}