Implement the S3 storage backend #41
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Storage is already behind an abstraction with a local filesystem implementation. The
Phase 4 acceptance criterion is that swapping storage backends requires no core
application logic change — this issue is the test of whether that abstraction actually holds.
Scope
An S3-compatible storage backend selectable by configuration.
Implementation notes
accommodate object storage, that is a finding worth noting — but core services must not
learn anything about S3.
backend — but presigned URLs bypass the app's authorization checks, so their expiry must
be short and the generation path must verify the requesting user may see that photo.
eventual consistency, and throttling. Retry with backoff.
every object arrived intact before anything local is removed.
Done when
References
backend/app/services/storage.pydocs/circa-spec.mdPhase 4 acceptance criteriaAmended by the audit of 2026-07-28.
This issue will collide with the storage interface as designed.
StorageBackend.get_path(key) -> Pathmeans "return a filesystem path the caller reads directly" (consumed byFileResponse), andS3 cannot honour that without downloading every object to a temp file.
So the v0.6.0 exit criterion — "swapping storage backends requires no core application logic
change" — fails at the interface, not the implementation.
#90 changes the read contract to
open(key) -> BinaryIOplus an optionalpublic_url(key)forpresigned redirects, while there is one implementation and two call sites. It should land well
before this issue.
Note also that presigned URLs bypass the app's authorization checks, so their expiry must be short
and the generating path must verify the requester may see that photo.