Provider / remote object storage

Validated

AWS S3

AWS S3 is a first-class block provider using the actual AWS region and the standard AWS workload credential chain. It is qualified through a private bucket and prefix-scoped role; the provider does not silently treat an S3-compatible endpoint as AWS evidence.

Metadata

The current object adapter is block-only. Use an independently selected metadata provider for namespace, revisions, leases, and chunk references; do not put metadata in a shared S3 listing and infer CAS.

Immutable blocks

The layout is an owned prefix containing one immutable object per fixed-size chunk, inspected through S3 GET/HEAD/LIST and ranged reads. Conditional create, ETag CAS, and cleanup are verified against the actual AWS endpoint by the W25 gate. The S3 gateway's streaming PUT and multipart completion paths stage under private.mountx-put-... keys and publish with atomic rename; staging entries are hidden from ordinary listings.

Storage anatomy

Follow one file through both planes.

A mount-rs namespace stores names, attributes, directory entries, layouts, and block references. The bytes stay in the independent block plane. The example below is illustrative; the provider-specific schema, keys, and prefixes are the inspectable contract.

Logical file/docs/readme.mdinode 42 · size 8,192NodeMetadata → NodeData::File(FileLayout)
blocksS3 objects under an owned prefixBlockId → raw bytes
Illustrative Namespace / FileLayout record (shape, not serialized bytes)
Namespace {
  nodes[42] = NodeMetadata {
    stats: { ino: 42, size: 8192, mode: regular },
    data: File(FileLayout {
      chunker: { algorithm: "fixed-size", version: 1, chunk_size: 4096 },
      extents: [
        { file_offset: 0,    block: "b012...", block_offset: 0, length: 4096 },
        { file_offset: 4096, block: "bfed...", block_offset: 0, length: 4096 }
      ]
    })
  }
}

BlockId "b012..." -> [4 KiB raw bytes]
BlockId "bfed..."  -> [4 KiB raw bytes]

Object storage

AWS S3 bucket prefix map

block-only bucket

The planned AWS path follows the same block-only shape, but the repository has not yet accepted the AWS-specific integration and failure matrix.

Bucketmount-rs-integration-…
mount-rs-integration-…/
└─mount-rs-tests/owned-run/
├─b0123456789abcdef0123456789abcdef
└─bfedcba9876543210fedcba987654321
selected relational/KV provider

Stores the namespace and the references that make each object part of a file.

blocksS3 objects under an owned prefix

Stores only raw bytes at exact keys. LIST shows a prefix; it does not reveal a directory tree.

mount-rs-tests/test namespace

logical LIST prefix; not a directory

mount-rs-tests/owned-run/owned prefix

unique cleanup boundary

mount-rs-tests/owned-run/b0123456789abcdef0123456789abcdefplanned block key

intended raw block object

mount-rs-tests/owned-run/bfedcba9876543210fedcba987654321planned block key

intended raw block object

What the key does not tell you

These keys document the intended layout, not completed AWS acceptance. Do not infer a passing AWS backend from R2 or RustFS results. The file name, inode, offsets, and chunk layout are not encoded in the object key; inspect the metadata plane to map them.

Validated — scoped evidence

The first-class Rust SDK/CLI AWS S3 block provider passed the live myroot private-bucket gate with a prefix-scoped assumed role, composed SQLite metadata, process reopen, and owned-prefix cleanup. The repository now also defines an operations runbook and optional S3Session::stats() telemetry boundary; production identity rotation, metadata ownership, recovery drills, collectors/alerts, canary/rollback, and hosted release gates remain separate. The 2026-09-21 W25 gate used the privatemyroot bucket in ap-southeast-2 and a short-lived prefix-scoped role. It passed the Rust SDK and Rust CLI public configuration paths, immutable create and duplicate rejection, byte ranges, stale conditional/CAS rejection, current-ETag CAS, a 65,537-byte boundary read, four concurrent writers, multi-chunk overwrite/truncate/extend/sparse-tail behavior, fresh-process reopen, and owner-verified cleanup with zero remaining objects. Cloudflare R2 and RustFS results remain separate providers. Separately, the 2026-09-21 S3 gateway hardening sequence added bounded staged PUT, multipart completion, and cross-driver CopyObject publication, with existing-object preservation on integrity/read failure. That is implementation and rootless gateway-test evidence, not a new hosted AWS durability or release-qualification claim. The current local S3/N-API packet also covers streamed async-iterable and ReadableStream bodies, typed peer-fault callbacks, cancellation-safe private staging, replacement-session multipart completion, and native-filesystem process-restart recovery. The replacement-session and restart checks preserve the boundary between local filesystem evidence and live AWS durability; neither promotes these results to hosted or power-loss acceptance. The companion operations runbook defines provider/reconciliation/identity/capacity signals, redaction boundaries, and O01–O08 drills, including identity expiry, conditional conflicts, throttling, metadata outage, restore, schema migration, cleanup/retention, and canary/rollback. It explicitly keeps production collector and alert routing, workload-identity rotation, approved metadata ownership, staging drills, canary, rollback, and post-deploy smoke open. The latest hosted qualification run35629600687 at 62383df passed provenance and the four synthetic contract suites, then failed closed atAWS_S3_CI_CONFIG_BLOCKED missing_bucket before AWS authentication; its retained artifact isaws-s3-qualification-35629600687-1. It does not close AWS identity or production acceptance. A newer hosted safety-preflight run35635498647 at 24408f8 also stopped before authentication with AWS_S3_CI_CONFIG_BLOCKED missing_bucket; protected bucket, region, account, versioning, and role inputs were blank. This is a current configuration refusal, not a provider failure or acceptance result. The latest authorized qualification at pushed source 870348184b5a047faea01f584a68cb961b34f810passed sibling-prefix denial, the public SDK/CLI self-test, composed AWS S3 filesystem, process reopen, independent PGlite metadata, writer fencing, PGlite backup/restore, fresh-server reopen, and exact owned-prefix cleanup, emitting AWS_S3_TEST_PASS andAWS_S3_PGLITE_TEST_PASS. This refreshes qualification- account evidence only; production metadata ownership, identity, recovery, and operational sign-off remain open. The current sealed W25 source scan reported zero reportable findings across its six scoped surfaces, with the rest of the repository and live AWS/GitHub state explicitly deferred. The latest read-only OIDC audit at source9b5acfbac3d88d5f17a969defd447f5d44ee3023 remained fail-closed for missing environment protection, protected inputs, GitHub OIDC provider, and immutable-subject role trust; it made no changes. The latest qualification-bucket audit repeated the account, region, public-access, ownership, encryption, versioning, lifecycle, and multipart-abort controls without mutating AWS. These are useful rollout controls, not production resource or identity approval. The newer provider-workflow admission run 35669918721 atc2df980 passed trigger coverage and static contracts but failed closed before AWS authentication atAWS_S3_CI_CONFIG_BLOCKED missing_bucket. The localprocess.abort() multipart restart check is native-filesystem evidence only; neither result changes the live AWS or power-loss acceptance boundary. The latest admission35693941024 at published source fcf1d547reached the same protected-config validator and stopped atAWS_S3_CI_CONFIG_BLOCKED missing_bucket before AWS authentication. No live AWS service PASS is claimable until the protected bucket, region, account, versioning, and OIDC role inputs are provisioned. The current shared-mainline qualification at source0d017f09 passed the authorized myroot and dedicated-role packet: sibling-prefix denial, public SDK/CLI self-test, composed AWS S3 filesystem, process reopen, independent PGlite metadata, writer fencing, PGlite backup/restore, fresh-server reopen, and exact owned-prefix cleanup all passed, emittingAWS_S3_TEST_PASS andAWS_S3_PGLITE_TEST_PASS. This refreshes qualification-account and local-metadata evidence only; production resource, metadata, DR, hosted-release, and operational gates remain open. The subsequent hosted admission run35712627727 at source ff5cc581 passed trigger, provenance, and contract checks but failed closed before AWS authentication at AWS_S3_CI_CONFIG_BLOCKED missing_bucket; credentialed acceptance steps were skipped. This is a configuration blocker, not an AWS provider failure or acceptance result.

Layout and chunking

ChunkedFs selects the chunk size and the metadata provider records object IDs. A remote object key is not a filesystem path and is not safe to delete unless the owning metadata revision has been reconciled.

Durability and consistency

S3's service durability and visibility behavior belong to the selected AWS deployment. The adapter uses signed requests, create-only immutable publication, conditional updates, completed upload barriers, and a durable-driver syncfs acknowledgment whendurable_writes is enabled. Streaming PUT, multipart completion, and CopyObject use bounded staging with read_chunk_bytes, so a failed integrity check or source read does not replace an existing destination before the final rename. Multi-writer scope and metadata-provider durability still belong to the selected deployment.

Across every split-store composition, new blocks are flushed before metadata references are published. A provider acknowledgement is not automatically a power-loss or distributed-locking guarantee.

Inspect an AWS-owned prefix without exposing credentials

Read-only inspection example
export AWS_REGION='ap-southeast-2'
export AWS_S3_BUCKET='private-bucket'
export AWS_S3_PREFIX='mount-rs/volume-a'

aws s3api list-objects-v2 --bucket "$AWS_S3_BUCKET"   --prefix "$AWS_S3_PREFIX/"
aws s3api head-object --bucket "$AWS_S3_BUCKET"   --key "$AWS_S3_PREFIX/<block-id>"
aws s3api get-object --bucket "$AWS_S3_BUCKET"   --key "$AWS_S3_PREFIX/<block-id>" --range bytes=0-63 /tmp/block-prefix.bin

Credentials, cleanup, and safe operations

Use the private test bucket, a least-privilege role/profile, and a unique prefix with a retention rule. Never put access keys in the repository or page examples. Delete only objects under the owned prefix after the test has closed all clients.

Current limits

AWS S3 is block-only: choose an independent metadata provider, and do not infer multi-writer or power-loss guarantees from the SQLite test composition. Production deployments still need explicit metadata durability, backup/restore, monitoring, cost/retention, and hosted release qualification. The companion operations runbook is a handoff and drill contract, not proof that those production gates have passed. The bounded publication path requires a driver with atomic_rename; unsupported drivers return an explicitNotImplemented response rather than falling back to a weaker direct write. Use the AWS workload identity chain rather than committing long-lived access keys.

← Back to providers