use super::*;
pub const OBJECT_LAYOUT_WHOLE_OBJECT: &str = "whole-object";
pub const OBJECT_LAYOUT_CHUNKED: &str = "chunked";
pub const OBJECT_LAYOUT_STRIPED: &str = "striped";
pub const OBJECT_LAYOUT_PACKED_SMALL_OBJECTS: &str = "packed-small-objects";
pub const OBJECT_LAYOUT_APPEND_ONLY_SEGMENTS: &str = "append-only-segments";
const OBJECT_LAYOUT_CAPABILITIES: &[&str] = &[
"whole-object-layout",
"chunked-layout",
"striped-layout",
"packed-small-objects",
"append-only-segments",
"native-support-state",
"semantic-parity",
"configuration-admin-surface",
"security-governance-impact",
"observability-evidence",
"failure-mode-behavior",
"validation-test-coverage",
"product-specific-caveats",
];
const OBJECT_LAYOUT_CAVEATS: &[&str] = &[
"BucketWarden supports whole-object committed versions and multipart chunk assembly for the local runtime boundary.",
"Chunked layout proof is the S3 multipart path: ordered parts are assembled atomically into one committed object version.",
"Striped layout, packed small-object containers, and append-only segment stores are tracked but fail closed until they have runtime semantics.",
"Object layout proof does not claim distributed striping, small-object packing compaction, or log-segment garbage collection.",
];
const OBJECT_LAYOUT_FAILURE_MODES: &[&str] = &[
"unsupported-object-layout-rejected",
"invalid-chunk-size-rejected",
"striped-layout-policy-rejected",
"packed-small-object-policy-rejected",
"append-only-segment-policy-rejected",
];
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct ObjectLayoutSupportEntry {
pub layout: &'static str,
pub native_support: bool,
pub semantic_parity: &'static str,
pub write_path: &'static str,
pub read_path: &'static str,
pub failure_mode: &'static str,
pub caveat: &'static str,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct ObjectLayoutSupportReport {
pub active_layout: &'static str,
pub supported_layouts: Vec<&'static str>,
pub unsupported_layouts: Vec<&'static str>,
pub default_chunk_policy: &'static str,
pub capabilities: Vec<&'static str>,
pub failure_modes: Vec<&'static str>,
pub caveats: Vec<&'static str>,
pub entries: Vec<ObjectLayoutSupportEntry>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
pub struct ObjectLayoutPolicy {
pub layout: String,
pub chunk_size_bytes: Option<usize>,
pub stripe_width: Option<u8>,
pub pack_small_objects: bool,
pub append_only_segments: bool,
}
impl BucketWarden {
pub fn object_layout_support_report(&self) -> ObjectLayoutSupportReport {
ObjectLayoutSupportReport {
active_layout: OBJECT_LAYOUT_WHOLE_OBJECT,
supported_layouts: vec![OBJECT_LAYOUT_WHOLE_OBJECT, OBJECT_LAYOUT_CHUNKED],
unsupported_layouts: vec![
OBJECT_LAYOUT_STRIPED,
OBJECT_LAYOUT_PACKED_SMALL_OBJECTS,
OBJECT_LAYOUT_APPEND_ONLY_SEGMENTS,
],
default_chunk_policy: "multipart-ordered-part-assembly",
capabilities: OBJECT_LAYOUT_CAPABILITIES.to_vec(),
failure_modes: OBJECT_LAYOUT_FAILURE_MODES.to_vec(),
caveats: OBJECT_LAYOUT_CAVEATS.to_vec(),
entries: vec![
ObjectLayoutSupportEntry {
layout: OBJECT_LAYOUT_WHOLE_OBJECT,
native_support: true,
semantic_parity: "Single PUT writes one committed object version with body, metadata, lock, and encryption envelope.",
write_path: "put_object commits the full object body atomically as one visible version.",
read_path: "get_object and range reads return the committed whole-object bytes.",
failure_mode: "Invalid object keys, digest mismatches, and lock conflicts reject before commit.",
caveat: "Whole-object layout is local runtime behavior and does not claim remote block placement.",
},
ObjectLayoutSupportEntry {
layout: OBJECT_LAYOUT_CHUNKED,
native_support: true,
semantic_parity: "Multipart uploads preserve ordered chunks and commit them into one visible object version.",
write_path: "create_multipart_upload, upload_part, and complete_multipart_upload assemble ordered parts.",
read_path: "reads observe the assembled object body after multipart completion.",
failure_mode: "Missing parts, invalid part numbers, and ETag mismatches reject completion.",
caveat: "Chunked support is S3 multipart assembly, not distributed chunk placement.",
},
ObjectLayoutSupportEntry {
layout: OBJECT_LAYOUT_STRIPED,
native_support: false,
semantic_parity: "No cross-disk or cross-node stripe placement semantics are claimed.",
write_path: "striped writes are out of the current runtime boundary.",
read_path: "striped reads are out of the current runtime boundary.",
failure_mode: "Striped layout selection is rejected as unsupported.",
caveat: "Striping needs explicit shard placement and reconstruction contracts.",
},
ObjectLayoutSupportEntry {
layout: OBJECT_LAYOUT_PACKED_SMALL_OBJECTS,
native_support: false,
semantic_parity: "No packed container, offset index, or compaction semantics are claimed.",
write_path: "packed small-object writes are out of the current runtime boundary.",
read_path: "packed small-object reads are out of the current runtime boundary.",
failure_mode: "Packed small-object layout selection is rejected as unsupported.",
caveat: "Packed small-object support needs container index and compaction proof.",
},
ObjectLayoutSupportEntry {
layout: OBJECT_LAYOUT_APPEND_ONLY_SEGMENTS,
native_support: false,
semantic_parity: "No append-only object segment log or segment cleaner semantics are claimed.",
write_path: "append-only segment writes are out of the current runtime boundary.",
read_path: "append-only segment reads are out of the current runtime boundary.",
failure_mode: "Append-only segment layout selection is rejected as unsupported.",
caveat: "Append-only segment support needs segment index and recovery proof.",
},
],
}
}
pub fn ensure_object_layout_supported(&self, layout: &str) -> Result<(), RuntimeError> {
let report = self.object_layout_support_report();
if report.supported_layouts.contains(&layout) {
Ok(())
} else {
Err(RuntimeError::UnsupportedObjectLayout(layout.to_string()))
}
}
pub fn validate_object_layout_policy(
&self,
policy: &ObjectLayoutPolicy,
) -> Result<(), RuntimeError> {
self.ensure_object_layout_supported(&policy.layout)?;
if policy.stripe_width.is_some_and(|width| width > 1) {
return Err(RuntimeError::InvalidObjectLayoutPolicy(
"striped object layout is outside the current layout boundary".to_string(),
));
}
if policy.pack_small_objects {
return Err(RuntimeError::InvalidObjectLayoutPolicy(
"packed small-object layout is outside the current layout boundary".to_string(),
));
}
if policy.append_only_segments {
return Err(RuntimeError::InvalidObjectLayoutPolicy(
"append-only segment layout is outside the current layout boundary".to_string(),
));
}
if matches!(policy.layout.as_str(), OBJECT_LAYOUT_CHUNKED)
&& policy.chunk_size_bytes.is_some_and(|bytes| bytes == 0)
{
return Err(RuntimeError::InvalidObjectLayoutPolicy(
"chunked object layout requires a nonzero chunk size".to_string(),
));
}
Ok(())
}
}