use bucketwarden_lock::{ObjectLock, RetentionMode};
use bucketwarden_s3::{ObjectMetadata, PutObjectRequest};
use bucketwarden_server::{BucketWarden, RuntimeConfig, RuntimeError};
#[test]
fn certified_runtime_slice_exercises_public_crate_surface() {
let mut runtime = BucketWarden::new(RuntimeConfig::development()).expect("runtime");
runtime.allow("operator", "s3:*", "*");
runtime
.create_bucket("operator", "archive-001")
.expect("bucket");
let put = runtime
.put_object(
"operator",
PutObjectRequest {
bucket: "archive-001".to_string(),
key: "records/report.json".to_string(),
body: br#"{"ok":true}"#.to_vec(),
metadata: ObjectMetadata::default(),
},
ObjectLock::none(),
)
.expect("put object");
let got = runtime
.get_object("operator", "archive-001", "records/report.json")
.expect("get object");
runtime
.set_retention(
"operator",
"archive-001",
"records/report.json",
RetentionMode::Governance,
3600,
false,
)
.expect("retention");
let denied = runtime
.delete_object("operator", "archive-001", "records/report.json", false)
.expect_err("retention denies delete");
let deleted = runtime
.delete_object("operator", "archive-001", "records/report.json", true)
.expect("governance bypass delete");
assert_eq!(put.version_id, "v1");
assert_eq!(got.body, br#"{"ok":true}"#);
assert!(matches!(
denied,
RuntimeError::ObjectLocked(bucketwarden_lock::LockError::GovernanceRetentionActive { .. })
));
assert_eq!(deleted.delete_marker_version_id, "v2");
assert_eq!(runtime.replication_records().len(), 2);
assert!(runtime.audit_events().iter().any(|event| {
event.outcome == bucketwarden_audit::AuditOutcome::Denied
&& event.action == "s3:DeleteObject"
}));
}
#[test]
fn certified_runtime_slice_enforces_explicit_deny() {
let mut runtime = BucketWarden::new(RuntimeConfig::development()).expect("runtime");
runtime.allow("operator", "s3:*", "*");
runtime.deny("operator", "s3:DeleteObject", "archive-001/private/*");
runtime
.create_bucket("operator", "archive-001")
.expect("bucket");
runtime
.put_object(
"operator",
PutObjectRequest {
bucket: "archive-001".to_string(),
key: "private/report.json".to_string(),
body: b"private".to_vec(),
metadata: ObjectMetadata::default(),
},
ObjectLock::none(),
)
.expect("put");
let denied = runtime
.delete_object("operator", "archive-001", "private/report.json", true)
.expect_err("explicit deny");
assert!(matches!(
denied,
RuntimeError::AccessDenied {
explicit_deny: true,
..
}
));
}