cloud-sdk 0.85.0

no_std-first provider-neutral cloud SDK foundations.
Documentation
use super::{PlanConfirmation, PlanFingerprintBuildError, PlanFingerprintRef, PlanSubject};
use crate::operation::{CostIntent, OperationImpact, PermitScope, PlanChange, ReplayPolicy};

pub(super) fn validate<E>(
    plan: &PlanConfirmation<'_, '_>,
    authorization_evidence_supplied: bool,
) -> Result<PermitScope, PlanFingerprintBuildError<E>> {
    if plan.prepared.authorization_evidence_required() && !authorization_evidence_supplied {
        return Err(PlanFingerprintBuildError::AuthorizationEvidenceRequired);
    }
    if plan.prepared.operation_id().is_none() {
        return Err(PlanFingerprintBuildError::MissingOperationId);
    }
    if !plan
        .prepared
        .service()
        .endpoint_policy()
        .admits(plan.endpoint)
    {
        return Err(PlanFingerprintBuildError::EndpointNotAdmitted);
    }
    if plan.change == PlanChange::NoOp {
        return Err(PlanFingerprintBuildError::NoOp);
    }
    plan.account
        .bytes()
        .map_err(PlanFingerprintBuildError::Context)?;
    plan.tenant
        .bytes()
        .map_err(PlanFingerprintBuildError::Context)?;
    let metadata = plan.prepared.metadata();
    let scope = match (metadata.cost_intent(), metadata.impact()) {
        (CostIntent::MayIncurCost, _) => PermitScope::Cost,
        (_, OperationImpact::Destructive) => PermitScope::Destructive,
        (_, OperationImpact::Mutation) => PermitScope::Mutation,
        (_, OperationImpact::ReadOnly) => return Err(PlanFingerprintBuildError::ReadOnlyOperation),
    };
    match (scope, plan.cost) {
        (PermitScope::Cost, None) => return Err(PlanFingerprintBuildError::MissingCost),
        (PermitScope::Mutation | PermitScope::Destructive, Some(_)) => {
            return Err(PlanFingerprintBuildError::UnexpectedCost);
        }
        _ => {}
    }
    match (plan.replay, plan.attempts.get(), plan.idempotency) {
        (ReplayPolicy::SingleAttempt, 1, None)
        | (ReplayPolicy::RecoverNotSent, _, None)
        | (ReplayPolicy::ReconcileThenRetry, _, Some(_)) => {}
        (ReplayPolicy::SingleAttempt, _, _) => {
            return Err(PlanFingerprintBuildError::InvalidSingleAttemptBudget);
        }
        (ReplayPolicy::ReconcileThenRetry, _, None) => {
            return Err(PlanFingerprintBuildError::MissingIdempotency);
        }
        (_, _, Some(_)) => return Err(PlanFingerprintBuildError::UnexpectedIdempotency),
    }
    Ok(scope)
}

pub(super) fn subject<'request, 'plan: 'fingerprint, 'fingerprint>(
    plan: &'fingerprint PlanConfirmation<'plan, 'request>,
    scope: PermitScope,
    fingerprint: PlanFingerprintRef<'fingerprint>,
) -> PlanSubject<'request, 'fingerprint> {
    PlanSubject {
        prepared: &plan.prepared,
        fingerprint,
        endpoint: plan.endpoint,
        scope,
        validity: plan.validity,
        replay: plan.replay,
        attempts: plan.attempts,
        idempotency: plan.idempotency,
    }
}