bucketwarden_server/
replication_strategy_support.rs1use 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}