1use super::*;
2
3pub const CONSISTENCY_MODEL_STRONG_LOCAL: &str = "strong-local";
4pub const CONSISTENCY_MODEL_EVENTUAL: &str = "eventual";
5pub const CONSISTENCY_MODEL_SESSION: &str = "session";
6pub const CONSISTENCY_MODEL_BOUNDED_STALENESS: &str = "bounded-staleness";
7
8const CONSISTENCY_MODEL_CAPABILITIES: &[&str] = &[
9 "read-after-write-consistency",
10 "list-consistency",
11 "overwrite-consistency",
12 "delete-consistency",
13 "metadata-consistency",
14 "native-support-state",
15 "semantic-parity",
16 "configuration-admin-surface",
17 "security-governance-impact",
18 "observability-evidence",
19 "failure-mode-behavior",
20 "validation-test-coverage",
21 "product-specific-caveats",
22];
23
24const CONSISTENCY_MODEL_CAVEATS: &[&str] = &[
25 "BucketWarden supports strong local consistency inside a single runtime state authority.",
26 "Reads, heads, lists, overwrites, deletes, and metadata reads observe committed local object state immediately.",
27 "Eventual, session, and bounded-staleness consistency modes are tracked but fail closed outside the current runtime boundary.",
28 "Strong local consistency does not claim distributed consensus, cross-region ordering, or multi-writer conflict semantics.",
29];
30
31const CONSISTENCY_MODEL_FAILURE_MODES: &[&str] = &[
32 "unsupported-consistency-model-rejected",
33 "invalid-consistency-policy-rejected",
34 "stale-read-mode-rejected",
35 "cross-region-consistency-out-of-bounds",
36];
37
38#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
39pub struct ConsistencyModelSupportEntry {
40 pub model: &'static str,
41 pub native_support: bool,
42 pub semantic_parity: &'static str,
43 pub read_after_write: bool,
44 pub list_consistency: bool,
45 pub overwrite_consistency: bool,
46 pub delete_consistency: bool,
47 pub metadata_consistency: bool,
48 pub failure_mode: &'static str,
49 pub caveat: &'static str,
50}
51
52#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
53pub struct ConsistencyModelSupportReport {
54 pub active_model: &'static str,
55 pub supported_models: Vec<&'static str>,
56 pub unsupported_models: Vec<&'static str>,
57 pub capabilities: Vec<&'static str>,
58 pub failure_modes: Vec<&'static str>,
59 pub caveats: Vec<&'static str>,
60 pub entries: Vec<ConsistencyModelSupportEntry>,
61}
62
63#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
64pub struct ConsistencyPolicy {
65 pub model: String,
66 pub stale_reads_allowed: bool,
67 pub cross_region_ordering: bool,
68}
69
70impl BucketWarden {
71 pub fn consistency_model_support_report(&self) -> ConsistencyModelSupportReport {
72 ConsistencyModelSupportReport {
73 active_model: CONSISTENCY_MODEL_STRONG_LOCAL,
74 supported_models: vec![CONSISTENCY_MODEL_STRONG_LOCAL],
75 unsupported_models: vec![
76 CONSISTENCY_MODEL_EVENTUAL,
77 CONSISTENCY_MODEL_SESSION,
78 CONSISTENCY_MODEL_BOUNDED_STALENESS,
79 ],
80 capabilities: CONSISTENCY_MODEL_CAPABILITIES.to_vec(),
81 failure_modes: CONSISTENCY_MODEL_FAILURE_MODES.to_vec(),
82 caveats: CONSISTENCY_MODEL_CAVEATS.to_vec(),
83 entries: vec![
84 ConsistencyModelSupportEntry {
85 model: CONSISTENCY_MODEL_STRONG_LOCAL,
86 native_support: true,
87 semantic_parity: "Single runtime state authority provides immediate visibility for committed object mutations.",
88 read_after_write: true,
89 list_consistency: true,
90 overwrite_consistency: true,
91 delete_consistency: true,
92 metadata_consistency: true,
93 failure_mode: "Invalid stale-read or cross-region policy is rejected.",
94 caveat: "Strong local consistency is scoped to the local runtime and persisted snapshot/store boundary.",
95 },
96 ConsistencyModelSupportEntry {
97 model: CONSISTENCY_MODEL_EVENTUAL,
98 native_support: false,
99 semantic_parity: "No delayed visibility or convergence-window semantics are claimed.",
100 read_after_write: false,
101 list_consistency: false,
102 overwrite_consistency: false,
103 delete_consistency: false,
104 metadata_consistency: false,
105 failure_mode: "Eventual consistency model selection is rejected as unsupported.",
106 caveat: "Eventual consistency requires explicit replication lag and convergence semantics.",
107 },
108 ConsistencyModelSupportEntry {
109 model: CONSISTENCY_MODEL_SESSION,
110 native_support: false,
111 semantic_parity: "No per-session read-your-writes token or causal session semantics are claimed.",
112 read_after_write: false,
113 list_consistency: false,
114 overwrite_consistency: false,
115 delete_consistency: false,
116 metadata_consistency: false,
117 failure_mode: "Session consistency model selection is rejected as unsupported.",
118 caveat: "Session consistency needs session-bound causal metadata before support.",
119 },
120 ConsistencyModelSupportEntry {
121 model: CONSISTENCY_MODEL_BOUNDED_STALENESS,
122 native_support: false,
123 semantic_parity: "No bounded stale read window, version lag, or timestamp lag semantics are claimed.",
124 read_after_write: false,
125 list_consistency: false,
126 overwrite_consistency: false,
127 delete_consistency: false,
128 metadata_consistency: false,
129 failure_mode: "Bounded-staleness consistency model selection is rejected as unsupported.",
130 caveat: "Bounded staleness needs explicit clock and replica lag contracts before support.",
131 },
132 ],
133 }
134 }
135
136 pub fn ensure_consistency_model_supported(&self, model: &str) -> Result<(), RuntimeError> {
137 let report = self.consistency_model_support_report();
138 if report.supported_models.contains(&model) {
139 Ok(())
140 } else {
141 Err(RuntimeError::UnsupportedConsistencyModel(model.to_string()))
142 }
143 }
144
145 pub fn validate_consistency_policy(
146 &self,
147 policy: &ConsistencyPolicy,
148 ) -> Result<(), RuntimeError> {
149 self.ensure_consistency_model_supported(&policy.model)?;
150 if policy.stale_reads_allowed {
151 return Err(RuntimeError::InvalidConsistencyPolicy(
152 "strong local consistency rejects stale-read mode".to_string(),
153 ));
154 }
155 if policy.cross_region_ordering {
156 return Err(RuntimeError::InvalidConsistencyPolicy(
157 "cross-region ordering is outside the current consistency boundary".to_string(),
158 ));
159 }
160 Ok(())
161 }
162}