Skip to main content

bucketwarden_server/
replication_strategy_support.rs

1use super::*;
2
3pub const REPLICATION_STRATEGY_ASYNC_ACTIVE_PASSIVE: &str = "async-active-passive";
4pub const REPLICATION_STRATEGY_SYNCHRONOUS: &str = "synchronous";
5pub const REPLICATION_STRATEGY_QUORUM: &str = "quorum";
6pub const REPLICATION_STRATEGY_ACTIVE_ACTIVE: &str = "active-active";
7
8const REPLICATION_STRATEGY_CAPABILITIES: &[&str] = &[
9    "native-support-state",
10    "semantic-parity",
11    "configuration-admin-surface",
12    "security-governance-impact",
13    "observability-evidence",
14    "failure-mode-behavior",
15    "validation-test-coverage",
16    "product-specific-caveats",
17];
18
19const REPLICATION_STRATEGY_CAVEATS: &[&str] = &[
20    "BucketWarden supports explicit asynchronous active-passive replication runs.",
21    "Replication preserves version identity, delete markers, Object Lock state, encryption metadata, and audit-relevant state.",
22    "Synchronous, quorum, and active-active strategies are tracked but fail closed outside the current runtime boundary.",
23];
24
25const REPLICATION_STRATEGY_FAILURE_MODES: &[&str] = &[
26    "unsupported-strategy-rejected",
27    "missing-destination-skipped",
28    "encrypted-object-skipped-when-disabled",
29    "replication-lag-visible-as-pending",
30];
31
32#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
33pub struct ReplicationStrategySupportEntry {
34    pub strategy: &'static str,
35    pub native_support: bool,
36    pub semantic_parity: &'static str,
37    pub failure_mode: &'static str,
38    pub caveat: &'static str,
39}
40
41#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
42pub struct ReplicationStrategySupportReport {
43    pub active_strategy: &'static str,
44    pub supported_strategies: Vec<&'static str>,
45    pub unsupported_strategies: Vec<&'static str>,
46    pub capabilities: Vec<&'static str>,
47    pub failure_modes: Vec<&'static str>,
48    pub caveats: Vec<&'static str>,
49    pub entries: Vec<ReplicationStrategySupportEntry>,
50}
51
52impl BucketWarden {
53    pub fn replication_strategy_support_report(&self) -> ReplicationStrategySupportReport {
54        ReplicationStrategySupportReport {
55            active_strategy: REPLICATION_STRATEGY_ASYNC_ACTIVE_PASSIVE,
56            supported_strategies: vec![REPLICATION_STRATEGY_ASYNC_ACTIVE_PASSIVE],
57            unsupported_strategies: vec![
58                REPLICATION_STRATEGY_SYNCHRONOUS,
59                REPLICATION_STRATEGY_QUORUM,
60                REPLICATION_STRATEGY_ACTIVE_ACTIVE,
61            ],
62            capabilities: REPLICATION_STRATEGY_CAPABILITIES.to_vec(),
63            failure_modes: REPLICATION_STRATEGY_FAILURE_MODES.to_vec(),
64            caveats: REPLICATION_STRATEGY_CAVEATS.to_vec(),
65            entries: vec![
66                ReplicationStrategySupportEntry {
67                    strategy: REPLICATION_STRATEGY_ASYNC_ACTIVE_PASSIVE,
68                    native_support: true,
69                    semantic_parity: "Explicit operator-triggered active-passive replication over BucketWarden object versions.",
70                    failure_mode: "Lag is visible as PENDING or MISSING_DESTINATION until an operator run completes.",
71                    caveat: "Replication is deterministic runtime replay, not an AWS cross-region replication SLA.",
72                },
73                ReplicationStrategySupportEntry {
74                    strategy: REPLICATION_STRATEGY_SYNCHRONOUS,
75                    native_support: false,
76                    semantic_parity: "No write-acknowledged synchronous replica commit semantics are claimed.",
77                    failure_mode: "Synchronous strategy selection is rejected as unsupported.",
78                    caveat: "Synchronous replication needs a consensus or two-phase commit boundary before support.",
79                },
80                ReplicationStrategySupportEntry {
81                    strategy: REPLICATION_STRATEGY_QUORUM,
82                    native_support: false,
83                    semantic_parity: "No quorum write, read repair, or replica voting semantics are claimed.",
84                    failure_mode: "Quorum strategy selection is rejected as unsupported.",
85                    caveat: "Quorum replication requires distributed placement and failure-domain decisions.",
86                },
87                ReplicationStrategySupportEntry {
88                    strategy: REPLICATION_STRATEGY_ACTIVE_ACTIVE,
89                    native_support: false,
90                    semantic_parity: "No multi-writer conflict resolution or split-brain semantics are claimed.",
91                    failure_mode: "Active-active strategy selection is rejected as unsupported.",
92                    caveat: "Active-active replication requires explicit conflict semantics before support.",
93                },
94            ],
95        }
96    }
97
98    pub fn ensure_replication_strategy_supported(
99        &self,
100        strategy: &str,
101    ) -> Result<(), RuntimeError> {
102        let report = self.replication_strategy_support_report();
103        if report.supported_strategies.contains(&strategy) {
104            Ok(())
105        } else {
106            Err(RuntimeError::UnsupportedReplicationStrategy(
107                strategy.to_string(),
108            ))
109        }
110    }
111}