A ctlplne studio product

ADR: durable browser artifacts use the tenant-bound S3/MinIO store

  • Status: accepted and implemented
  • Decision date: 2026-08-09
  • Approver: founder/product owner

Decision, ELI5

The filesystem backend remains the small/local-development option. Durable deployments use probectl's native S3/MinIO-compatible backend. Both sit behind the same objectstore.Store contract and both are wrapped by ForTenant, so a browser worker can name only a relative artifact path while the storage layer prepends the tenant namespace.

The backend is operator-configured and self-hosted. It never discovers a cloud, fetches pricing, or phones home. Remote endpoints require verified HTTPS; static credentials are SigV4-signed through internal/crypto, may be resolved from the existing secret backends, and are never logged or placed in a ConfigMap.

Why this choice

  • S3 semantics cover AWS S3 and self-hosted MinIO without a new Go dependency.
  • The already-shipped tenant wrapper, bounded reads/listing, lifecycle export/erase, and storage router remain the single isolation boundary.
  • The control plane and browser agent use the same backend/prefix configuration, so tenant deletion can inventory and delete the artifacts the agent wrote.
  • Filesystem remains useful for air-gapped single-node/dev installs, but it is no longer presented as the durable scale answer.

Failure policy

Object storage is evidence storage, not test execution. If an upload fails, the browser test still reports its success/failure and logs an artifact-storage error, but publishes no screenshot reference. It never returns a key for an object that was not stored, never falls back into another tenant's prefix, and never includes a partial response body. Listing pagination that does not advance, oversized objects/responses, invalid credentials, plaintext remote endpoints, and non-2xx responses fail closed.

Proof boundary

internal/objectstore/s3_test.go exercises tenant A/B put/list/read/delete, bounded reads, SigV4 headers, configuration rejection, and upstream outage. Existing object-store and browser-fleet tests cover traversal rejection, tenant-prefix routing, silo-prefix routing, and the no-reference-on-upload-error behavior. A real managed-bucket latency/availability receipt belongs to the representative infrastructure wave; it is not invented by this ADR.

Rendered live from github.com/ctlplne/probectl — found a mistake? edit this page.