1use super::*;
2
3pub const LARGE_OBJECT_MODE_MULTIPART: &str = "multipart-large-object";
4pub const LARGE_OBJECT_MODE_STRIPED: &str = "striped-large-object";
5pub const LARGE_OBJECT_MODE_PARALLEL_READ: &str = "parallel-read-large-object";
6pub const LARGE_OBJECT_MODE_PARALLEL_WRITE: &str = "parallel-write-large-object";
7
8pub const LARGE_OBJECT_MULTIPART_THRESHOLD_BYTES: usize = 5 * 1024 * 1024;
9
10const LARGE_OBJECT_CAPABILITIES: &[&str] = &[
11 "multipart-throughput",
12 "striping",
13 "parallel-reads",
14 "parallel-writes",
15 "range-read-behavior",
16 "native-support-state",
17 "semantic-parity",
18 "configuration-admin-surface",
19 "security-governance-impact",
20 "observability-evidence",
21 "failure-mode-behavior",
22 "validation-test-coverage",
23 "product-specific-caveats",
24];
25
26const LARGE_OBJECT_CAVEATS: &[&str] = &[
27 "BucketWarden supports multipart upload, part listing, multipart completion, copy-source ranges, HTTP range reads, integrity, encryption, audit, and notification semantics under the local runtime boundary.",
28 "Large-object multipart support is semantically validated, but no storage-engine throughput SLO or benchmark-backed numeric performance claim is made.",
29 "Striping, parallel read scheduling, and parallel write scheduling are tracked but fail closed until a durable scheduler and placement contract exist.",
30 "Large-object proof does not claim distributed striping, concurrent IO fanout, adaptive chunk sizing, or p95/p99 throughput targets.",
31];
32
33const LARGE_OBJECT_FAILURE_MODES: &[&str] = &[
34 "unsupported-large-object-mode-rejected",
35 "striped-large-object-mode-rejected",
36 "parallel-read-mode-rejected",
37 "parallel-write-mode-rejected",
38 "invalid-large-object-threshold-rejected",
39];
40
41#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
42pub struct LargeObjectOptimizationEntry {
43 pub mode: &'static str,
44 pub native_support: bool,
45 pub semantic_parity: &'static str,
46 pub storage_behavior: &'static str,
47 pub throughput_behavior: &'static str,
48 pub failure_mode: &'static str,
49 pub caveat: &'static str,
50}
51
52#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
53pub struct LargeObjectOptimizationReport {
54 pub active_mode: &'static str,
55 pub multipart_threshold_bytes: usize,
56 pub supported_modes: Vec<&'static str>,
57 pub unsupported_modes: Vec<&'static str>,
58 pub capabilities: Vec<&'static str>,
59 pub failure_modes: Vec<&'static str>,
60 pub caveats: Vec<&'static str>,
61 pub entries: Vec<LargeObjectOptimizationEntry>,
62}
63
64#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
65pub struct LargeObjectOptimizationPolicy {
66 pub mode: String,
67 pub multipart_threshold_bytes: Option<usize>,
68 pub enable_striping: bool,
69 pub enable_parallel_reads: bool,
70 pub enable_parallel_writes: bool,
71 pub throughput_slo_bytes_per_second: Option<u64>,
72}
73
74impl BucketWarden {
75 pub fn large_object_optimization_report(&self) -> LargeObjectOptimizationReport {
76 LargeObjectOptimizationReport {
77 active_mode: LARGE_OBJECT_MODE_MULTIPART,
78 multipart_threshold_bytes: LARGE_OBJECT_MULTIPART_THRESHOLD_BYTES,
79 supported_modes: vec![LARGE_OBJECT_MODE_MULTIPART],
80 unsupported_modes: vec![
81 LARGE_OBJECT_MODE_STRIPED,
82 LARGE_OBJECT_MODE_PARALLEL_READ,
83 LARGE_OBJECT_MODE_PARALLEL_WRITE,
84 ],
85 capabilities: LARGE_OBJECT_CAPABILITIES.to_vec(),
86 failure_modes: LARGE_OBJECT_FAILURE_MODES.to_vec(),
87 caveats: LARGE_OBJECT_CAVEATS.to_vec(),
88 entries: vec![
89 LargeObjectOptimizationEntry {
90 mode: LARGE_OBJECT_MODE_MULTIPART,
91 native_support: true,
92 semantic_parity: "Multipart uploads, ordered part completion, part checksums, version creation, encryption, lock defaults, audit, notifications, and range reads preserve the same object semantics as single PUT objects.",
93 storage_behavior: "Completed multipart objects are stored as committed object versions with multipart integrity records.",
94 throughput_behavior: "Multipart part ingestion and range reads are supported as protocol/runtime behavior; no benchmark-backed throughput SLO is claimed.",
95 failure_mode: "Invalid threshold or unsupported optimization policy is rejected before claiming support.",
96 caveat: "Multipart proof does not claim distributed striping or concurrent IO fanout.",
97 },
98 LargeObjectOptimizationEntry {
99 mode: LARGE_OBJECT_MODE_STRIPED,
100 native_support: false,
101 semantic_parity: "No stripe placement, stripe index, or stripe recovery semantics are claimed.",
102 storage_behavior: "Striped large-object storage is out of the current runtime boundary.",
103 throughput_behavior: "Striping-related throughput improvement is not claimed.",
104 failure_mode: "Striped large-object mode selection is rejected as unsupported.",
105 caveat: "Striping needs durable placement, repair, recovery, and integrity contracts.",
106 },
107 LargeObjectOptimizationEntry {
108 mode: LARGE_OBJECT_MODE_PARALLEL_READ,
109 native_support: false,
110 semantic_parity: "No parallel range scheduler or fanout read semantics are claimed.",
111 storage_behavior: "Parallel read scheduling is out of the current runtime boundary.",
112 throughput_behavior: "Parallel read throughput improvement is not claimed.",
113 failure_mode: "Parallel read mode selection is rejected as unsupported.",
114 caveat: "Parallel reads need scheduler, cancellation, ordering, and observability proof.",
115 },
116 LargeObjectOptimizationEntry {
117 mode: LARGE_OBJECT_MODE_PARALLEL_WRITE,
118 native_support: false,
119 semantic_parity: "No parallel write scheduler or fanout write commit semantics are claimed.",
120 storage_behavior: "Parallel write scheduling is out of the current runtime boundary.",
121 throughput_behavior: "Parallel write throughput improvement is not claimed.",
122 failure_mode: "Parallel write mode selection is rejected as unsupported.",
123 caveat: "Parallel writes need atomic multi-part scheduling and failure recovery proof.",
124 },
125 ],
126 }
127 }
128
129 pub fn is_large_object(&self, body_len: usize) -> bool {
130 body_len >= LARGE_OBJECT_MULTIPART_THRESHOLD_BYTES
131 }
132
133 pub fn ensure_large_object_mode_supported(&self, mode: &str) -> Result<(), RuntimeError> {
134 let report = self.large_object_optimization_report();
135 if report.supported_modes.contains(&mode) {
136 Ok(())
137 } else {
138 Err(RuntimeError::UnsupportedLargeObjectOptimization(
139 mode.to_string(),
140 ))
141 }
142 }
143
144 pub fn validate_large_object_optimization_policy(
145 &self,
146 policy: &LargeObjectOptimizationPolicy,
147 ) -> Result<(), RuntimeError> {
148 self.ensure_large_object_mode_supported(&policy.mode)?;
149 if policy
150 .multipart_threshold_bytes
151 .is_some_and(|threshold| threshold == 0)
152 {
153 return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
154 "large-object multipart threshold must be nonzero".to_string(),
155 ));
156 }
157 if policy.enable_striping {
158 return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
159 "large-object striping is outside the current boundary".to_string(),
160 ));
161 }
162 if policy.enable_parallel_reads {
163 return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
164 "parallel large-object reads are outside the current boundary".to_string(),
165 ));
166 }
167 if policy.enable_parallel_writes {
168 return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
169 "parallel large-object writes are outside the current boundary".to_string(),
170 ));
171 }
172 if policy.throughput_slo_bytes_per_second.is_some() {
173 return Err(RuntimeError::InvalidLargeObjectOptimizationPolicy(
174 "numeric large-object throughput SLOs require benchmark evidence".to_string(),
175 ));
176 }
177 Ok(())
178 }
179}