Storage Capabilities

Copy Markdown View Source

Rindle exposes storage capabilities as an explicit adapter contract so adopters can tell which upload and delivery flows are expected to work before wiring a profile to a backend. Unsupported flows fail with tagged tuples instead of falling back silently.

This guide is the canonical capability reference for v1.1. Other guides link here instead of repeating provider matrices inline.

Shipped Capability Vocabulary

Rindle currently knows these capability atoms:

CapabilityMeaning today
:presigned_putThe adapter can mint a direct-upload URL for a single-object PUT.
:multipart_uploadThe adapter can initiate, sign parts for, complete, and abort an S3-style multipart upload.
:signed_urlThe adapter can mint a time-limited signed delivery URL for private delivery.
:headThe adapter can read remote object metadata for verification and cleanup.
:localThe adapter is backed by local filesystem semantics.
:resumable_uploadThe adapter can drive a resumable upload lifecycle instead of a single-shot direct PUT.
:resumable_upload_sessionThe adapter can create and continue provider-owned resumable upload sessions.

These atoms are shipped vocabulary, but adapter-specific. Rindle does not imply that every storage backend supports them.

Unsupported Flow Contract

Rindle uses tagged unsupported tuples when a flow requires a capability the adapter does not advertise:

Flow familyTagged error
Upload{:error, {:upload_unsupported, capability}}
Delivery{:error, {:delivery_unsupported, capability}}

Examples:

  • Rindle.Storage.Local returns {:error, {:upload_unsupported, :multipart_upload}} for multipart entrypoints.
  • Private delivery against an adapter without :signed_url returns {:error, {:delivery_unsupported, :signed_url}}.
  • A resumable path against an adapter that does not advertise it remains intentionally explicit: {:error, {:upload_unsupported, :resumable_upload}}.

These failures are part of the adopter-facing contract. Rindle does not guess, downgrade, or silently swap in another flow.

Provider Matrix

The table below describes the current v1.1 posture for adapters and common provider choices.

Backend / providerRuntime seamExpected capabilities todayProof postureNotes
Local filesystemRindle.Storage.Local[:local, :presigned_put]Automated in the default test suitePresigned PUT is a local-development parity shim, not a remote-object-store claim. Rindle.Storage.Local does not advertise :resumable_upload or :resumable_upload_session.
MinIORindle.Storage.S3[:presigned_put, :head, :signed_url, :multipart_upload]Automated in default CI and local integration lanesThis is the always-on real S3-compatible proof for direct PUT, multipart upload, metadata verification, and signed delivery URL generation. Rindle.Storage.S3 does not advertise the resumable capability family.
Generic S3-compatible providerRindle.Storage.S3[:presigned_put, :head, :signed_url, :multipart_upload]Expected by contract; not proven against every vendor in default CIRindle uses the shipped S3 adapter seam. Provider-specific behavior beyond that seam should be validated in adopter-owned environments.
Cloudflare R2Rindle.Storage.S3[:presigned_put, :head, :signed_url, :multipart_upload] when the provider honors the shipped S3-compatible operationsDocumented compatibility target; adopters validate vendor behavior in their own environmentsPhase 8 does not add a bespoke R2 adapter. The repo only claims the current shipped S3-style operations it can exercise through the existing adapter seam, with MinIO as the automated proof lane.
Google Cloud StorageRindle.Storage.GCS[:head, :signed_url, :resumable_upload, :resumable_upload_session]Live GCS proof exists in the GCS test lanes; adopters still own bucket and browser wiringRindle.Storage.GCS is the shipped adapter that honestly advertises the resumable capability family. See storage_gcs.md for runtime wiring, CORS, and session hygiene.

Proof Boundaries

Rindle separates "documented contract" from "what the repo proves by default":

  • MinIO is the default real-provider proof lane in CI for the shipped S3 adapter contract.
  • Cloudflare R2 is documented as a compatibility target through the shipped Rindle.Storage.S3 seam.
  • Default CI proves the shipped S3-style contract against MinIO, not against every vendor-branded backend.
  • Generic S3 providers are expected to match the shipped S3 adapter contract, but adopters should still validate vendor-specific behavior in their own environments before rollout.

That distinction matters: Phase 8 improves auditability, not marketing claims. This guide does not imply provider-specific live R2 proof in CI.

Adapter Honesty

Capability claims are adapter-specific, not marketing-wide:

  • Rindle.Storage.GCS advertises :resumable_upload and :resumable_upload_session
  • Rindle.Storage.S3 advertises neither resumable capability today
  • Rindle.Storage.Local advertises neither resumable capability today
  • custom adapters may honestly advertise either, both, or neither depending on what they actually implement

Rindle does not silently downgrade resumable requests into presigned PUT.

Cloudflare R2 Boundary

Cloudflare R2 is documented here as an S3-compatible provider path through the existing Rindle.Storage.S3 adapter. In v1.1, the supported Rindle contract is:

  • Direct upload via presigned PUT.
  • Metadata verification via head/2.
  • Signed delivery URL generation when :signed_url is advertised.
  • S3-style multipart upload when :multipart_upload is advertised.

This guide does not claim:

  • A bespoke Rindle.Storage.R2 adapter.
  • HTML form POST uploads as part of the shipped contract.
  • Provider-specific live R2 coverage in CI.
  • A shipped resumable-upload API through the S3 adapter.

Resumable Boundary

Resumable upload is shipped where the adapter advertises it. Today that means Rindle.Storage.GCS.

That does not mean:

  • every adapter supports resumable upload
  • Rindle falls back automatically from resumable upload to presigned PUT
  • S3-compatible providers inherit resumable semantics through Rindle.Storage.S3
  • Rindle ships tus or a provider-agnostic resumable abstraction beyond the honest capability contract