refactor(api): replace Arweave uploads with Supabase public bucket (phase 1)
Summary
Phase 1 of the Arweave→Supabase upload migration. Removes every Arweave write code path in api (Arweave wallet has been broken in production: every real upload returns "Transaction verification failed") and rewires each consumer to a new public Supabase bucket. The POST /api/upload wire contract stays byte-identical so the chat-side cutover (recoupable/chat#1718) needs no changes other than allowing the new image hostname in next.config.mjs.
Storage paths are flat opaque UUIDs at the bucket root — no scope encoding, no path semantics. Phase-2 access control will resolve through the parent resource that references the file (chat / account / artist).
Out of scope (deferred to phase 2): Bearer auth, signed URLs, private buckets, files-table changes, LLM-context URL rewriting, rate limiting.
Plan: PHASE_1_UPLOAD_MIGRATION_PLAN.md in the monorepo root.
Bucket-creation migration: recoupable/database#23 — must land before this PR.
What changes
Adds
lib/supabase/storage/getPublicUrlByKey.tslib/files/uploadDataToPublicBucket.ts(unified helper)lib/files/uploadFileHandler.ts(POST /api/upload)lib/files/mirrorUrlToPublicBucket.ts(replacesuploadLinkToArweave)lib/networking/isSafeHttpUrl.ts(moved fromlib/arweave/)lib/image/uploadImageAndCreateMoment.ts(moved + Supabase swap)- 3 new constants in
lib/const.ts:SUPABASE_PUBLIC_UPLOADS_BUCKET,MAX_UPLOAD_BYTES,SUPPORTED_UPLOAD_MIME
Rewires (Arweave → Supabase via uploadDataToPublicBucket)
/api/upload,/api/x402/image/generatehandleInstagramProfileScraperResults(apify webhook)createImageMoment,generateAndStoreTxtFile,createKnowledgeBase,generateAndProcessImage,registerGenerateTxtFileTool
Removes
lib/arweave/upload*.ts(all upload helpers)lib/arweave/client.ts(no consumers after upload helpers)lib/arweave/isSafeHttpUrl.ts(moved)arweavenpm dep
Read-side helpers (getFetchableUrl, arweaveGatewayUrl, IPFS utilities) stay — still needed for legacy URLs in DB/messages.
Test plan
-
pnpm test— 2476/2476 passing (15 new tests covering the new helpers) -
pnpm lint:checkclean -
pnpm format:checkclean - After database PR #23 lands: smoke
curl -F file=@x.png $PREVIEW/api/uploadreturns 200 withhttps://*.supabase.co/.../<uuid>.png - Verify the URL fetches with 200 + correct
content-type+cache-control: max-age=31536000 - Per-feature sanity: trigger apify Instagram webhook, image generation, knowledge-base save, txt-file tool — all return Supabase URLs
- Chat preview (#1718): drag-drop a PNG; image renders end-to-end
Summary by CodeRabbit
-
New Features
- Added a new file upload API endpoint with CORS support for uploading files to cloud storage.
-
Refactor
- Migrated image storage from decentralized to cloud-based infrastructure for improved reliability and performance.
- Updated image generation and knowledge base creation to use cloud storage instead of previous storage method.
- Updated Instagram profile data processing to use cloud storage infrastructure.