ADR-0006: Cloudflare R2 for R-Plan Pass 4.C photo storage; AWS SDK v3…
Decision
ADR-0006: Cloudflare R2 for R-Plan Pass 4.C photo storage; AWS SDK v3 client (S3-compatible, swap to S3/B2/MinIO is config-only). Inert-wired in v1 — code reads R2_* env vars; if missing, photo upload feature-flags off and form falls back to URL text input. Presigned-URL upload pattern with assertCanWriteActivityProgress gating; bucket key progress/{activityId}/{clientId}.{ext}. Offline path: photo stored as Blob next to queued progress entry, uploaded on reconnect before entry submission.
Rationale
ST decision_matrix (session 83dcbaa5): R2 4.68 / B2 3.91 / MinIO-VPS 3.68 / S3 3.41 weighted. Egress is dominant cost driver (planners re-read photos repeatedly during variance review + audit + EV dashboards) — R2’s zero-egress is structurally winning at our read pattern. R2 free tier 10GB storage + 1M Class A + 10M Class B ops covers year-1 pilot. S3-API portability via @aws-sdk/client-s3 means swap path is rclone + env-var change, well-trodden.
Alternatives Rejected
Outcome
Pending