Skip to content

feat(migrate-tool): add track migration tool#14392

Merged
dylanjeffers merged 4 commits into
mainfrom
feat/migrate-tool
Jun 18, 2026
Merged

feat(migrate-tool): add track migration tool#14392
dylanjeffers merged 4 commits into
mainfrom
feat/migrate-tool

Conversation

@dylanjeffers

Copy link
Copy Markdown
Contributor

Summary

A small Vite + React SPA + Vercel-functions tool that helps artists move tracks from an old Audius account they've lost access to onto a new account they control. Intended to live at migrate.audius.co.

  • Located at packages/migrate-tool.
  • Frontend: PKCE OAuth (SDK with apiKey only). User signs in with new account, enters old handle, previews the tracks, submits.
  • Backend (Vercel functions + Supabase): stores requests in a migration_requests table, exposes admin endpoints gated by ADMIN_BEARER_TOKEN.
  • Migration worker: on approval, the backend SDK (initialized with apiKey + bearerToken via createSdkWithServices) fetches each old track's audio + artwork and re-uploads it as the new owner using the OAuth grant. Per-track results are written back to the DB.

Approval flow

The README is explicit that identity verification of the requester happens out-of-band (support ticket, Discord DM, etc.). The admin step in this tool is just a gate so nothing executes automatically; the team is responsible for confirming ownership before they click "Approve & execute."

Known limitations (documented in the README)

  • Tracks marked downloadable migrate with the original audio file; everything else migrates with the transcoded MP3 stream. The original master file isn't accessible via the public API for non-downloadable tracks.
  • Old account is not modified; plays / favorites / reposts / comments don't carry over.
  • The admin "approve" handler runs the migration synchronously with maxDuration: 300 set in vercel.json. For artists with many tracks this should be moved to a queue/cron worker.

Verification

  • npx tsc -b passes for the SPA and the API functions (no type errors).
  • vite build was not verified locally — there's a pre-existing vite-plugin-node-polyfills resolver issue in this worktree's install that also breaks packages/web/examples/upload, so it isn't specific to this change. A fresh install on Vercel should build cleanly.

Test plan

  • Provision a Supabase project, run supabase/migrations/0001_init.sql.
  • Create an Audius developer app, set VITE_AUDIUS_API_KEY, AUDIUS_API_KEY, AUDIUS_BEARER_TOKEN, ADMIN_BEARER_TOKEN, SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY.
  • npm run dev + sign in with a test account, enter another artist's handle, preview shows tracks.
  • Submit a request and verify the row appears in Supabase with status = 'pending'.
  • Open /admin, unlock with ADMIN_BEARER_TOKEN, click Reject — confirm status flips to rejected.
  • Submit a second request, click Approve & execute, confirm tracks re-appear on the new account and per-track results are written back.

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented May 22, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a57e0ab

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions

github-actions Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

🌐 Web preview ready

Preview URL: https://audius-web-preview-pr-14392.audius.workers.dev

Unique preview for this PR (deployed from this branch).
Workflow run

dylanjeffers and others added 2 commits May 26, 2026 17:23
A small Vite + React SPA backed by Vercel functions + Supabase that lets an
artist request migration of tracks from an old Audius account they've lost
access to onto a new account they control. Every migration sits in a
pending queue until an Audius team member approves it via an admin route
gated by a bearer token — the README spells out that identity
verification of the requester has to happen out-of-band.

The frontend uses the SDK's PKCE OAuth flow with apiKey only; on approval
the backend re-uploads each track via createSdkWithServices using the
dev app's API key + bearer token, acting on behalf of the new owner.

Designed for migrate.audius.co.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Audio source resolution now walks a prioritized candidate list per track
(raw orig_file_cid → CID mirror → gated download URL → transcoded mp3
stream), trying each until one fetch succeeds. Original masters now flow
through for every indexed track that still has its bytes on the network,
not just the ones the artist toggled downloadable. The stream fallback
guarantees every approved request migrates at least the lossy mp3 so a
single pruned original never aborts the run. Preview UI relabeled to
"mp3 only" for the rare tracks where no original is on file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the static ADMIN_BEARER_TOKEN unlock in the admin UI with Google
sign-in restricted to @audius.co / @audius.org accounts, mirroring the
notifications-dashboard auth pattern.

- api/_lib/auth.ts: add isAudiusEmail, jose-signed session JWT helpers,
  httpOnly session cookie, and upgrade requireAdmin to accept a valid
  staff session cookie OR the existing ADMIN_BEARER_TOKEN (now an optional
  escape hatch for programmatic access).
- api/auth/{index,session,logout}.ts: verify Google ID token via
  google-auth-library, enforce the Audius-domain check, mint/clear session.
- admin endpoints (requests/approve/reject) now await requireAdmin.
- Admin.tsx: Google sign-in + session restore + sign out; admin calls use
  the session cookie (credentials: 'include') instead of a bearer header.
- config/vite-env: VITE_GOOGLE_CLIENT_ID. Document GOOGLE_CLIENT_ID and
  AUTH_SESSION_SECRET in .env.example and README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@socket-security

Copy link
Copy Markdown

Dependency limit exceeded — report not shown.

This pull request scan exceeded the 10,000-dependency limit applied to this scan, so the results are incomplete and may be inaccurate. To avoid reporting false positives, Socket has not posted a report.

Upgrade your plan to raise the dependency limit and get complete reports, or view the partial scan in the dashboard.

Socket is always free for open source. If this is a non-commercial open source project, contact us to request a free Team account.

…isting

migrate-tool used ^0.23.0 while distro/embed pin 0.17.0, which npm hoists to
the root. The injected `vite-plugin-node-polyfills/shims/process` import then
resolved against the shadowing 0.17.0 (which only exports `./shims/banner`),
breaking `vite build` in the monorepo. Aligning migrate-tool to 0.17.0 dedupes
to the single hoisted copy so plugin code and resolved package match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dylanjeffers dylanjeffers merged commit 0ce8f03 into main Jun 18, 2026
7 checks passed
@dylanjeffers dylanjeffers deleted the feat/migrate-tool branch June 18, 2026 03:39
dylanjeffers added a commit that referenced this pull request Jun 18, 2026
…ead of bearer token (#14496)

## Summary

Follow-up to #14392. Switches the migrate-tool's server-side SDK
initialization from a bearer token to `apiKey` + `apiSecret` (Basic
auth), which is cleaner for app-level server-side operations.

The SDK's EntityManager relay call in `manageEntity` accepts either
`Authorization: Bearer <bearerToken>` or `Basic
base64(apiKey:apiSecret)`. Using `apiKey`+`apiSecret` lets the developer
app authenticate and sign its own requests server-side without an
OAuth-derived bearer token.

## Changes

- `api/_lib/audius.ts` — `getServerSDK()` now reads `AUDIUS_API_SECRET`
and passes `apiSecret` to `createSdkWithServices` instead of
`bearerToken`. Updated error message and doc comment.
- `.env.example` — `AUDIUS_BEARER_TOKEN` → `AUDIUS_API_SECRET`.
- `README.md` — env var documentation updated to reference the API
Secret.

The unrelated `ADMIN_BEARER_TOKEN` escape hatch for admin endpoints is
untouched.

## Verification

- `tsc -b` passes.
- `vite build` passes (polyfill issue resolved by the
vite-plugin-node-polyfills 0.17.0 pin from #14392).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant