Add S3-compatible storage backend (B2, MinIO, AWS S3)

Introduces a StorageBackend interface with local filesystem and S3
implementations. The StorageService delegates raw I/O to the backend
while keeping validation, encryption, and URL generation unchanged.

Backend selection is config-driven: set B2_ENDPOINT + B2_KEY_ID +
B2_APP_KEY + B2_BUCKET_NAME for S3 mode, or STORAGE_UPLOAD_DIR for
local mode. STORAGE_USE_SSL=false for in-cluster MinIO (HTTP).

All existing tests pass unchanged — the local backend preserves
identical behavior to the previous direct-filesystem implementation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-03-30 21:31:24 -05:00
parent 34553f3bec
commit 2e10822e5a
8 changed files with 359 additions and 132 deletions

View File

@@ -0,0 +1,21 @@
package services
import "io"
// StorageBackend abstracts where files are physically stored.
// The StorageService handles validation, encryption, and URL generation,
// then delegates raw I/O to the backend.
type StorageBackend interface {
// Write stores data at the given key (e.g., "images/20240101_uuid.jpg").
Write(key string, data []byte) error
// Read returns the raw bytes stored at the given key.
Read(key string) ([]byte, error)
// Delete removes the object at the given key. Returns nil if not found.
Delete(key string) error
// ReadStream returns a reader for the object (used for large files).
// Callers must close the returned ReadCloser.
ReadStream(key string) (io.ReadCloser, error)
}