S3-compatible storage
S3-compatible object storage with explicit per-provider qualification limits..
ROM-extras reuses the published rom_blob_object_store::Adapter::s3 constructor.
It adds no copy of ROM's provider or BlobService implementation.
SeaweedFS 4.48 and RustFS 1.0.1 have separate local fixture evidence. Neither is an Amazon S3 cloud test.
Fixture profiles
| Profile | Fixed endpoint | Persistence and limits | Qualification |
|---|---|---|---|
| seaweedfs | http://127.0.0.1:55455 | Named volume, one CPU, 512 MiB | Strict burst fails with Unknown |
| rustfs | http://127.0.0.1:55456 | Dedicated data/log directories, one CPU, 1 GiB | Four public-port tests pass, including strict burst |
SeaweedFS facts and RustFS facts identify the fixed images and actual configuration.
RustFS follows its documented testing memory minimum; the hardware limits differ between these profiles.
Both publish only a loopback S3 port. Generated credentials remain in ignored mode-600 files.
Both use the dedicated unversioned rom-extras bucket and region us-east-1.
SeaweedFS admin UI and WebDAV are disabled. RustFS console is disabled.
These single-node fixtures have no disk quota, redundancy, or production topology claim.
The adapter fixes path-style addressing, conditional create, zero SDK retries, and a three-second request timeout. This does not disable every lower transport retry; the fault scenario counts actual forwarded PUT requests. Its connect timeout is one second. The configured object limit is 16 bytes for port conformance and 1024 bytes for lifecycle tests. See the pinned public configuration.
Results and qualification status
| Scenario | SeaweedFS | RustFS |
|---|---|---|
| Published blob contract, including two-way create arbitration | Passed | Passed |
| Wrong secret denied; correct account verifies no created object | Passed | Passed |
| Acknowledged false bytes and conflict behavior after server restart | Passed | Passed |
| Eight concurrent creates with outcome classification and explicit reconciliation | Passed; recorded Unknown outcomes | Passed; does not require an Unknown outcome |
| Sixteen fresh keys with eight simultaneous creates each; one acknowledged winner and seven conflicts | Failed with Unknown | Passed |
| BlobService staging, private reads, detachment, and native SQLite/redb reopen | Passed | Passed |
| Deleted reservation after physical publication, retained Unattached receipt, and native reopen | Passed | Passed |
| Lost HTTP success response, unchanged Pending, explicit verified retry, and SQLite/redb Ready reopen | Not executed | Passed |
The strict test reads each winner's bytes, verifies subsequent Conflict without overwrite, and deletes only after all outcomes are confirmed. The separate reconciliation test permits Unknown and retains bytes without cleanup. It checks that a confirmed-conflict candidate cannot be the stored winner. A passing run without an injected fault does not prove actual lost acknowledgement recovery.
SeaweedFS native diagnostics found typed HTTP timeouts near three seconds. A separate verbose reproduction confirms distributed lock use despite prior S3 owner-ring delivery. Exact source also locks recovery after routed precondition rejection; individual request attribution remains limited. See the recovery-path assessment. The strict failure does not prove create-only correctness is broken. No outcome is relabelled to make it pass.
Run one exact profile
Set the five private ROM_EXTRAS_S3 variables for the dedicated fixture, then select its matching profile:
ROM_EXTRAS_S3_PROFILE=rustfs ./scripts/check-s3 Use seaweedfs to reproduce the retained SeaweedFS profile.
An unset profile preserves the previous SeaweedFS selection. Unknown profiles and mismatched endpoints fail before provider access.
Restart tests verify the selected container's fixture label before issuing restart.
The required s3-lifecycle feature runs all four port cases, two shared native BlobService cases, and actual HTTP response-loss recovery, plus Clippy.
The public constructor and strict scenario remain identical.
check-all runs S3 qualification for the configured profile. Selecting RustFS does not establish SeaweedFS qualification.
See SeaweedFS evidence and RustFS evidence.
Remaining work
Garage 2.4.1 source review finds no conditional-create enforcement in its inspected PUT path. RustFS passes local public-port qualification, basic native lifecycle, and one injected HTTP response-loss profile. SeaweedFS remains unqualified for the strict operational profile. Basic native BlobService lifecycle now passes through the same scenario functions used for Azure. See shared lifecycle evidence. RustFS response-loss evidence is recorded in the wire-fault report. The proxy observes backend success before dropping the client response; explicit retry verifies existing bytes before attachment. Corrupt provider reads, current revocation during I/O, cancellation/drain faults, verified TLS, cloud authorization, and packaged release remain pending. Use the public BlobService for lifecycle work. Preserve trusted cleanup requirements for detachment, grace, and quiescence. Other S3-compatible services require their own versioned conformance; these fixtures do not certify them.